RISC-V Instructions

  • Instruction syntax is rigid

    op dst, src1, src2
    • 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

# Fibonacci Sequence
main: 
	add t0, x0, x0
	addi t1, x0, 1
	la t3, n
	lw t3, 0(t3)
fib: 
	beq t3, x0, finish
	add t2, t1, t0
	mv t0, t1
	mv t1, t2
	addi t3, t3, -1
	j fib
finish:
	addi a0, x0, 1
	addi a1, t0, 0
	ecall
	addi a0, x0, 10
	ecall
  • 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
  • Integer Substraction(sub)
    • C: a = b - c;
    • RISC-V: sub s1, s2, s3

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 destination
    • bAddr = 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-extension
  • sb: save byte. Upper 24 bits are ignored.

For example, let memo at s0 = 0x00000180:

lb s1, 1(s0) 	# s1 = 0x00000001
lb s2, 0(s0)	# s2 = 0xffffff80
sb s2, 2(s0)	#(s0)= 0x00800180

Half-Word Instructions

  • sh, lh, behavior same as sb and lb

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 in reg2, go to label
    • 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 NameRISV-V
Shift Left Logicalsll s1, s2, s3
Shift Left Logical Immslli s1, s2, imm
Shift Right Logicalsrl s1, s2, s3
Shift Right Logical Immsrli srli, s1, s2, imm
Shift Right Arithmeticsra s1, s2, s3
Shift Right Arithmetic Immsrai, 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

RegisterNameUseSaver
x0zeroThe constant value 0N.A.
x1raReturn addressCaller
x2spStack pointerCallee
x3gpGlobal pointer
x4tpThread pointer
x5-x7t0-t2TemporariesCaller
x8s0/fpSaved register/Frame pointerCallee
x9s1Saved registerCallee
x10-x11a0-a1Function arguments/Return valuesCaller
x12-x17a2-a7Function argumentsCaller
x18-x27s2-s11Saved registersCallee
x28-x31t3-t6TemporariesCaller

Calling Convention

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

Translate C for loop into RISC-V

<preloop>
for (<initial>; <condition>; <increment>) {
	<body>
}
<postloop>
<preloop>
<initial>
loop_start:
	b !<condition>, loop_end
	<body>
	<increment>
	j loop_start
loop_end:
<postloop>