Constant Operands
-
Accessing constants in an operation is a very frequent occurrence. For example
the C compiler gcc uses constants over 50% of the time in arithmetic
operations.
-
Heeding the design principle, "keep the common case fast",MIPS architecture
includes a way to access small constants in an instruction.
-
This avoids a slower memory access and includes the ability to have one operand
of the instruction as a constant.
-
The format for these instructions is the same as data transfer and branch
instructions. It is the I-format. In fact, the "I" in I-format stands for
immediate.
op
|
rs
|
rt
|
constant
|
6 bits
|
5 bits
|
5 bits
|
16 bits
|
|
-
The field containing the constant is 16 bits long. This allows 216 or
65,536 unsigned values.
-
Constants are short and frequently fit into this field.
Example 1 Constants are frequently used in arithmetic operations:
addi $t0, $s1, 17 # $t0 = $s1 + 17
Example 2 Constants are also frequently used in comparisons:
slti $t0, $s1, 45 # $t0 = 1 if $s1 < 45
|
What if the constant is larger than 16 bit?
The MIPS instruction set includes the
lui (load upper immediate) instruction. This allows the upper 16 bits of a constant to be set in a register. An additional instruction can load the lower 16 bits such as an
addi or ori instruction. Then this register may be used as the constant.
Example 3
Place the constant 11,370,150 in register $t0:
step 1 # converted to binary = 0000 0000 1010 1101 0111 1110 1010 0110
step 2 lui $t0, 173 # 173 = 0000 0000 1010 1101 binary upper bits
step 3 ori $t0, $t0, 32423 # 32423 = 0111 1110 1010 0110 binary lower bits
register $t0 after each step:
|
1 |
0000 0000 0000 0000 0000 0000 0000 0000 |
2 |
0000 0000 1010 1101 0111 1110 1010 0110 |
3 |
0000 0000 1010 1101 0000 0000 0000 0000 |
|
-
A note of caution: One must be careful as to which instructions are chosen for creating a 32-bit constant. The
addi instruction will copy the leftmost bit of the 16-bit immediate field of the instruction into the upper 16 bits of a word. The ori instruction will zero extend the immediate into the register rt field.
|
Jumps (Unconditional Branches)
-
The simplest addressing is found in the jump instruction. It uses the j-type
format in which 6 bits are for the operation field and the other 26 bits are
for the address field.
op
|
address
|
6 bits
|
26 bits
|
-
MIPS stretches the addressable distance 4X by referring to the number of words
since all instructions are 4 bytes long.
-
This allows the jump instruction over 67 million values giving over 268 MB of
addressable space representing a 28-bit byte address.
For programs larger that 256MB the jump must be replaced by several
instructions followed by a jump register instruction in order to allow for
loading a full 32-bit address into a register.
-
If a jump must go further, then a jump register,
jr, instruction must be used.
|
Branches (Conditional)
-
Conditional branches use the I-type instruction format where the immediate is
the "branch to" address.
op
|
rs
|
rt
|
constant
|
6 bits
|
5 bits
|
5 bits
|
16 bits
|
-
This form of address branching is called
PC-relative addressing.
It gets its name from the method used to determine the address.
A 16-bit address is too restrictive and would limit a program to about 64k
instructions.
To overcome this problem, the branch address is added to the program counter
(PC).
This allows any branch to be a distance of 215 or 32,767 words from
the current instruction in either direction.
-
Using two design principals, "make the common case fast", and "smaller is
faster",
the addressing is left to 16-bits.
-
As most conditional branches are found in loops and in
if statements, almost all of these
statements are much smaller than the 216 size restriction.
Most go to locations under 20 instructions from the PC.
-
The actual address is really relative to the Program Counter + 4 because the PC
is incremented early in the process.
-
MIPS uses byte addressing and all instructions are 4 bytes long.
Just as in jumps, MIPS gains the maximum distance for a branch by using the
value as the number of words to the next instruction as compared to the number
of bytes to the instruction.
Thus, a relative word address instead of a relative byte address increases the
distance 4 fold.
-
Most often when coding a conditional branch, a label is used instead of
calculating the actual instruction address because the distance between
instructions can be difficult to calculate when pseudo instructions expand into
several instructions.
A branch can jump 215 - 1 forward or 215 backward.
Example 4 branch if a condition is true to a NewLocation:
lw $t0, 0($sp) # load variable 1
lw $t1, 1($sp) # load variable 2
beg $t0, $t1, NewLoc # if $t0 = $t1 go to NewLoc
... # more processing
... # more processing
NewLoc:
|
What if the less frequent case occurs in which a branch to a far away
location is needed?
Then what's called
Pseudodirect addressing occurs. The assembler inserts an unconditional jump to the branch target and the condition is inverted so the branch decides whether to skip the jump or not.
Example 5
branch to a far away NewLocation:
lw $t0, 0($sp) # load variable 1
lw $t1, 1($sp) # load variable 2
bne $t0, $t1, L1 # if $t0 != $t1 skip far jump, go to L1
j NewLoc # far away jump
L1:
|