Skip to content

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.

Design Principle #2

Keep the common part common

Design Principle #3

Use as much of the part as possible

Design Principle #4

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:

  1. Find the value of opcode.
  2. Find the register number for $rs.
  3. Find the register number for $rt.
  4. Compute the number for immediate (may need conversion from negative 2s complement number).
  5. Convert the values to binary.
  6. 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.
  • 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
addi $s5, $s6, -50
#op  $rt, $rs, immediate
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
   00100010110101011111111111001110
=> 0010 0010 1101 0101 1111 1111 1100 1110
=> 2    2    D    5    F    F    C    E
=> 22D5FFCE

0x22D5FFCE

Exercise

Convert the following instruction to hexadecimal:

Question
1
lw $t1, 12($t0)

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
   10001101000010010000000000001100
=> 1000 1101 0000 1001 0000 0000 0000 1100
=> 8    D    0    9    0    0    0    C
=> 22D5FFCE

`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
ori  $t0, $t1, 0xFFF
#op  $rt, $rs, immediate
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
   00110101001010000000111111111111
=> 0011 0101 0010 1000 0000 1111 1111 1111
=> 3    5    2    8    0    F    F    F
=> 35280FFF

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.

Branch

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).

Branch

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
Loop: beq  $t1, $zero, End    # rlt addr: 0
      #op  $rs, $rt  , label
      add  $t0, $t0  , $t2    # rlt addr: 4
      addi $t1, $t1  , -1     # rlt addr: 8
      j    Loop               # rlt addr: 12
End:                          # rlt addr: 16
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
   $PC' = ($PC + 4) + (immediate × 4)
=> 16   = (0   + 4) + (immediate × 4)
=> 16   = 4         + (immediate × 4)
=> 16-4 =             (immediate × 4)
=> 12   =             (immediate × 4)
=> 3    =              immediate

So, the value of immediate field should be 3.

  1. Draw a line below the current instruction (this represents the $PC + 4).

    Immediate Step 1

  2. Draw a line above the target instruction (this represents the $PC').

    Immediate Step 2

  3. Complete the box.

    Immediate Step 3

  4. 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
   00010001001000000000000000000011
=> 0001 0001 0010 0000 0000 0000 0000 0011
=> 1    1    2    0    0    0    0    3
=> 11200003

0x11200003

Exercise

Given the following branch instruction below.

MIPS Instruction
1
2
3
4
5
6
Loop: beq  $t1  , $zero, End   # rlt addr: 0
      add  $t0  , $t0  , $t2   # rlt addr: 4
      addi $t1  , $t1  , -1    # rlt addr: 8
      beq  $zero, $zero, Loop  # rlt addr: 12
      #op  $rs  , $rt  , label
End:                           # rlt addr: 16

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
   $PC' = ($PC + 4) + (immediate × 4)
=> 0    = (12  + 4) + (immediate × 4)
=> 0    = 16        + (immediate × 4)
=> 0-16 =             (immediate × 4)
=> -16  =             (immediate × 4)
=> -4   =              immediate

So, the value of immediate field should be -4.

  1. Draw a line below the current instruction (this represents the $PC + 4).

    Immediate Step 1

  2. Draw a line above the target instruction (this represents the $PC').

    Immediate Step 2

  3. Complete the box.

    Immediate Step 3

  4. 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.