[comp.sys.m68k] Why does addq.w #n,sp work?

jbwaters@bsu-cs.UUCP (J. Brian Waters) (12/08/88)

I have been looking at the assembly output of a C compiler and am puzzled to 
find that it sometimes uses, for example, the instruction addq.w #8,sp.  
I know that this clears the arguments pushed on the stack for a subroutine
call.  What I do not understand is why it is not a addq.l #8,sp as I thought
the sp was a 32 bit counter.  Why does it use the addq.w form rather then
the addq.l?

-- 
Brian Waters              <backbone>!{iuvax|pur-ee}!bsu-cs!jbwaters
                                          uunet!---/

ben@grace.UUCP (Ben Henwood) (12/09/88)

From postnews Thu Dec  8 08:48:24 1988
In article <5005@bsu-cs.UUCP>, jbwaters@bsu-cs.UUCP (J. Brian Waters) writes:
> 
> I have been looking at the assembly output of a C compiler and am puzzled to 
> find that it sometimes uses, for example, the instruction addq.w #8,sp.  
> I know that this clears the arguments pushed on the stack for a subroutine
> call.  What I do not understand is why it is not a addq.l #8,sp as I thought
> the sp was a 32 bit counter.  Why does it use the addq.w form rather then
> the addq.l?

When an "addq" instruction affects an address register (A7 in this
case), the entire destination address register is used, regardless
of the operation size.

So even though the assembler instruction specifies 16-bits, which
would be a bug, the instruction will use 32-bits since it's dealing
with the SP.

rbrown@svax.cs.cornell.edu (Russell Brown) (12/09/88)

In article <5005@bsu-cs.UUCP> jbwaters@bsu-cs.UUCP (J. Brian Waters) writes:
>
>What I do not understand is why it is not a addq.l #8,sp as I thought
>the sp was a 32 bit counter.  Why does it use the addq.w form rather then
>the addq.l?

According to the entry on ADDQ in the M68000 Programmer's reference manual,
"When adding to address registers, the entire destination address register is
used, regardless of the operation size."  As to why the C compiler you're
using chooses the .w form, I can't say.  It might be a feature, or it might
be that doing it that way made doing something else easier.

Russell G. Brown					Cornell Computer Science

ditto@cbmvax.UUCP (Michael "Ford" Ditto) (12/09/88)

In article <5005@bsu-cs.UUCP> jbwaters@bsu-cs.UUCP (J. Brian Waters) writes:
>  What I do not understand is why it is not a addq.l #8,sp as I thought
>the sp was a 32 bit counter.  Why does it use the addq.w form rather then
>the addq.l?

Under "addq" in the 68020 manual:  "When adding to address registers,
the entire destination address register is used, regardless of the
operation size."  (It should be the same for any 68000-family CPU.)

