The assembly language instructions described in this manual are a superset of the actual machine-code instructions. Generally, the assembly language instructions match the machine-code instructions; however, in some cases the assembly language instructions are macros that generate more than one machine-code instruction (the division instructions in assembly language are examples). This appendix describes the assembly language instructions that generate more than one machine-code instruction.
You can, in most instances, consider the assembly language instructions
as machine-code instructions; however, for routines that require tight coding
for performance reasons, you must be aware of the assembly language instructions
that generate more than one machine-code instruction.
C.1 Implicit Register Use
Register
$28
($at
) is reserved as a temporary register
for use by the assembler.
Some assembly language instructions require additional temporary registers.
For these instructions, the assembler uses one or more of the general-purpose
temporary registers (t0
-
t12
).
The following table lists the instructions that require additional temporary
registers and the specific registers that they use:
Instruction | Registers Used |
ldb |
AT,t9 |
ldbu |
AT,t9
[Footnote 15]
|
ldw |
AT,t9 |
ldwu |
AT,t9
[Footnote 15] |
stb |
AT,t9,t10
[Footnote 15] |
stw |
AT,t9,t10
[Footnote 15] |
ustw |
AT,t9,t10,t11,t12 |
ustl |
AT,t9,t10,t11,t12 |
ustq |
AT,t9,t10,t11,t12 |
uldw |
AT,t9,t10 |
uldwu |
AT,t9,t10 |
uldl |
AT,t9,t10 |
uldq |
AT,t9,t10 |
divl |
AT,t9,t10,t11,t12 |
divq |
AT,t9,t10,t11,t12 |
divlu |
AT,t9,t10,t11,t12 |
divqu |
AT,t9,t10,t11,t12 |
reml |
AT,t9,t10,t11,t12 |
remq |
AT,t9,t10,t11,t12 |
remlu |
AT,t9,t10,t11,t12 |
remqu |
AT,t9,t10,t11,t12 |
The registers that equate to the software names (from
regdef.h
) in the preceding table are as follows:
Software Name | Register |
AT |
$28 or $at |
t9 |
$23 |
t10 |
$24 |
t11 |
$25 |
t12 or pv |
$27 |
Note
The
div
andrem
instructions destroy the contents oft12
only if the third operand is a register other thant12
. See Section C.5 for more details.
If you use an address as an operand and it references a data item
that does not have an absolute address in the range -32768 to 32767, the assembler
may generate a machine-code instruction to load the address of the data (from
the literal address section) into
$at
.
The assembler's
ldgp
(load global pointer) instruction
generates an
lda
and
ldah
instruction.
The assembler requires the
ldgp
instruction because
ldgp
couples relocation information with the instruction.
C.3 Immediate Values
If you use
an immediate value as an operand and the immediate value falls outside the
range -32768 to 32767 for the
ldil
and
ldiq
instructions or the range 0 - 255 for other instructions, multiple machine
instructions are generated to load the immediate value into the destination
register or
$at
.
C.4 Load and Store Instructions
On most processors that implement the Alpha architecture, loading and storing unaligned data or data less than 32 bits is done with multiple machine-code instructions. Except on EV56 Alpha processors, the following assembler instructions generate multiple machine-code instructions:
Load Byte (ldb
)
Load Byte Unsigned (ldbu
)
Load Word (ldw
)
Load Word Unsigned (ldwu
)
Unaligned Load Word (uldw
)
Unaligned Load Word Unsigned (uldwu
)
Unaligned Load Longword (uldl
)
Unaligned Load Quadword (uldq
)
Store Byte (stb
)
Store Word (stw
)
Unaligned Store Word (ustw
)
Unaligned Store Longword (ustl
)
Unaligned Store Quadword (ustq
)
Signed loads may require one more instruction than an unsigned load.
On EV56 Alpha processors, the following instructions from the preceding list generate a single instruction:
Load Byte Unsigned (ldbu
)
Load Word Unsigned (ldwu
)
Store Byte (stb
)
Store Word (stw
)
C.5 Integer Arithmetic Instructions
Multiply
operations using constant powers of two are turned into
sll
or scaled add instructions.
There are no machine instructions for performing integer division (divl
,
divlu
,
divq
, and
divqu
) or remainder operations (reml
,
remlu
,
remq
, and
remqu
).
The
machine instructions generated for these assembler instructions depend on
the operands specified on the instructions.
Division and remainder operations involving constant values are replaced by an instruction sequence that depends on the data type of the numerator and the value of the constant.
Division and remainder operations involving nonconstant values are replaced
with a procedure call to a library routine to perform the operation.
The library
routines are in the C run-time library (libc
).
The library
routines use a nonstandard parameter passing mechanism.
The first operand
is passed in register
t10
and the second operand is passed
in
t11
.
The result is returned in
t12
.
If the operands specified are other than those just described, the assembler
moves them to the correct registers.
The library routines expect the return
address in
t9
; therefore, a routine that uses divide instructions
does not need to save register
ra
just because it uses
divide instructions.
The
absl
and
absq
(absolute value)
instructions generate two machine instructions.
C.6 Floating-Point Load Immediate Instructions
There are no floating-point instructions that accept an immediate value
(except for 0.0).
Whenever the assembler encounters a floating-point load
immediate instruction, the immediate value is stored in the data section and
a load instruction is generated to load the value.
C.7 One-to-One Instruction Mappings
Some assembler instructions generate single machine instructions. Such assembler instructions are sometimes referred to as pseudoinstructions. The following table lists these assembler instructions and their equivalent machine instructions:
Assembler Instruction | Machine Instruction | ||
andnot |
$rx,$ry,$rz |
bic |
$rx,$ry,$rz |
clr |
$rx |
bis |
$31,$31,$rx |
fabs |
$fx,$fy |
cpys |
$f31,$fx,$fy |
fclr |
$fx |
cpys |
$f31,$f31,$fx |
fmov |
$fx,$fy |
cpys |
$fx,$fx,$fy |
fneg |
$fx,$fy |
cpysn |
$fx,$fx,$fy |
fnop |
|
cpys |
$f31,$f31,$f31 |
mov |
$rx,$ry |
bis |
$rx,$rx,$ry |
mov |
|
bis |
|
negf |
$fx,$fy |
subf |
$f31,$fx,$fy |
negfs |
$fx,$fy |
subfs |
$f31,$fx,$fy |
negg |
$fx,$fy |
subg |
$f31,$fx,$fy |
neggs |
$fx,$fy |
subgs |
$f31,$fx,$fy |
negl |
$rx,$ry |
subl |
$31,$rx,$ry |
neglv |
$rx,$ry |
sublv |
$31,$rx,$ry |
negq |
$rx,$ry |
subq |
$31,$rx,$ry |
negqv |
$rx,$ry |
subqv |
$31,$rx,$ry |
negs |
$fx,$fy |
subs |
$f31,$fx,$fy |
negssu |
$fx,$fy |
subssu |
$f31,$fx,$fy |
negt |
$fx,$fy |
subt |
$f31,$fx,$fy |
negtsu |
$fx,$fy |
subtsu |
$f31,$fx,$fy |
nop |
|
bis |
$31,$31,$31 |
not |
$rx,$ry |
ornot |
$31,$rx,$ry |
or |
$rx,$ry,$rz |
bis |
$rx,$ry,$rz |
sextl |
$rx,$ry |
addl |
$rx,0,$ry |
unop |
|
ldq_u |
$31,0($sp) |
xornot |
$rx,$ry,$rz |
eqv |
$rx,$ry,$rz |