I-Format
Recap that we have 5-bit shamt
field.
This can only represent the values between 0 and 31.
We do not need the second register operand as well as shamt
so we can merge them into a longer 16-bit field.
Unfortunately, a naive approach to this would probably remove the $rt
field.
But this field is in between $rt
and $rd
and that will make for an awkward immediate field.
But if you remember the summary, we actually remove $rd
!
This is better because the merged field will now be continuous.
This is a compromise. We have just defined a new instruction format (i.e., I-format) that is partially consistent with R-format. The compromise follows from MIPS design principles.
Keep the common part common
Use as much of the part as possible
Keep the instruction size uniform
Bits
I-format instructions use the following fields with the following name and number of bits:
opcode |
$rs |
$rt |
immediate |
---|---|---|---|
6 | 5 | 5 | 16 |
The immediate field is 16-bit.
This is also the only field that is inconsistent with R-format.
In particular opcode
, $rs
and $rt
are still in the same locations.
Fields | Meaning |
---|---|
opcode |
Specifies the instruction. |
$rs |
Specify register containing first operand. |
$rt |
Specify register which will receive the result of computation (_except for sw , beq and bne ). |
immediate |
The constant to be used in the operation. |
Steps
The steps to assemble I-format instructions can be summarised as follows:
- Find the value of
opcode
. - Find the register number for
$rs
. - Find the register number for
$rt
. - Compute the number for
immediate
(may need conversion from negative 2s complement number). - Convert the values to binary.
- Combine the fields.
Register Ordering
Note that the result (if any) is now stored in the target register $rt
as we no longer have destination register $rd
.
Additionally, the register and immediate value ordering are different on different instruction (on the MIPS code and not on the machine code):
Instruction | Basic | 1st | 2nd | 3rd |
---|---|---|---|---|
Branch | op $rs, $rt, immediate |
$rs |
$rt |
immediate |
Memory | op $rt, immediate($rs) |
$rt |
immediate |
$rs |
Others | op $rt, $rs, immediate |
$rt |
$rs |
immediate |
Opcode Values
The values for the opcode
field is summarised below:
Operation | Hexadecimal | Decimal |
---|---|---|
beq |
04 | 04 |
bne |
05 | 05 |
addi |
08 | 08 |
andi |
0C | 12 |
ori |
0D | 13 |
xori |
0E | 14 |
lb |
20 | 32 |
lw |
23 | 35 |
sb |
28 | 40 |
sw |
2B | 43 |
Immediate Field
The immediate field is how we put the constant value into the instruction. Since we only have 32 bits for the instruction, we cannot use all of them for the constant values. With the compromise above, we have come up with a 16 bits field.
Now, we can classify the immediate field into two kinds:
- Signed Integer
- Range is between -215 to 215-1.
- Signed extended (append the MSB to the front until 32 bits).
- Used for arithmetic operations:
addi
,slti
,lw
,sw
. - This is large enough to handle:
- The offset in a typical memory operations:
lw
,sw
. - Most of the values used in the
addi
,slti
instructions.
- The offset in a typical memory operations:
- Unsigned Integer
- Range is between 0 to 216-1.
- Bit extended (append the 0 to the front until 32 bits).
- Used for logical operations:
andi
,ori
,xori
.
Examples
Arithmetic and Memory
The conversion simply follow the steps above.
The value of the immediate
is treated as signed integers.
Addition
Addition | |
---|---|
1 2 |
|
Fields | Decimal Value | Binaries |
---|---|---|
opcode |
8 | 001000 |
$rs |
22 | 10110 |
$rt |
21 | 10101 |
immediate |
-50 | 1111111111001110 |
Given the steps, we can now combine the binaries:
001000 10110 10101 1111111111001110
or more simply:
00100010110101011111111111001110
We can also convert this into hexadecimal by splitting it into 4-bit groups:
Binary to Hexadecimal | |
---|---|
1 2 3 4 |
|
0x22D5FFCE
Exercise
Convert the following instruction to hexadecimal:
Question | |
---|---|
1 |
|
See the steps to get the following binaries:
100011 01000 01001 0000000000001100
or more simply:
10001101000010010000000000001100
Convert this into hexadecimal by splitting it into 4-bit groups:
Binary to Hexadecimal | |
---|---|
1 2 3 4 |
|
`0x22D5FFCE
Fields | Decimal Value | Binaries |
---|---|---|
opcode |
35 | 100011 |
$rs |
8 | 01000 |
$rt |
9 | 01001 |
immediate |
12 | 0000000000001100 |
Logic
We are still following the steps, but now the value of the immediate
is treated as unsigned integers.
In fact, it is often written simply as hexadecimals.
Bitwise OR
Bitwise OR | |
---|---|
1 2 |
|
Fields | Decimal Value | Binaries |
---|---|---|
opcode |
13 | 001101 |
$rs |
9 | 01001 |
$rt |
8 | 01000 |
immediate |
4095 | 0000111111111111 |
Given the steps, we can now combine the binaries:
001101 01001 01000 0000111111111111
or more simply:
00110101001010000000111111111111
We can also convert this into hexadecimal by splitting it into 4-bit groups:
Binary to Hexadecimal | |
---|---|
1 2 3 4 |
|
0x35280FFF
Branch
Branch operations (e.g., beq
and bne
) use PC-relative addressing.
The main limitation faced by branch operation is that the immediate field is only 16 bits while the memory address is 32 bits.
Fortunately, if we look at the usage of branch operations, they are often used in selection statements (e.g., if
) or repetition statements (e.g., while
or for
).
These statements are typically small, usually only up to 50 instructions.
Which means, the value of $PC
will often change only by a small amount either positive (i.e., downwards) or negative (i.e., upwards).
So, we can actually specify the target address relative to the current instruction address.
The current instruction address is stored in the special register $PC
We usually represent the $PC
as an arrow before the instruction currently being executed.
Using PC-relative addressing technique, the branch can take values in the range of ±215 bytes from the $PC
.
If we use the value as it is, given that each instruction is word-aligned, the usable values are actually only ±213 words from the $PC
.
Obviously that's a waste of useful values.
But since the instructions are word-aligned, the number of bytes to add to the $PC
will always be a multiple of 4.
So, we can instead interpret the immediate value as the number of words by automatically multiply the value by 4.
This way, we can branch ±215 words (or ±217 bytes) from the $PC
.
To put it simply, we can now branch 4 times farther!
Branch Calculation
-
If the branch is not taken:
$PC' = $PC + 4
-
If the branch is taken:
$PC' = ($PC + 4) + (immediate × 4)
Here, $PC + 4
is the address of the next instruction and $PC'
is the target address.
Why do we use $PC + 4
when the branch is not taken?
The reason will be clearer when we show the processor implementation.
The advantage of this computation is that the immediate value specifies the number of instruction to "skip over" (from the next instruction).
Quick Branch Calculation
The immediate value specifies the number of instruction to "skip over" (from the next instruction).
Due to the PC-relative addressing, we cannot simply give you a single branch instruction and ask you to translate it into machine code. This is because one of the value to be deduced corresponds to the label which may be several instructions away.
Branch
Branch | |
---|---|
1 2 3 4 5 6 |
|
Fields | Decimal Value | Binaries |
---|---|---|
opcode |
4 | 000100 |
$rs |
9 | 01001 |
$rt |
0 | 00000 |
immediate |
3 | 0000000000000011 |
We will illustrate two ways to compute the value of immediate.
The current $PC
is 0.
The target address $PC'
is 16.
We need to solve the equation $PC' = ($PC + 4) + (immediate × 4)
given that we know the value of $PC
and $PC'
.
Computation of Immediate | |
---|---|
1 2 3 4 5 6 |
|
So, the value of immediate field should be 3.
-
Draw a line below the current instruction (this represents the
$PC + 4
). -
Draw a line above the target instruction (this represents the
$PC'
). -
Complete the box.
-
Count the number of instructions within the box (this represents the
immediate × 4
).- If the target label is after, keep the value as positive.
- If the target label is before, convert the value to negative.
Similar to the previous method, we get the answer for the immediate field as 3.
Given the steps, we can now combine the binaries:
000100 01001 00000 0000000000000011
or more simply:
00010001001000000000000000000011
We can also convert this into hexadecimal by splitting it into 4-bit groups:
Binary to Hexadecimal | |
---|---|
1 2 3 4 |
|
0x11200003
Exercise
Given the following branch instruction below.
MIPS Instruction | |
---|---|
1 2 3 4 5 6 |
|
For the instruction at line 4 (highlighted above), what is the immediate value for the instruction?
-4
Steps
We will illustrate two ways to compute the value of immediate.
The current $PC
is 12.
The target address $PC'
is 0.
We need to solve the equation $PC' = ($PC + 4) + (immediate × 4)
given that we know the value of $PC
and $PC'
.
Computation of Immediate | |
---|---|
1 2 3 4 5 6 |
|
So, the value of immediate field should be -4.
-
Draw a line below the current instruction (this represents the
$PC + 4
). -
Draw a line above the target instruction (this represents the
$PC'
). -
Complete the box.
-
Count the number of instructions within the box (this represents the
immediate × 4
).- If the target label is after, keep the value as positive.
- If the target label is before, convert the value to negative.
So the answer is also -4 using this method.