RISC-V assembler instructions
The RISC-V Lisp assembler supports the following instructions:
Operation | Example | Action | Notes | |
Move |
Register to register |
($mv 'a0 'a1) |
a0 = a1 |
|
Arithmetic |
Add Add immediate Add word Add immediate word Subtract Subtract word Add upper imm to PC |
($add 'a0 'a1 'a2) ($addi 'a0 'a1 8) ($addw 'a0 'a1 'a2) ($addiw 'a0 'a1 8) ($sub 'a0 'a1 'a2) ($subw 'a0 'a1 'a2) ($auipc 'a0 imm) |
a0 = a1 + a2 a0 = a1 + imm a0 = a1 + a2 a0 = a1 + imm r0 = sp + 4
a0 = PC + imm[31:12] |
Range -2048 to 2047
Range -2048 to 2047 Range 0 to 1020 (word aligned)
|
Multiply/ |
Multiply Multiply upper word Multiply upper word Multiply upper word Divide Divide unsigned Divide word Divide unsigned word Remainder Remainder unsigned Remainder word Remainder un. word |
($mul 'a0 'a1 'a2) ($mulh 'a0 'a1 'a2) ($mulhsu 'a0 'a1 'a2) ($mulhu 'a0 'a1 'a2) ($div 'a0 'a1 'a2) ($divu 'a0 'a1 'a2) ($divw 'a0 'a1 'a2) ($divuw 'a0 'a1 'a2) ($rem 'a0 'a1 'a2) ($remu 'a0 'a1 'a2) ($remw 'a0 'a1 'a2) ($remuw 'a0 'a1 'a2) |
a0 = a1 * a2
a0 = a1 / a2
a0 = a1 % a2 |
Lower result word Upper result word signed x signed Upper result word unsigned x unsigned Upper result word signed x unsigned Signed division Unsigned division |
Compare |
Set less than |
($slt 'a0 'a1 'a2) |
|
|
Logical |
AND AND immediate OR OR immediate XOR XOR immediate |
($and 'a0 'a1 'a2) ($andi 'a0 'a1 imm) ($or 'a0 'a1 'a2) ($ori 'a0 'a1 imm) ($xor 'a0 'a1 'a2) ($xori 'a0 'a1 imm) |
a0 = a1 AND a2 a0 = a1 AND imm a0 = a1 OR a2 a0 = a1 OR imm a0 = a1 XOR a2 a0 = a1 XOR imm |
Range -2048 to 2047
Range -2048 to 2047
Range -2048 to 2047 |
Shift/ |
Shift left logical Shift left logical word Shift left logical imm Shift right logical Shift right logical word Shift right logical imm Shift right arithmetic Shift right arith word Shift right arith imm |
($sll 'a0 'a1 'a2) ($sllw 'a0 'a1 'a2) ($slli 'a0 'a1 imm) ($srl 'a0 'a1 'a2) ($srlw 'a0 'a1 'a2) ($srli 'a0 'a1 imm) ($sra 'a0 'a1 'a2) ($sraw 'a0 'a1 'a2) ($srai 'a0 'a1 imm) |
a0 = a1 << a2 a0 = a1 << a2 a0 = a1 << imm a0 = a1 >> a2 a0 = a1 >> a2 a0 = a1 >> imm a0 = a1 >> a2 a0 = a1 >> a2 a0 = a1 >> imm |
Sign extended Sign extended Sign extended |
Load |
Load byte Load byte unsigned Load half Load half unsigned Load word Load word unsigned Load double Load immediate Load upper imm. |
($lb 'a0 imm '(a1)) ($lbu 'a0 imm '(a1)) ($lh 'a0 imm '(a1)) ($lhu 'a0 imm '(a1)) ($lw 'a0 imm '(a1)) ($lwu 'a0 imm '(a1)) ($ld 'a0 imm '(a1)) ($li 'a0 imm) ($lui 'a0 imm) |
a0 = (a1 + imm) a0 = (a1 + imm) a0 = (a1 + imm) a0 = (a1 + imm) a0 = (a1 + imm) a0 = (a1 + imm) a0 = (a1 + imm) a0 = imm a0 = imm[31:12] |
Sign extended Zero extended Sign extended Zero extended Sign extended Zero extended |
Store |
Store byte Store half Store word Store double |
($sb 'a0 imm '(a1)) ($sh 'a0 imm '(a1)) ($sw 'a0 imm '(a1)) ($sd 'a0 imm '(a1)) |
(a1 + imm) = a0 (a1 + imm) = a0 (a1 + imm) = a0 (a1 + imm) = a0 |
|
Extend | Sign extend word | ($sext.w 'a0 'a1) | a0 = sign extend a1 | Any except pc. |
Branch |
Branch = Branch = 0 Branch ≠ Branch ≠ 0 Branch ≤ Branch ≤ 0 Branch ≥ Branch ≥ unsigned Branch ≥ 0 Branch < Branch < unsigned Branch < 0 Branch > Branch > 0 |
($beq 'a0 'a1 label) ($beqz 'a0 label) ($bne 'a0 'a1 label) ($bnez 'a0 label) ($ble 'a0 'a1 label) ($blez 'a0 label) ($bge 'a0 'a1 label) ($bgeu 'a0 'a1 label) ($bgez 'a0 label) ($blt 'a0 'a1 label) ($bltu 'a0 'a1 label) ($bltz 'a0 label) ($bgt 'a0 'a1 label) ($bgtz 'a0 label) |
|
Range PC-4096 to PC+4095 |
Jump and link |
Jump Jump and link Jump and link Jump & link register Jump register |
($j label) ($jal label) ($jal 'a0 label) ($jalr label '(a0)) ($jr 'a0) |
PC = label PC = label, ra = next PC = label, a0 = next PC = label+a0, ra = next PC = a0 |
|
State | Fence | ($fence) | ||
No op | No operation | ($nop) |
I recommend this RISC-V quick ref card for a good introduction to programming in RISC-V assembler.