RISC-V Complete Documentation
Instructions
add reg, reg, reg
Addition: set t1 to (t2 plus t3)
addi reg, reg, [imm / %lo(id)]
Addition immediate: set t1 to (t2 plus signed 12-bit immediate)
Load Lower Address : Set t1 to t2 + lower 12-bit label's address
addiw reg, reg, imm
Addition immediate: set t1 to (t2 plus signed 12-bit immediate) using only the lower 32 bits (64bit)
addw reg, reg, reg
Addition: set t1 to (t2 plus t3) using only the lower 32 bits (64bit)
and reg, reg, reg
Bitwise AND : Set t1 to bitwise AND of t2 and t3
andi reg, reg, imm
Bitwise AND immediate : Set t1 to bitwise AND of t2 and sign-extended 12-bit immediate
auipc reg, imm
Add upper immediate to pc: set t1 to (pc plus an upper 20-bit immediate)
b id
Branch : Branch to statement at label unconditionally
beq reg, reg, id
Branch if equal : Branch to statement at label's address if t1 and t2 are equal
beqz reg, id
Branch if EQual Zero : Branch to statement at label if t1 == 0
bge reg, reg, id
Branch if greater than or equal: Branch to statement at label's address if t1 is greater than or equal to t2
bgeu reg, reg, id
Branch if greater than or equal to (unsigned): Branch to statement at label's address if t1 is greater than or equal to t2 (with an unsigned interpretation)
bgez reg, id
Branch if Greater than or Equal to Zero : Branch to statement at label if t1 >= 0
bgt reg, reg, id
Branch if Greater Than : Branch to statement at label if t1 > t2
bgtu reg, reg, id
Branch if Greater Than Unsigned: Branch to statement at label if t1 > t2 (unsigned compare)
bgtz reg, id
Branch if Greater Than Zero: Branch to statement at label if t1 > 0
ble reg, reg, id
Branch if Less or Equal : Branch to statement at label if t1 <= t2
bleu reg, reg, id
Branch if Less or Equal Unsigned : Branch to statement at label if t1 <= t2 (unsigned compare)
blez reg, id
Branch if Less than or Equal to Zero : Branch to statement at label if t1 <= 0
blt reg, reg, id
Branch if less than: Branch to statement at label's address if t1 is less than t2
bltu reg, reg, id
Branch if less than (unsigned): Branch to statement at label's address if t1 is less than t2 (with an unsigned interpretation)
bltz reg, id
Branch if Less Than Zero : Branch to statement at label if t1 < 0
bne reg, reg, id
Branch if not equal : Branch to statement at label's address if t1 and t2 are not equal
bnez reg, id
Branch if Not Equal Zero : Branch to statement at label if t1 != 0
call id
CALL: call a far-away subroutine
csrc reg, csr
Clear bits in control and status register
csrci csr, imm
Clear bits in control and status register
csrr reg, csr
Read control and status register
csrrc reg, csr, reg
Atomic Read/Clear CSR: read from the CSR into t0 and clear bits of the CSR according to t1
csrrci reg, csr, imm
Atomic Read/Clear CSR Immediate: read from the CSR into t0 and clear bits of the CSR according to a constant
csrrs reg, csr, reg
Atomic Read/Set CSR: read from the CSR into t0 and logical or t1 into the CSR
csrrsi reg, csr, imm
Atomic Read/Set CSR Immediate: read from the CSR into t0 and logical or a constant into the CSR
csrrw reg, csr, reg
Atomic Read/Write CSR: read from the CSR into t0 and write t1 into the CSR
csrrwi reg, csr, imm
Atomic Read/Write CSR Immediate: read from the CSR into t0 and write a constant into the CSR
csrs reg, csr
Set bits in control and status register
csrsi csr, imm
Set bits in control and status register
csrw reg, csr
Write control and status register
csrwi csr, imm
Write control and status register
div reg, reg, reg
Division: set t1 to the result of t2/t3
divu reg, reg, reg
Division: set t1 to the result of t2/t3 using unsigned division
divuw reg, reg, reg
Division: set t1 to the result of t2/t3 using unsigned division limited to 32 bits (64bit)
divw reg, reg, reg
Division: set t1 to the result of t2/t3 using only the lower 32 bits (64bit)
ebreak
Pause execution
ecall
Issue a system call : Execute the system call specified by value in a7
fabs.d freg, freg
Set f1 to the absolute value of f2 (64 bit)
fabs.s freg, freg
Set f1 to the absolute value of f2
fadd.d freg, freg, freg, rounding
Floating ADD (64 bit): assigns f1 to f2 + f3
fadd.s freg, freg, freg, rounding
Floating ADD: assigns f1 to f2 + f3
fclass.d reg, freg
Classify a floating point number (64 bit)
fclass.s reg, freg
Classify a floating point number
fcvt.d.l freg, reg, rounding
Convert double from long: Assigns the value of t1 to f1 (64bit)
Convert double from signed 64 bit integer: Assigns the value of t1 to f1 (64bit)
fcvt.d.lu freg, reg, rounding
Convert double from unsigned long: Assigns the value of t1 to f1 (64bit)
Convert double from unsigned 64 bit integer: Assigns the value of t1 to f1 (64bit)
fcvt.d.s freg, freg, rounding
Convert a float to a double: Assigned the value of f2 to f1
Convert float to double: Assigned the value of f2 to f1
fcvt.d.w freg, reg, rounding
Convert double from integer: Assigns the value of t1 to f1
Convert double from signed integer: Assigns the value of t1 to f1
fcvt.d.wu freg, reg, rounding
Convert double from unsigned integer: Assigns the value of t1 to f1
fcvt.l.d reg, freg, rounding
Convert 64 bit integer from double: Assigns the value of f1 (rounded) to t1 (64bit)
Convert signed 64 bit integer from double: Assigns the value of f1 (rounded) to t1 (64bit)
fcvt.l.s reg, freg, rounding
Convert 64 bit integer from float: Assigns the value of f1 (rounded) to t1 (64bit)
Convert signed 64 bit integer from float: Assigns the value of f1 (rounded) to t1 (64bit)
fcvt.lu.d reg, freg, rounding
Convert unsigned 64 bit integer from double: Assigns the value of f1 (rounded) to t1 (64bit)
fcvt.lu.s reg, freg, rounding
Convert unsigned 64 bit integer from float: Assigns the value of f1 (rounded) to t1 (64bit)
fcvt.s.d freg, freg, rounding
Convert a double to a float: Assigned the value of f2 to f1
Convert double to float: Assigned the value of f2 to f1
fcvt.s.l freg, reg, rounding
Convert float from long: Assigns the value of t1 to f1 (64bit)
Convert float from signed 64 bit integer: Assigns the value of t1 to f1 (64bit)
fcvt.s.lu freg, reg, rounding
Convert float from unsigned long: Assigns the value of t1 to f1 (64bit)
Convert float from unsigned 64 bit integer: Assigns the value of t1 to f1 (64bit)
fcvt.s.w freg, reg, rounding
Convert float from integer: Assigns the value of t1 to f1
Convert float from signed integer: Assigns the value of t1 to f1
fcvt.s.wu freg, reg, rounding
Convert float from unsigned integer: Assigns the value of t1 to f1
fcvt.w.d reg, freg, rounding
Convert integer from double: Assigns the value of f1 (rounded) to t1
Convert signed integer from double: Assigns the value of f1 (rounded) to t1
fcvt.w.s reg, freg, rounding
Convert integer from float: Assigns the value of f1 (rounded) to t1
Convert signed integer from float: Assigns the value of f1 (rounded) to t1
fcvt.wu.d reg, freg, rounding
Convert unsinged integer from double: Assigns the value of f1 (rounded) to t1
Convert unsigned integer from double: Assigns the value of f1 (rounded) to t1
fcvt.wu.s reg, freg, rounding
Convert unsinged integer from float: Assigns the value of f1 (rounded) to t1
Convert unsigned integer from float: Assigns the value of f1 (rounded) to t1
fdiv.d freg, freg, freg, rounding
Floating DIVide (64 bit): assigns f1 to f2 / f3
fdiv.s freg, freg, freg, rounding
Floating DIVide: assigns f1 to f2 / f3
fence imm, imm
Ensure that IO and memory accesses before the fence happen before the following IO and memory accesses as viewed by a different thread
fence.i
Ensure that stores to instruction memory are visible to instruction fetches
feq.d reg, freg, freg
Floating EQuals (64 bit): if f1 = f2, set t1 to 1, else set t1 to 0
feq.s reg, freg, freg
Floating EQuals: if f1 = f2, set t1 to 1, else set t1 to 0
fge.d reg, freg, freg
Floating Greater Than or Equal (64 bit): if f2 >= f3, set t1 to 1, else set t1 to 0
fge.s reg, freg, freg
Floating Greater Than or Equal: if f2 >= f3, set t1 to 1, else set t1 to 0
fgt.d reg, freg, freg
Floating Greater Than (64 bit): if f2 > f3, set t1 to 1, else set t1 to 0
fgt.s reg, freg, freg
Floating Greater Than: if f2 > f3, set t1 to 1, else set t1 to 0
fld freg, [imm(reg) / (reg) / imm / id / %lo(id)], [reg / (reg)]
Load a double from memory
Load Word: Set f1 to 64-bit value from effective memory word address
Load Word: Set f1 to 64-bit value from effective memory word address using t3 as a temporary
Load from Address
fle.d reg, freg, freg
Floating Less than or Equals (64 bit): if f1 <= f2, set t1 to 1, else set t1 to 0
fle.s reg, freg, freg
Floating Less than or Equals: if f1 <= f2, set t1 to 1, else set t1 to 0
flt.d reg, freg, freg
Floating Less Than (64 bit): if f1 < f2, set t1 to 1, else set t1 to 0
flt.s reg, freg, freg
Floating Less Than: if f1 < f2, set t1 to 1, else set t1 to 0
flw freg, [imm(reg) / (reg) / imm / id / %lo(id)], [reg / (reg)]
Load a float from memory
Load Word Coprocessor 1 : Set f1 to 32-bit value from effective memory word address
Load Word Coprocessor 1 : Set f1 to 32-bit value from effective memory word address using t3 as a temporary
Load from Address
fmadd.d freg, freg, freg, freg, rounding
Fused Multiply Add (64 bit): Assigns f2*f3+f4 to f1
fmadd.s freg, freg, freg, freg, rounding
Fused Multiply Add: Assigns f2*f3+f4 to f1
fmax.d freg, freg, freg
Floating MAXimum (64 bit): assigns f1 to the larger of f1 and f3
fmax.s freg, freg, freg
Floating MAXimum: assigns f1 to the larger of f1 and f3
fmin.d freg, freg, freg
Floating MINimum (64 bit): assigns f1 to the smaller of f1 and f3
fmin.s freg, freg, freg
Floating MINimum: assigns f1 to the smaller of f1 and f3
fmsub.d freg, freg, freg, freg, rounding
Fused Multiply Subatract: Assigns f2*f3-f4 to f1
Fused Multiply Subatract (64 bit): Assigns f2*f3-f4 to f1
fmsub.s freg, freg, freg, freg, rounding
Fused Multiply Subatract: Assigns f2*f3-f4 to f1
fmul.d freg, freg, freg, rounding
Floating MULtiply (64 bit): assigns f1 to f2 * f3
fmul.s freg, freg, freg, rounding
Floating MULtiply: assigns f1 to f2 * f3
fmv.d freg, freg
Move the value of f2 to f1 (64 bit)
fmv.d.x freg, reg
Move float: move bits representing a double from an 64 bit integer register (64bit)
fmv.s freg, freg
Move the value of f2 to f1
fmv.s.x freg, reg
Move float: move bits representing a float from an integer register
fmv.w.x freg, reg
Move float (New mnemonic): move bits representing a float from an integer register
fmv.x.d reg, freg
Move double: move bits representing a double to an 64 bit integer register (64bit)
fmv.x.s reg, freg
Move float: move bits representing a float to an integer register
fmv.x.w reg, freg
Move float (New mnemonic): move bits representing a float to an integer register
fneg.d freg, freg
Set f1 to the negation of f2 (64 bit)
fneg.s freg, freg
Set f1 to the negation of f2
fnmadd.d freg, freg, freg, freg, rounding
Fused Negate Multiply Add (64 bit): Assigns -(f2*f3+f4) to f1
fnmadd.s freg, freg, freg, freg, rounding
Fused Negate Multiply Add: Assigns -(f2*f3+f4) to f1
fnmsub.d freg, freg, freg, freg, rounding
Fused Negated Multiply Subatract: Assigns -(f2*f3-f4) to f1
Fused Negated Multiply Subatract (64 bit): Assigns -(f2*f3-f4) to f1
fnmsub.s freg, freg, freg, freg, rounding
Fused Negated Multiply Subatract: Assigns -(f2*f3-f4) to f1
frcsr reg
Read FP control/status register
frflags reg
Read FP exception flags
frrm reg
Read FP rounding mode
frsr reg
Alias for frcsr t1
fscsr reg, reg
Swap FP control/status register
Write FP control/status register
fsd freg, [imm(reg) / (reg) / imm / id], reg
Store a double to memory
Store Word: Store 64-bit value from f1 to effective memory word address
Store Word: Store 64-bit value from f1 to effective memory word address using t3 as a temporary
fsflags reg, reg
Swap FP exception flags
Write FP exception flags
fsgnj.d freg, freg, freg
Floating point sign injection (64 bit): replace the sign bit of f2 with the sign bit of f3 and assign it to f1
fsgnj.s freg, freg, freg
Floating point sign injection: replace the sign bit of f2 with the sign bit of f3 and assign it to f1
fsgnjn.d freg, freg, freg
Floating point sign injection (inverted 64 bit): replace the sign bit of f2 with the opposite of sign bit of f3 and assign it to f1
fsgnjn.s freg, freg, freg
Floating point sign injection (inverted): replace the sign bit of f2 with the opposite of sign bit of f3 and assign it to f1
fsgnjx.d freg, freg, freg
Floating point sign injection (xor 64 bit): xor the sign bit of f2 with the sign bit of f3 and assign it to f1
fsgnjx.s freg, freg, freg
Floating point sign injection (xor): xor the sign bit of f2 with the sign bit of f3 and assign it to f1
fsqrt.d freg, freg, rounding
Floating SQuare RooT (64 bit): Assigns f1 to the square root of f2
fsqrt.s freg, freg, rounding
Floating SQuare RooT: Assigns f1 to the square root of f2
fsrm reg, reg
Swap FP rounding mode
Write FP rounding mode
fssr reg, reg
Alias for fscsr t1, t2
Alias for fscsr t1
fsub.d freg, freg, freg, rounding
Floating SUBtract (64 bit): assigns f1 to f2 - f3
fsub.s freg, freg, freg, rounding
Floating SUBtract: assigns f1 to f2 - f3
fsw freg, [imm(reg) / (reg) / imm / id], reg
Store a float to memory
Store Word Coprocessor 1 : Store 32-bit value from f1 to effective memory word address
Store Word Coprocessor 1 : Store 32-bit value from f1 to effective memory word address using t3 as a temporary
j id
Jump : Jump to statement at label
jal [reg / id], id
Jump and link : Set t1 to Program Counter (return address) then jump to statement at target address
Jump And Link: Jump to statement at label and set the return address to ra
jalr reg, [reg / imm / imm(reg)], imm
Jump and link register: Set t1 to Program Counter (return address) then jump to statement at t2 + immediate
Jump And Link Register: Jump to address in t0 and set the return address to ra
Jump And Link Register: Jump to address in t1 and set the return address to t0
jr reg, imm
Jump Register: Jump to address in t0
la reg, id
Load Address : Set t1 to label's address
lb reg, [imm(reg) / (reg) / imm / id / %lo(id)], (reg)
Set t1 to sign-extended 8-bit value from effective memory byte address
Load Byte : Set t1 to sign-extended 8-bit value from effective memory byte address
Load Byte : Set $1 to sign-extended 8-bit value from effective memory byte address
Load Byte : Set $t1 to sign-extended 8-bit value from effective memory byte address
Load from Address
lbu reg, [imm(reg) / (reg) / imm / id]
Set t1 to zero-extended 8-bit value from effective memory byte address
Load Byte Unsigned : Set $t1 to zero-extended 8-bit value from effective memory byte address
Load Byte Unsigned : Set t1 to zero-extended 8-bit value from effective memory byte address
ld reg, [imm(reg) / (reg) / imm / id / %lo(id)], (reg)
Set t1 to contents of effective memory double word address (64bit)
Load Double word : Set t1 to contents of effective memory word address (64bit)
Load Double word : Set t1 to contents of memory word at label's address (64bit)
Load from Address (64bit)
lh reg, [imm(reg) / (reg) / imm / id / %lo(id)], (reg)
Set t1 to sign-extended 16-bit value from effective memory halfword address
Load Halfword : Set t1 to sign-extended 16-bit value from effective memory halfword address
Load from Address
lhu reg, [imm(reg) / (reg) / imm / id]
Set t1 to zero-extended 16-bit value from effective memory halfword address
Load Halfword Unsigned : Set t1 to zero-extended 16-bit value from effective memory halfword address
li reg, imm
Load Immediate : Set t1 to 12-bit immediate (sign-extended)
Load Immediate : Set t1 to 32-bit immediate
Load Immediate : Set t1 to 12-bit immediate (sign-extended) (64bit)
Load Immediate : Set t1 to 32-bit immediate (sign-extended) (64bit)
Load Immediate : Set t1 to 64-bit immediate (64bit)
lui reg, [imm / %hi(id)]
Load upper immediate: set t1 to 20-bit followed by 12 0s
Load Upper Address : Set t1 to upper 20-bit label's address
lw reg, [imm(reg) / (reg) / imm / id / %lo(id)], (reg)
Set t1 to contents of effective memory word address
Load Word : Set t1 to contents of effective memory word address
Load Word : Set t1 to contents of memory word at label's address
Load from Address
lwu reg, imm(reg)
Set t1 to contents of effective memory word address without sign-extension (64bit)
mul reg, reg, reg
Multiplication: set t1 to the lower 32 bits of t2*t3
mulh reg, reg, reg
Multiplication: set t1 to the upper 32 bits of t2*t3 using signed multiplication
mulhsu reg, reg, reg
Multiplication: set t1 to the upper 32 bits of t2*t3 where t2 is signed and t3 is unsigned
mulhu reg, reg, reg
Multiplication: set t1 to the upper 32 bits of t2*t3 using unsigned multiplication
mulw reg, reg, reg
Multiplication: set t1 to the lower 32 bits of t2*t3 using only the lower 32 bits of the input (64bit)
mv reg, reg
MoVe : Set t1 to contents of t2
neg reg, reg
NEGate : Set t1 to negation of t2
negw reg, reg
NEGate Word: Set t1 to negation of t2 (only lower 32 bits) (64bit)
nop
NO OPeration
not reg, reg
Bitwise NOT (bit inversion)
or reg, reg, reg
Bitwise OR : Set t1 to bitwise OR of t2 and t3
ori reg, reg, imm
Bitwise OR immediate : Set t1 to bitwise OR of t2 and sign-extended 12-bit immediate
rdcycle reg
Read from cycle
rdcycleh reg
Read from cycleh
rdinstret reg
Read from instret
rdinstreth reg
Read from instreth
rdtime reg
Read from time
rdtimeh reg
Read from timeh
rem reg, reg, reg
Remainder: set t1 to the remainder of t2/t3
remu reg, reg, reg
Remainder: set t1 to the remainder of t2/t3 using unsigned division
remuw reg, reg, reg
Remainder: set t1 to the remainder of t2/t3 using unsigned division limited to 32 bits (64bit)
remw reg, reg, reg
Remainder: set t1 to the remainder of t2/t3 using only the lower 32 bits (64bit)
ret
Return: return from a subroutine
sb reg, [imm(reg) / (reg) / imm / id], reg
Store byte : Store the low-order 8 bits of t1 into the effective memory byte address
Store Byte : Store the low-order 8 bits of t1 into the effective memory byte address
Store Byte : Store the low-order 8 bits of $t1 into the effective memory byte address
sd reg, imm(reg)
Store double word : Store contents of t1 into effective memory double word address (64bit)
seqz reg, reg
Set EQual to Zero : if t2 == 0 then set t1 to 1 else 0
sext.b reg, reg
Sign EXTend Byte: extract the low byte from t2 and sign extend it into t1
Sign EXTend Byte: extract the low byte from t2 and sign extend it into t1 (64bit)
sext.h reg, reg
Sign EXTend Half: extract the low 16 bit from t2 and sign extend it into t1
Sign EXTend Half: extract the low 16 bit from t2 and sign extend it into t1 (64bit)
sext.w reg, reg
Sign EXTend Word: extract the low 32-bits from t2 and sign extend it into t1 (64bit)
sgt reg, reg, reg
Set Greater Than : if t2 greater than t3 then set t1 to 1 else 0
sgtu reg, reg, reg
Set Greater Than Unsigned : if t2 greater than t3 (unsigned compare) then set t1 to 1 else 0
sgtz reg, reg
Set Greater Than Zero : if t2 > 0 then set t1 to 1 else 0
sh reg, [imm(reg) / (reg) / imm / id], reg
Store halfword : Store the low-order 16 bits of t1 into the effective memory halfword address
Store Halfword : Store the low-order 16 bits of $1 into the effective memory halfword address
Store Halfword : Store the low-order 16 bits of $t1 into the effective memory halfword address
Store Halfword : Store the low-order 16 bits of t1 into the effective memory halfword address using t2 as a temporary
sll reg, reg, reg
Shift left logical: Set t1 to result of shifting t2 left by number of bits specified by value in low-order 5 bits of t3
slli reg, reg, imm
Shift left logical : Set t1 to result of shifting t2 left by number of bits specified by immediate
Shift left logical : Set t1 to result of shifting t2 left by number of bits specified by immediate (64bit)
slliw reg, reg, imm
Shift left logical (32 bit): Set t1 to result of shifting t2 left by number of bits specified by immediate (64bit)
sllw reg, reg, reg
Shift left logical (32 bit): Set t1 to result of shifting t2 left by number of bits specified by value in low-order 5 bits of t3 (64bit)
slt reg, reg, reg
Set less than : If t2 is less than t3, then set t1 to 1 else set t1 to 0
slti reg, reg, imm
Set less than immediate : If t2 is less than sign-extended 12-bit immediate, then set t1 to 1 else set t1 to 0
sltiu reg, reg, imm
Set less than immediate unsigned : If t2 is less than sign-extended 16-bit immediate using unsigned comparison, then set t1 to 1 else set t1 to 0
sltu reg, reg, reg
Set less than : If t2 is less than t3 using unsigned comparision, then set t1 to 1 else set t1 to 0
sltz reg, reg
Set Less Than Zero : if t2 < 0 then set t1 to 1 else 0
snez reg, reg
Set Not Equal to Zero : if t2 != 0 then set t1 to 1 else 0
sra reg, reg, reg
Shift right arithmetic: Set t1 to result of sign-extended shifting t2 right by number of bits specified by value in low-order 5 bits of t3
srai reg, reg, imm
Shift right arithmetic : Set t1 to result of sign-extended shifting t2 right by number of bits specified by immediate
Shift right arithmetic : Set t1 to result of sign-extended shifting t2 right by number of bits specified by immediate (64bit)
sraiw reg, reg, imm
Shift right arithmetic (32 bit): Set t1 to result of sign-extended shifting t2 right by number of bits specified by immediate (64bit)
sraw reg, reg, reg
Shift left logical (32 bit): Set t1 to result of shifting t2 left by number of bits specified by value in low-order 5 bits of t3 (64bit)
srl reg, reg, reg
Shift right logical: Set t1 to result of shifting t2 right by number of bits specified by value in low-order 5 bits of t3
srli reg, reg, imm
Shift right logical : Set t1 to result of shifting t2 right by number of bits specified by immediate
Shift right logical : Set t1 to result of shifting t2 right by number of bits specified by immediate (64bit)
srliw reg, reg, imm
Shift right logical (32 bit): Set t1 to result of shifting t2 right by number of bits specified by immediate (64bit)
srlw reg, reg, reg
Shift left logical (32 bit): Set t1 to result of shifting t2 left by number of bits specified by value in low-order 5 bits of t3 (64bit)
sub reg, reg, reg
Subtraction: set t1 to (t2 minus t3)
subw reg, reg, reg
Subtraction: set t1 to (t2 minus t3) using only the lower 32 bits (64bit)
sw reg, [imm(reg) / (reg) / imm / id], reg
Store word : Store contents of t1 into effective memory word address
Store Word : Store t1 contents into effective memory word address
Store Word : Store $t1 contents into effective memory word address
Store Word : Store $t1 contents into effective memory word address using t2 as a temporary
Store Word : Store $t1 contents into memory word at label's address using t2 as a temporary
tail id
TAIL call: tail call (call without saving return address)a far-away subroutine
uret
Return from handling an interrupt or exception (to uepc)
wfi
Wait for Interrupt
xor reg, reg, reg
Bitwise XOR : Set t1 to bitwise XOR of t2 and t3
xori reg, reg, imm
Bitwise XOR immediate : Set t1 to bitwise XOR of t2 and sign-extended 12-bit immediate
zext.b reg, reg
Zero EXTend Byte: extract the low byte into t1
Zero EXTend Byte: extract the low byte into t1 (64bit)
zext.h reg, reg
Zero EXTend Half: extract the low 16 bit into t1
Zero EXTend Half: extract the low 16 bit into t1 (64bit)
zext.w reg, reg
Zero EXTend Word: extract the low 32-bits from t2 into t1 (64bit)
Directives
RISC-V directives are used to define the structure of the program. They are not instructions that are executed by the CPU, but rather instructions that are used by the assembler to define the structure of the program.
.data
Subsequent items stored in Data segment at next available address
.text
Subsequent items (instructions) stored in Text segment at next available address
.word
Store the listed value(s) as 32 bit words on word boundary
.dword
Store the listed value(s) as 64 bit double-word on word boundary
.ascii
Store the string in the Data segment but do not add null terminator
.asciz
Store the string in the Data segment and add null terminator
.string
Alias for .asciz
.byte
Store the listed value(s) as 8 bit bytes
.align
Align next data item on specified byte boundary (0=byte, 1=half, 2=word, 3=double)
.half
Store the listed value(s) as 16 bit halfwords on halfword boundary
.space
Reserve the next specified number of bytes in Data segment
.double
Store the listed value(s) as double precision floating point
.float
Store the listed value(s) as single precision floating point
.extern
Declare the listed label and byte length to be a global data field
.globl
Declare the listed label(s) as global to enable referencing from other files
.global
Declare the listed label(s) as global to enable referencing from other files
.eqv
Substitute second operand for first. First operand is symbol, second operand is expression (like #define)
.macro
Begin macro definition. See .end_macro
.end_macro
End macro definition. See .macro
.include
Insert the contents of the specified file. Put filename in quotes.
.section
Allows specifying sections without .text or .data directives. Included for gcc comparability
Syscalls
RISC-V syscalls are used to make requests to the operating system. They are not instructions that are executed by the CPU, but rather instructions that are used by the simulator to make requests to the operating system.
Each syscall has a unique code that is used to identify it. You must put the syscall code inside
the the a7 register before calling the ecall instruction.
As an example:
# Load the integer 42 into register a0, which is
# the register that will be printed by the syscall
li a0, 42
# Set the syscall code for printing an integer
li a7, 1
ecall
1 - Print integer
Arguments
2 - Print float
Arguments
3 - Print double
Arguments
4 - Print string
Arguments
5 - Read integer
Result
6 - Read float
Result
7 - Read double
Result
8 - Read string
Service 8 - Follows semantics of UNIX 'fgets'. For specified length n, string can be no longer than n-1. If less than that, adds newline to end. In either case, then pads with null byte If n = 1, input is ignored and null byte placed at buffer address. If n < 1, input is ignored and nothing is written to the buffer.
Arguments
9 - Sbrk (allocate heap memory)
Result
Arguments
10 - Exit (terminate execution)
11 - Print character
Service 11 - Prints ASCII character corresponding to contents of low-order byte.
Arguments
12 - Read character
Result
17 - Get cwd
30 - Time (program time)
Service 30 - Milliseconds since the run started, rather than since 1 January 1970 as in RARS: it is the time the program can observe passing, and in a testcase it comes from a virtual clock that starts at zero and only advances through the waits of service 32.
Result
32 - Sleep
Service 32 - Lets that much program time pass before the next instruction. The editor stays responsive while it waits and the wait costs no instructions, so a program idling on the keyboard never reaches the execution limit; in a testcase it completes at once and advances the virtual clock instead.
Arguments
34 - Print integer in hexadecimal
Displayed value is 8 hexadecimal digits, left-padding with zeroes if necessary.
Arguments
35 - Print integer in binary
Displayed value is 32 bits, left-padding with zeroes if necessary.
Arguments
36 - Print integer as unsigned
Displayed as unsigned decimal value.
Arguments
41 - Random int
Each stream (identified by a0 contents) is modeled by a different Random object. There are no default seed values, so use the Set Seed service (40) if replicated random sequences are desired.
Result
Arguments
42 - Random int range
Each stream (identified by a0 contents) is modeled by a different Random object. There are no default seed values, so use the Set Seed service (40) if replicated random sequences are desired.
Result
Arguments
43 - Random float
Each stream (identified by a0 contents) is modeled by a different Random object. There are no default seed values, so use the Set Seed service (40) if replicated random sequences are desired.
Result
Arguments
44 - Random double
Each stream (identified by a0 contents) is modeled by a different Random object. There are no default seed values, so use the Set Seed service (40) if replicated random sequences are desired.
Result
Arguments
50 - ConfirmDialog
Result
Arguments
51 - InputDialogInt
Result
Arguments
52 - InputDialogFloat
Result
Arguments
53 - InputDialogDouble
Result
Arguments
54 - InputDialogString
See Service 8 note below table
Result
Arguments
55 - MessageDialog
Arguments
56 - MessageDialogInt
Arguments
57 - Close file
Arguments
58 - MessageDialogDouble
Arguments
59 - MessageDialogString
Arguments
60 - MessageDialogFloat
Arguments
63 - Read from file
Result
Arguments
64 - Write to file
Result
Arguments
93 - Exit2 (terminate with value)
Service 93 - If the RISCV program is run under control of the MARS graphical interface (GUI), the exit code in a0 is ignored.
Arguments
1024 - Open file
Service 1024 - MARS implements three flag values: 0 for read-only, 1 for write-only with create, and 9 for write-only with create and append. It ignores mode. The returned file descriptor will be negative if the operation failed. MARS maintains file descriptors internally and allocates them starting with 3. File descriptors 0, 1 and 2 are always open for: reading from standard input, writing to standard output, and writing to standard error, respectively (new in release 4.3).
Result
Arguments
Screen and memory-mapped I/O
RISC-V programs draw and read input through memory, not through system calls: the screen is
a grid of words anywhere in memory, and the keyboard and the console are four words at 0xffff0000. Both are RARS's own tools, the bitmap display and the keyboard and display simulator, with the same parameters and the same
register layout, so a program written for RARS runs here unchanged.
Bitmap display
One word of memory is one pixel. Its low 24 bits are the color, red in bits 23-16, green in 15-8 and blue in 7-0; the top byte is ignored. Words run left to right and then top to bottom, so the pixel below a word is one row of words further on.
The screen panel's Display button configures it, with RARS's own five parameters, and a program can ask for them itself with the @screen comment below. The parameters are saved with the project, and testcases run with them too.
0x10000000 (global data), 0x10008000 ($gp), 0x10010000 (static data), 0x10040000 (heap), 0xffff0000 (memory map). Default 0x10010000 (static data), which
is where .data puts your first label. .data
display:.space 262144 # 256 * 256 words
.text
main:
la t0, display
li t1, 0x00ff8000 # low 24 bits: red 0xff, green 0x80, blue 0x00
sw t1, 0(t0) # the pixel at the top left
sw t1, 1024(t0) # 256 words further on: the one below it
Reserve the memory the grid covers, with .space or a label of your own: the
screen shows whatever those words hold, and a program that writes past what it reserved
is writing over something else. Undo walks the picture back with the code, because the
picture is the memory the emulator rolled back.
Configuring the screen from the program
A comment line naming @screen sets those five parameters at every Build, before the first instruction runs, so opening a program and
building it is all it takes. It is a comment, so the same file still assembles in
RARS, where you set the parameters in the tool's window as usual.
# @screen unit=1 width=256 height=256 base=display
.data
display:.space 262144 # 256 * 256 words
.text
main:
la t0, display
The display width in pixels, one of 64, 128, 256, 512, 1024.
The display height in pixels, one of 64, 128, 256, 512, 1024.
How many pixels wide and high one word is drawn, one of 1, 2, 4, 8, 16, 32. unitWidth and unitHeight set the two separately.
Where the grid starts: a label the program defines, which is the point of it — the program never has to know the address — or an address such as 0x10010000 or 268500992. A label not on a word boundary is rounded down to one.
- Order and spacing do not matter, commas are allowed between settings, and
unitWidth,unit-widthandunitwidthare the same name. - What the directive leaves out keeps the value it had, and a program with no
@screenline changes nothing at all: the configuration stays yours. - A value RARS has no entry for, an unknown setting or a label that does not exist is a warning on the directive's line, never an error: a comment cannot stop a program from assembling. A size off the list is replaced by the nearest one on it, and anything else is left as it was.
- Changing a parameter in the Display popover afterwards wins, until the next Build reads the comment again.
Keyboard and display registers
Four words carry one character each way. Click the screen panel to give the program the
keyboard; the ring around it says the editor's own shortcuts are off while it has focus.
What the program transmits is appended to the console transcript, the same one print services write to, which is also what testcases assert on.
Bit 0 is Ready: a typed character is waiting in the receiver data register. The device sets it and clears it; a program only reads it.
The typed character, in the low byte. Reading it takes that character; the next one, if any, appears at once and Ready stays set until the queue is empty.
Bit 0 is Ready, and here it is always set: the console never makes a program wait to print.
Storing a character in the low byte prints it on the console. ASCII 12, a form feed, clears the console instead.
li s0, 0xffff0000
poll:
lw t0, 0(s0) # receiver control
andi t0, t0, 1 # the Ready bit
bnez t0, take
li a7, 32 # nothing typed yet: a wait costs no instructions
li a0, 10
ecall
j poll
take:
lw t1, 4(s0) # receiver data, one character
sw t1, 12(s0) # transmitter data: print it
The receiver never loses a keystroke: what does not fit in the data register waits in a queue behind it, and Ready (1) stays set until that queue is empty. Bit 1 of either control register, RARS's interrupt-enable bit (2), stops the program with an error: this editor polls, it does not deliver device interrupts.
Program time
Service 30 (a7 before a ecall) answers
with the time in milliseconds, low word in a0 and high word in a1, and service 32 waits for the
milliseconds in a0. Time is counted from the start of the run
rather than from 1970, so a program differences two reads exactly as it did before, and
a wait costs no instructions — a program idling on the keyboard never reaches the
execution limit. In a testcase both run on a virtual clock that starts at zero and only
advances through the program's own waits, so a five second wait finishes at once and
elapsed-time output is the same on every machine.
Differences from RARS
- The display is always there: it is a panel next to the memory view rather than a tool you connect to the program before running it.
- Interrupt-driven I/O is not supported. Setting the interrupt-enable bit of a control register stops the program with an error naming the feature; poll the Ready bit instead.
- Time comes from the start of the run, and a testcase runs on a virtual clock. RARS answers with the host's wall clock.
- There is no mouse: neither simulator's tools have one.
- Programs live in
examples/risc-v/in the repository, one per feature, each naming the display it wants in an@screencomment; RARS has no such directive and ignores the line.