This is typical of address register operations on the 680x0 ... even a
move.w to an address register is sign-extended to 32-bits and modifies
the whole 32 bits of the destination.
-- 
					-=] Ford [=-

"The number of Unix installations	(In Real Life:  Mike Ditto)
has grown to 10, with more expected."	ford@kenobi.cts.com
- The Unix Programmer's Manual,		...!sdcsvax!crash!elgar!ford
  2nd Edition, June, 1972.		ditto@cbmvax.commodore.com

mikes@oakhill.UUCP (Mike Schultz) (12/09/88)

In article <5005@bsu-cs.UUCP> jbwaters@bsu-cs.UUCP (J. Brian Waters) writes:
>
>I have been looking at the assembly output of a C compiler ...
>.....  What I do not understand is why it is not a addq.l #8,sp as I thought
>the sp was a 32 bit counter.  Why does it use the addq.w form rather then
>the addq.l?

First, as others have pointed out, the immediate word value is sign extended
when dealing with address registers, so it really is adding a 32 bit value 
to the 32 bit register.

Second, the timing tables in appendix F show that the word version of the addq
takes 4 clocks, while the long version takes 8.  I don't know, but I suspect
that the hardware adder is optimized for word adds.

Mike Schultz
..!uunet!cs.utexas.edu!oakhill!mikes

cruff@ncar.ucar.edu (Craig Ruff) (12/09/88)

In article <5460@cbmvax.UUCP> ditto@cbmvax.UUCP (Michael "Ford" Ditto) writes:
>In article <5005@bsu-cs.UUCP> jbwaters@bsu-cs.UUCP (J. Brian Waters) writes:
>>  What I do not understand is why it is not a addq.l #8,sp as I thought
>>the sp was a 32 bit counter.  Why does it use the addq.w form rather then
>>the addq.l?
>
>Under "addq" in the 68020 manual:  "When adding to address registers,
>the entire destination address register is used, regardless of the
>operation size."  (It should be the same for any 68000-family CPU.)

The other reason that everyone seemed to miss is that this method saves
2 bytes.  If you think about it, this instruction is used commonly to
pop arguments off the stack after a function call (for C).  If you have
many function calls, the savings can add up.

Another method some compilers use is to just let the arguments build up
on the stack for a while and pop a whole bunch off in one shot, saving
even more instructions.
-- 
Craig Ruff      NCAR                         INTERNET: cruff@ncar.UCAR.EDU
(303) 497-1211  P.O. Box 3000                   CSNET: cruff@ncar.CSNET
		Boulder, CO  80307               UUCP: cruff@ncar.UUCP

rbrown@svax.cs.cornell.edu (Russell Brown) (12/10/88)

In article <1100@ncar.ucar.edu> cruff@handies.UCAR.EDU (Craig Ruff) writes:
>>
>>Under "addq" in the 68020 manual:  "When adding to address registers,
>>the entire destination address register is used, regardless of the
>>operation size."  (It should be the same for any 68000-family CPU.)
>
>The other reason that everyone seemed to miss is that this method saves
>2 bytes.  If you think about it, this instruction is used commonly to
>pop arguments off the stack after a function call (for C).  If you have
>many function calls, the savings can add up.
>
	Untrue.  The addq instruction has its data in the instruction word.
It can only be used to add values 1 thru 8, so it only needs 3 bits.  That's
why people use it.

Russell G. Brown					Cornell Computer Science

cruff@ncar.ucar.edu (Craig Ruff) (12/10/88)

In article <23329@cornell.UUCP> rbrown@svax.cs.cornell.edu (Russell Brown) writes:
>>The other reason that everyone seemed to miss is that this method saves
>>2 bytes.  ...
 
>	Untrue.  The addq instruction has its data in the instruction word.
>It can only be used to add values 1 thru 8, so it only needs 3 bits.  That's
>why people use it.


No, it is true.  Compare:

	addq.w	#8, a7		(2 bytes)
	add.w	#8, a7		(4 bytes)
	add.l	#8, a7		(6 bytes)

That's also why you'll see values > 8 using add.w instead of add.l.
-- 
Craig Ruff      NCAR                         INTERNET: cruff@ncar.UCAR.EDU
(303) 497-1211  P.O. Box 3000                   CSNET: cruff@ncar.CSNET
		Boulder, CO  80307               UUCP: cruff@ncar.UUCP

guy@auspex.UUCP (Guy Harris) (12/10/88)

>The other reason that everyone seemed to miss is that this method saves
>2 bytes.

People miss it because it's not true.

	addq.w	#8,sp

and

	addq.l	#8,sp

both take two bytes.

However, on the 68010, according to my '010 reference manual, the
"addq.w" takes 4 clocks, and the "addq.l" takes 8.

guy@auspex.UUCP (Guy Harris) (12/11/88)

 >>	Untrue.  The addq instruction has its data in the instruction word.
 >>It can only be used to add values 1 thru 8, so it only needs 3 bits.  That's
 >>why people use it.
 >
 >No, it is true.  Compare:
 >
 >	addq.w	#8, a7		(2 bytes)
 >	add.w	#8, a7		(4 bytes)

No, it is not true.  The statement being referred to is the claim that
"addq.l #8,a7" takes two more bytes than "addq.w #8,a7"; "add.w" and
"add.l" don't enter into it.