1Learning Outcomes¶
Translate between I-type assembly instructions and machine instructions.
Reason about why load and
jalrare I-Type instructions.Translate
jrandretpseudoinstructions to machine instructions.
🎥 Lecture Video
We now turn to our next instruction format: I-Type. While the “I” is for Immediate, the I-Type instruction format is used for a variety of instructions:
Register-immediate arithmetic instructions
Load instructions
The
jalrinstruction(out of scope) Environment calls and breakpoints
The I-Type instruction format is the second and third rows of the instruction format table.
2I-Type: Fields¶
We first discuss arithmetic instructions of the form opname rd rs1 imm like addi, xori, etc. The format is shown in Figure 1:
!["RISC-V I-type layout: assembly opname rd rs1 imm above a 32-bit bar with imm[11:0] (bits 31–20), rs1 (bits 19–15), funct3 (bits 14–12), rd (bits 11–7), and opcode (bits 6–0), labeling the 12-bit immediate, source register, and destination register fields."](/build/i-type-437efb2074bb1c7af8b73d8a550fb1b4.png)
Figure 1:The I-Type Instruction Format.
I-Type Fields:
Register operands: Notice that the register fields
rs1andrdare in the same positions in I-Type and R-type; this intentional design reduces hardware complexity.Constant operand: The immediate field[1]
immspecifies a 12-bit-wide numeric constant. The I-Type has no second source registerrs2, soimmreuses those bit positions to encode a larger numeric constant across bits 15 to 31.The 12-bit immediate is a two’s complement integer with range to . Before using this 12-bit-wide value in an operation, the hardware sign-extends it to a 32-bit-wide value.
Operation fields:
opcode,funct3
3Assembly Instruction Machine Instruction¶
Consider Figure 2, which translates addi x15 x1 -50 to a machine instruction.
!["Encoding of addi x15 x1 -50: imm[11:0] holds two’s complement 0b111111001110 for -50, rs1 is 0b00001 for x1, funct3 is 0b000 for add, rd is 0b01111 for x15, and the opcode is 0b0010011 for I-type arithmetic."](/build/itype-addi-example-270e47e927b8ddfbfc13df1f1cbdb6dc.png)
Figure 2:The I-Type instruction addi x15 x1 -50.
We follow the steps for translating assembly into machine code from earlier:
Determine instruction format type.
addiis I-type because it performs arithmetic betwen a register operand and a constant operand. We use the arithmetic instructions table on the RISC-V green card.Determine operation field codes.
opcode:0010011for all register-immediate arithmetic instructionsfunct3:000foradd
Translate registers, immediates, etc.
rs1: Registerx1. Translate 1 to 5-bit unsigned integer representation00001.rd: Registerx15. Translate 15 to 5-bit unsigned integer representation01111.imm: -50 as 12-bit two’s complement:+50 is
0000 0011 0010.Flip bits:
1111 1100 1101.Add one to get -50:
1111 1100 1110.
(if needed) Convert to hexadecimal.
We leave this as an exercise to you!
4I-Type vs. R-Type¶
Figure 3 compares the two instruction formats we have seen so far:
!["Side-by-side R-type and I-type instruction format comparison: both formats share bit positions for opcode, rd, funct3, and rs1; R-type uses bits 31–20 for funct7 plus rs2, while I-type replaces that region with a 12-bit immediate imm[11:0]."](/build/comparison-itype-rty-40bcbad2b613c0ec2d9729afe9c83118.png)
Figure 3:I-Type instruction set comparison to R-Type instruction set.
Again, good design demands good compromises. If we only had the single R-Type format and specified imm as a 5-bit field replacing rs2, then we’d only be able to represent 32 immediate values. The I-Type field therefore expands the imm field across the R-type’s rs2 and funct7 fields to at least guarantee we can represent a wider range of 212 immediate values.
The I-type design’s consistency with R-type simplifies how hardware processes these two instruction formats. Constants are frequently short and can fit into the 12-bit imm field. For larger constants, we must use additional instructions like lui (load upper-immediate), which we discuss later.
Notice the 3-bit funct3 field is not sufficient to specify the 9 register-immediate arithmetic instructions, much less any load instructions. The I-Type therefore still has a few details. Onward!
5Arithmetic Shifts (“I*-Type”)¶
While there is no official “I*-Type” instructions, the RV32I Unprivileged Manual says:
Shifts by a constant are encoded as a specialization of the I-type format.
In this course we will call these “I*-Type” (where the asterisk is “mostly I-Type, save some details”). Consider Table 1 and the following excerpt from the manual:
The operand to be shifted is in rs1, and the shift amount is encoded in the lower 5 bits of the I-immediate field. The right shift type is encoded in bit 30.
Table 1:Shift-by-immediate instructions.
| Instruction | imm[11:5] | imm[4:0] | rs1 | funct3 | rd | opcode |
|---|---|---|---|---|---|---|
slli | 0000000 | imm[4:0] | rs1 | 001 | rd | 0010011 |
srli | 0000000 | imm[4:0] | rs1 | 101 | rd | 0010011 |
srai | 0100000 | imm[4:0] | rs1 | 101 | rd | 0010011 |
Observations:
Arithmetic bitshift operations need only a 5-bit unsigned immediate, in
imm[4:0]. The maximum bitshift is 32; anything larger will shift all data off the register, which is 32 bits wide.The upper seven bits[2] are not part of the immediate and used very similarly to the
funct7field for R-Type instructionssll,srl, andsra.Like with R-type, Bit 30 is a flag that indicates when it is necessary to sign-extend.
If Bit 30 is on, insert leading
1’s (forsrai).If Bit 30 is off, just zero-extend for
srli(andslli, where left-shifts are only ever logical).
6Load Instructions¶
Remember, instruction formats are simply just formats. The operation specifies what the hardware actually does. However, keeping the same instruction format allows us to simplify and reuse certain hardware.
Load instructions are one such example. Recall from an earlier section:
The load word instruction:
Computes a memory address
R[rs1]+immLoad a word from this address in memory,
M[R[rs1] + imm][31:0]into a destination register,rd.
Loads can therefore use the I-Type instruction format (Figure 4):
imm,rs1,rdfieldsopcode(as all instructions do). Loads use opcode000 0011.funct3specifies partial loads and signed/unsigned loads.
!["I-type layout for loads: syntax loadop rd imm(rs1) with immediate imm[11:0] as a byte offset added to the base rs1, funct3, rd as destination of the loaded value, and the load opcode field; color-coding differentiates the immediate, source register, and destination register."](/build/load-operation-isa-c74990f2cdded96c105e5afe33495ecf.png)
Figure 4:Load instructions use I-Type instruction format.
Observations:
The fact that loads perform a memory access is irrelevant to how we specify the instruction. The instruction bits simply provide enough information for the hardware to decode and execute the correct instruction.
Loads do share some similarities with other I-Type instructions. Notably, loads also perform register-immediate addition to compute the memory address as
R[rs1] + imm. Loads can therefore reuse any hardware needed for register-immediate arithmetic instructions.
We recommend reviewing the earier chapter for the description of each load instruction in Table 2.
Table 2:Load Instructions (recall there is no lwu).
| Instruction | imm[11:0] | rs1 | funct3 | rd | opcode |
|---|---|---|---|---|---|
lb | imm[11:0] | rs1 | 000 | rd | 0000011 |
lbu | imm[11:0] | rs1 | 100 | rd | 0000011 |
lh | imm[11:0] | rs1 | 001 | rd | 0000011 |
lhu | imm[11:0] | rs1 | 101 | rd | 0000011 |
lw | imm[11:0] | rs1 | 010 | rd | 0000011 |
6.1Load Example¶
Show Explanation
!["Encoding of lw x14 8(x2): imm[11:0] 0b000000001000 for offset 8, rs1 is 0b00010 for register x2, funct3 is 0b010, rd is 0b01110 for x14, and opcode is 0b0000011 for loads."](/build/practice-lw-7dcf6859b25780f287c16c4e4cc149e8.png)
Figure 5:The I-Type instruction lw x14 8(x2).
We follow the steps for translating assembly into machine code from earlier:
Determine instruction format type.
lwis I-type. We use the memory table on the RISC-V green card.Determine operation field codes.
opcode:0000011for load instructionsfunct3:010for load word
Translate registers, immediates, etc.
rs1: Base Registerx2. Translate 1 to 5-bit unsigned integer representation00010.rd: Registerx14. Translate 14 to 5-bit unsigned integer representation01110.imm: address offset +8 as 12-bit two’s complement:0000 0000 1000.
7jalr: I-Type¶
We recommend reviewing jump instructions before continuing:
Jump and Link Register (
jalr rd rs1 imm). Link the “return address” (PC + 4) to a registerrd. Then perform an unconditional jump by settingPCtoR[rs1] + imm.
The jalr instruction can also be supported with the I-Type format (Figure 6):
imm,rs1,rdfieldsopcode(as all instructions do).jalruses opcode110 0111.funct3is not particularly needed, since there is only onejalrinstruction. However, because the I-Type format requires it,jalruses000.
!["I-type jalr layout including the immediate field imm[11:0] as an offset added to source register rs1 to form the jump target, funct3, rd receiving the link value PC plus four, and opcode; annotations differentiate the offset, base register, and link destination."](/build/jalr-isa-9c35b41b10b44a5dcee2c21a9d783af9.png)
Figure 6:jalr instruction format. The program counter is updated to the base register plus a numeric constant, e.g., PC = R[rs1] + imm.
Observations:
Like with loads, the fact that
jalraccesses PC is irrelevant to how we specify the instruction.Like with loads,
jalralso performs register-immediate addition,jalrcan therefore reuse register-immediate arithmetic hardware to compute the jump addressR[rs1] + imm.
8Design Decisions for I-Type¶
This section is intended for you to develop your intuition for I-Type instructions using what you learned in this section.
Consider the I-Type instructions[3] shown in Table 3, which is a reformatting of the rightmost columns of relevant tables on the RISC-V green card.
Table 3:RV32I Instructions: (a) I-Type; (b) “I*-Type”, a reprint of Table 1.
| Instruction | imm[11:0] | rs1 | funct3 | rd | opcode |
|---|---|---|---|---|---|
addi | imm[11:0] | rs1 | 000 | rd | 0010011 |
andi | imm[11:0] | rs1 | 111 | rd | 0010011 |
ori | imm[11:0] | rs1 | 110 | rd | 0010011 |
xori | imm[11:0] | rs1 | 100 | rd | 0010011 |
slti | imm[11:0] | rs1 | 010 | rd | 0010011 |
sltiu | imm[11:0] | rs1 | 011 | rd | 0010011 |
lb | imm[11:0] | rs1 | 000 | rd | 0000011 |
lbu | imm[11:0] | rs1 | 100 | rd | 0000011 |
lh | imm[11:0] | rs1 | 001 | rd | 0000011 |
lhu | imm[11:0] | rs1 | 101 | rd | 0000011 |
lw | imm[11:0] | rs1 | 010 | rd | 0000011 |
jalr | imm[11:0] | rs1 | 000 | rd | 1100111 |
ecall | 000000000000 | 00000 | 000 | 00000 | 1110011 |
ebreak | 000000000001 | 00000 | 000 | 00000 | 1110011 |
| Instruction | imm[11:5] | imm[4:0] | rs1 | funct3 | rd | opcode |
|---|---|---|---|---|---|---|
slli | 0000000 | imm[4:0] | rs1 | 001 | rd | 0010011 |
srli | 0000000 | imm[4:0] | rs1 | 101 | rd | 0010011 |
srai | 0100000 | imm[4:0] | rs1 | 101 | rd | 0010011 |
Show Explanation
Arithmetic:
0010011Load:
0000011jalr:
1100111Other (
ecall,ebreak):1110011
Show Explanation
Same eight unique funct3 fields as corresponding R-format operation (remember, no subi)
| funct3 | R-Type | I-Type |
|---|---|---|
000 | add | addi |
000 | sub | |
111 | and | andi |
110 | or | ori |
100 | xor | xori |
001 | sll | slli |
101 | srl | srli |
101 | sra | srai |
010 | slt | slti |
011 | sltu | sltiu |
See explanation [above].
First question: see explanation [above]. Second question: See a later section.
Again, immediates are called as such because their bit patterns are directly encoded into the machine instruction.
The course RISC-V green card labels these upper 7 bits as “funct7”–a misnomer, because I-Types don’t have a
funct7field. As per the RISC-V Unprivileged Manual these upper 7 bits should really be relabeledimm[11:5]–part of theimm[11:0]field, but not considered part of the numeric constant.ecall,ebreakare out of scope in our discussion, but see more details in the RISC-V Green Card and the RISC-V Unprivileged Manual.