RISC-V Instructions
-
Instruction syntax is rigid
op
= opration name(“operator”)dst
= register getting result(“destination”)src1
= first register for operation(“source1”)src2
= second register for operation(“source2”)
-
Keep hardware Simple via regularity
-
One operation per instruction, at most one instruction per line
-
Assembly instructions are related to C operations (=, +, -, *, etc.)
Example RISV-V Assembly
- comments start with
#
- Labels are arbitrary names that mark a section of code
Basic Arithmetic Instructions
Assume here that the variable a, b and c are assigned to register s1, s2 and s3, respectively
- Integer Addition(add)
- C:
a = b + c;
- RISC-V:
add s1, s2, s3
- C:
- Integer Substraction(sub)
- C:
a = b - c;
- RISC-V:
sub s1, s2, s3
- C:
Immediate Instructions
- Numerical Constants are called Immediates
- Separate instruction syntax for immediates:
opi dst, src, imm
- operation names end with ‘i’, replace 2nd source register with an immediate
- immediates can be up to 12-bits in size
- Interpreted as sign-extended two’s complement
- Example uses:
addi s1, s2, 5 # a = b + 5
addi s3, s3, 1 # c++
Data Transfer Instructions
- Instruction syntax for data transfer:
memop reg, off(bAddr)
memop
= operation name(“operator”)reg
= register for operation source or destinationbAddr
= register with pointer to memory(“base address”)off
= address offset(“immediate”) in bytes(“offset”)
- Access memory add address
bAddr + off
Endianness
- Big Endian: Most-significant byte at least address of word
- Little Endian: Least-significant byte at least address of word
RISC-V is Little Endian
Sign Extension
Represent the same number using more bits than before:
- Sign extend: Take the most-significant bit and copy it to the new bits
- 0b11=0b1111
- Zero/One pad: Set the new bits with one/zero.
- Zero pad: 0b11=0b0011
- One pad: 0b11=0b1111
All base RISC-V instructins sign extend when needed.
Byte Instructions
lb
: load byte. Upper 24 bits are filled by sign-extensionsb
: save byte. Upper 24 bits are ignored.
For example, let memo at s0 = 0x00000180:
Half-Word Instructions
sh
,lh
, behavior same assb
andlb
Unsigned Instructions
l(b/h)u
, upper bits are filled by zero-extension.
No s(b/h)u
because upper bits of register are ignored when save to memory.
No lwu
because there are no extension when load word.
Control Flow Instructions
beq
(branch if equal)- `beq reg1, reg2, label
- if value in
reg1
= value inreg2
, go tolabel
- otherwise go to the next instruction
bne
(branch if not equal)bne reg1, reg2, label
j
(jump)j label
- Unconditional jump to label
Shifting Instructions
Instruction Name | RISV-V |
---|---|
Shift Left Logical | sll s1, s2, s3 |
Shift Left Logical Imm | slli s1, s2, imm |
Shift Right Logical | srl s1, s2, s3 |
Shift Right Logical Imm | srli srli, s1, s2, imm |
Shift Right Arithmetic | sra s1, s2, s3 |
Shift Right Arithmetic Imm | srai, s1, s2, imm |
- When using immediate, only values 0-31 are pratical
- When using variable, only lowest 5 bits are used.
Register Name, Use, Calling Convention
Register | Name | Use | Saver |
---|---|---|---|
x0 | zero | The constant value 0 | N.A. |
x1 | ra | Return address | Caller |
x2 | sp | Stack pointer | Callee |
x3 | gp | Global pointer | — |
x4 | tp | Thread pointer | — |
x5-x7 | t0-t2 | Temporaries | Caller |
x8 | s0/fp | Saved register/Frame pointer | Callee |
x9 | s1 | Saved register | Callee |
x10-x11 | a0-a1 | Function arguments/Return values | Caller |
x12-x17 | a2-a7 | Function arguments | Caller |
x18-x27 | s2-s11 | Saved registers | Callee |
x28-x31 | t3-t6 | Temporaries | Caller |
The 6 Instruction Formats
-
R: instructions using 3 register inputs
- add, xor, mul
-
I: instructions with immediates, loads
- addi, lw, jalr, slli
-
S: store instruction
- sw, sb
-
SB: branch instructions:
- beq, bge
-
U: instructions with upper immediates. Upper immediate is 20-bits
- lui, auipc
-
UJ: the jump instruction:
- jal