RV32C, RV64C Instructions

c.addi4spn

15-13 12-5 4-2 1-0
000 nzuimm[5:4|9:6|2|3] rd’ 00
Format:
c.addi4spn rd’,uimm
Description:
Add a zero-extended non-zero immediate, scaled by 4, to the stack pointer, x2, and writes the result to rd’.
This instruction is used to generate pointers to stack-allocated variables, and expands to addi rd’, x2, nzuimm[9:2].
Implementation:
x[8+rd’] = x[2] + nzuimm
Expansion:
addi rd’,x2,nzuimm

c.fld

15-13 12-10 9-7 6-5 4-2 1-0
001 uimm[5:3] rs1’ uimm[7:6] rd’ 00
Format:
c.fld rd’,uimm(rs1’)
Description:
Load a double-precision floating-point value from memory into floating-point register rd’.
It computes an effective address by adding the zero-extended offset, scaled by 8, to the base address in register rs1’.
Implementation:
f[8+rd’] = M[x[8+rs1’] + uimm][63:0]
Expansion:
fld rd’,offset[7:3](rs1’)

c.lw

15-13 12-10 9-7 6-5 4-2 1-0
010 uimm[5:3] rs1’ uimm[2|6] rd’ 00
Format:
c.lw rd’,uimm(rs1’)
Description:
Load a 32-bit value from memory into register rd’. It computes an effective address by adding the zero-extended offset, scaled by 4, to the base address in register rs1’.
Implementation:
x[8+rd’] = sext(M[x[8+rs1’] + uimm][31:0])
Expansion:
lw rd’,offset[6:2](rs1’)

c.flw

15-13 12-10 9-7 6-5 4-2 1-0
011 uimm[5:3] rs1’ uimm[2|6] rd’ 00
Format:
c.flw rd’,uimm(rs1’)
Description:
Load a single-precision floating-point value from memory into floating-point register rd’.
It computes an effective address by adding the zero-extended offset, scaled by 4, to the base address in register rs1’.
Implementation:
f[8+rd’] = M[x[8+rs1’] + uimm][31:0]
Expansion:
lw rd’,offset[6:2](rs1’)

c.ld

15-13 12-10 9-7 6-5 4-2 1-0
011 uimm[5:3] rs1’ uimm[7:6] rd’ 00
Format:
c.ld rd’,uimm(rs1’)
Description:
Load a 64-bit value from memory into register rd’.
It computes an effective address by adding the zero-extended offset, scaled by 8, to the base address in register rs1’.
Implementation:
x[8+rd’] = M[x[8+rs1’] + uimm][63:0]
Expansion:
ld rd’, offset[7:3](rs1’)

c.fsd

15-13 12-10 9-7 6-5 4-2 1-0
101 uimm[5:3] rs1’ uimm[7:6] rd’ 00
Format:
c.fsd rd’,uimm(rs1’)
Description:
Store a double-precision floating-point value in floating-point register rs2’ to memory.
It computes an effective address by adding the zeroextended offset, scaled by 8, to the base address in register rs1’.
Implementation:
M[x[8+rs1’] + uimm][63:0] = f[8+rs2’]
Expansion:
fsd rs2’,offset[7:3](rs1’)

c.sw

15-13 12-10 9-7 6-5 4-2 1-0
110 uimm[5:3] rs1’ uimm[2|6] rs2’ 00
Format:
c.sw rd’,uimm(rs1’)
Description:
Store a 32-bit value in register rs2’ to memory.
It computes an effective address by adding the zero-extended offset, scaled by 4, to the base address in register rs1’.
Implementation:
M[x[8+rs1’] + uimm][31:0] = x[8+rs2’]
Expansion:
sw rs2’,offset[6:2](rs1’)

c.fsw

15-13 12-10 9-7 6-5 4-2 1-0
111 uimm[5:3] rs1’ uimm[2|6] rs2’ 00
Format:
c.fsw rd’,uimm(rs1’)
Description:
Store a single-precision floating-point value in floatingpoint register rs2’ to memory.
It computes an effective address by adding the zero-extended offset, scaled by 4, to the base address in register rs1’.
Implementation:
M[x[8+rs1’] + uimm][31:0] = f[8+rs2’]
Expansion:
fsw rs2’, offset[6:2](rs1’)

c.sd

15-13 12-10 9-7 6-5 4-2 1-0
111 uimm[5:3] rs1’ uimm[7:6] rs2’ 00
Format:
c.sd rd’,uimm(rs1’)
Description:
Store a 64-bit value in register rs2’ to memory.
It computes an effective address by adding the zero-extended offset, scaled by 8, to the base address in register rs1’.
Implementation:
M[x[8+rs1’] + uimm][63:0] = x[8+rs2’]
Expansion:
sd rs2’, offset[7:3](rs1’)

c.nop

15-13 12-10 9-7 6-5 4-2 1-0
000 0 0 0 0 01
Format:
c.nop
Description:
Does not change any user-visible state, except for advancing the pc.
Implementation:
None
Expansion:
addi x0, x0, 0

c.addi

15-13 12 11-7 6-2 1-0
000 nzimm[5] rs1/rd!=0 nzimm[4:0] 01
Format:
c.addi rd,u[12:12]|u[6:2]
Description:
Add the non-zero sign-extended 6-bit immediate to the value in register rd then writes the result to rd.
Implementation:
x[rd] = x[rd] + sext(imm)
Expansion:
addi rd, rd, nzimm[5:0]

c.jal

15-13 12-2 1-0
001 imm[11|4|9:8|10|6|7|3:1|5] 01
Format:
c.jal offset
Description:
Jump to address and place return address in rd.
Implementation:
x[1] = pc+2; pc += sext(offset)
Expansion:
jal x1, offset[11:1]

c.addiw

15-13 12 11-7 6-2 1-0
001 imm[5] rd imm[4:0] 01
Format:
c.addiw rd,imm
Description:
Add the non-zero sign-extended 6-bit immediate to the value in register rd then produce 32-bit result, then sign-extends result to 64 bits.
Implementation:
x[rd] = sext((x[rd] + sext(imm))[31:0])
Expansion:
addiw rd,rd,imm[5:0]

c.li

15-13 12 11-7 6-2 1-0
010 imm[5] rd imm[4:0] 01
Format:
c.li rd,imm
Description:
Load the sign-extended 6-bit immediate, imm, into register rd.
C.LI is only valid when rd!=x0.
Implementation:
x[rd] = sext(imm)
Expansion:
addi rd,x0,imm[5:0]

c.addi16sp

15-13 12 11-7 6-2 1-0
011 imm[9] 00010 imm[4|6|8:7|5] 01
Format:
c.addi16sp imm
Description:
Add the non-zero sign-extended 6-bit immediate to the value in the stack pointer (sp=x2), where the immediate is scaled to represent multiples of 16 in the range (-512,496).
Implementation:
x[2] = x[2] + sext(imm)
Expansion:
addi x2,x2, nzimm[9:4]

c.lui

15-13 12 11-7 6-2 1-0
011 imm[17] rd imm[16:12] 01
Format:
c.lui rd,imm
Description:

Implementation:
x[rd] = sext(imm[17:12] << 12)
Expansion:
lui rd,nzuimm[17:12]

c.srli

15-13 12 11-10 9-7 6-2 1-0
100 uimm[5] 00 rd’ uimm[4:0] 01
Format:
c.srli rd’,uimm
Description:
Perform a logical right shift of the value in register rd’ then writes the result to rd’.
The shift amount is encoded in the shamt field, where shamt[5] must be zero for RV32C.
Implementation:
x[8+rd’] = x[8+rd’] >>u uimm
Expansion:
srli rd’,rd’,shamt[5:0]

c.srai

15-13 12 11-10 9-7 6-2 1-0
100 uimm[5] 01 rd’ uimm[4:0] 01
Format:
c.srai rd’,uimm
Description:
Perform a arithmetic right shift of the value in register rd’ then writes the result to rd’.
The shift amount is encoded in the shamt field, where shamt[5] must be zero for RV32C.
Implementation:
x[8+rd’] = x[8+rd’] >>s uimm
Expansion:
srai rd’,rd’,shamt[5:0]

c.andi

15-13 12 11-10 9-7 6-2 1-0
100 imm[5] 10 rd’ imm[4:0] 01
Format:
c.andi rd’,imm
Description:
Compute the bitwise AND of of the value in register rd’ and the sign-extended 6-bit immediate, then writes the result to rd’.
Implementation:
x[8+rd’] = x[8+rd’] & sext(imm)
Expansion:
andi rd’,rd’,imm[5:0]

c.sub

15-10 9-7 6-5 4-2 1-0
100011 rd’ 00 rs2’ 01
Format:
c.sub rd’,rs2’
Description:
Subtract the value in register rs2’ from the value in register rd’, then writes the result to register rd’.
Implementation:
x[8+rd’] = x[8+rd’] - x[8+rs2’]
Expansion:
sub rd’,rd’,rs2’

c.xor

15-10 9-7 6-5 4-2 1-0
100011 rd’ 01 rs2’ 01
Format:
c.xor rd’,rs2’
Description:
Compute the bitwise XOR of the values in registers rd’ and rs2’, then writes the result to register rd’.
Implementation:
x[8+rd’] = x[8+rd’] ^ x[8+rs2’]
Expansion:
xor rd’,rd’,rs2’

c.or

15-10 9-7 6-5 4-2 1-0
100011 rd’ 10 rs2’ 01
Format:
c.or rd’,rs2’
Description:
Compute the bitwise OR of the values in registers rd’ and rs2’, then writes the result to register rd’.
Implementation:
x[8+rd’] = x[8+rd’] | x[8+rs2’]
Expansion:
or rd’,rd’,rs2

c.and

15-10 9-7 6-5 4-2 1-0
100011 rd’ 11 rs2’ 01
Format:
c.and rd’,rs2’
Description:
Compute the bitwise AND of the values in registers rd’ and rs2’, then writes the result to register rd’.
Implementation:
x[8+rd’] = x[8+rd’] & x[8+rs2’]
Expansion:
and rd’,rd’,rs2’

c.subw

15-10 9-7 6-5 4-2 1-0
100111 rd’ 00 rs2’ 01
Format:
c.subw rd’,rs2’
Description:
Subtract the value in register rs2’ from the value in register rd’, then sign-extends the lower 32 bits of the difference before writing the result to register rd’.
Implementation:
x[8+rd’] = sext((x[8+rd’] - x[8+rs2’])[31:0])
Expansion:
subw rd’,rd’,rs2’

c.addw

15-10 9-7 6-5 4-2 1-0
100111 rd’ 01 rs2’ 01
Format:
c.addw rd’,rs2’
Description:
Add the value in register rs2’ from the value in register rd’, then sign-extends the lower 32 bits of the difference before writing the result to register rd’.
Implementation:
x[8+rd’] = sext((x[8+rd’] + x[8+rs2’])[31:0])
Expansion:
addw rd’,rd’,rs2’

c.j

15-13 12-2 1-0
101 imm[11|4|9:8|10|6|7|3:1|5] 01
Format:
c.j offset
Description:
Unconditional control transfer.
Implementation:
pc += sext(offset)
Expansion:
jal x0,offset[11:1]

c.beqz

15-13 12-10 9-7 6-2 1-0
110 offset[8|4:3] rs1’ offset[7:6|2:1|5] 01
Format:
c.beqz rs1’,offset
Description:
Take the branch if the value in register rs1’ is zero.
Implementation:
if (x[8+rs1’] == 0) pc += sext(offset)
Expansion:
beq rs1’,x0,offset[8:1]

c.bnez

15-13 12-10 9-7 6-2 1-0
111 offset[8|4:3] rs1’ offset[7:6|2:1|5] 01
Format:
c.bnez rs1’,offset
Description:
Take the branch if the value in register rs1’ is not zero.
Implementation:
if (x[8+rs1’] != 0) pc += sext(offset)
Expansion:
bne rs1’,x0,offset[8:1]

c.slli

15-13 12 11-7 6-2 1-0
010 uimm[5] rd uimm[4:0] 10
Format:
c.slli rd,uimm
Description:
Perform a logical left shift of the value in register rd then writes the result to rd.
The shift amount is encoded in the shamt field, where shamt[5] must be zero for RV32C.
Implementation:
x[rd] = x[rd] << uimm
Expansion:
slli rd,rd,shamt[5:0]

c.fldsp

15-13 12 11-7 6-2 1-0
001 uimm[5] rd uimm[4:3|8:6] 10
Format:
c.fldsp rd,uimm(x2)
Description:
Load a double-precision floating-point value from memory into floating-point register rd.
It computes its effective address by adding the zero-extended offset, scaled by 8, to the stack pointer, x2.
Implementation:
f[rd] = M[x[2] + uimm][63:0]
Expansion:
fld rd,offset[8:3](x2)

c.lwsp

15-13 12 11-7 6-2 1-0
010 uimm[5] rd uimm[4:2|7:6] 10
Format:
c.lwsp rd,uimm(x2)
Description:
Load a 32-bit value from memory into register rd. It computes an effective address by adding the zero-extended offset, scaled by 4, to the stack pointer, x2.
Implementation:
x[rd] = sext(M[x[2] + uimm][31:0])
Expansion:
lw rd,offset[7:2](x2)

c.flwsp

15-13 12 11-7 6-2 1-0
011 uimm[5] rd uimm[4:2|7:6] 10
Format:
c.flwsp rd,uimm(x2)
Description:
Load a single-precision floating-point value from memory into floating-point register rd.
It computes its effective address by adding the zero-extended offset, scaled by 4, to the stack pointer, x2.
Implementation:
f[rd] = M[x[2] + uimm][31:0]
Expansion:
flw rd,offset[7:2](x2)

c.ldsp

15-13 12 11-7 6-2 1-0
011 uimm[5] rd uimm[4:3|8:6] 10
Format:
c.ldsp rd,uimm(x2)
Description:
Load a 64-bit value from memory into register rd.
It computes its effective address by adding the zero-extended offset, scaled by 8, to the stack pointer, x2.
Implementation:
x[rd] = M[x[2] + uimm][63:0]
Expansion:
ld rd,offset[8:3](x2)

c.jr

15-13 12 11-7 6-2 1-0
100 0 rs1 00000 10
Format:
c.jr rs1
Description:
Performs an unconditional control transfer to the address in register rs1.
Implementation:
pc = x[rs1]
Expansion:
jalr x0,rs1,0

c.mv

15-13 12 11-7 6-2 1-0
100 0 rd rs2 10
Format:
c.mv rd,rs2
Description:
Copy the value in register rs2 into register rd.
Implementation:
x[rd] = x[rs2]
Expansion:
add rd, x0, rs2

c.ebreak

15-13 12 11-7 6-2 1-0
100 1 00000 00000 10
Format:
c.ebreak
Description:
Cause control to be transferred back to the debugging environment.
Implementation:
RaiseException(Breakpoint)
Expansion:
ebreak

c.jalr

15-13 12 11-7 6-2 1-0
100 1 rs1 00000 10
Format:
c.jalr rd
Description:
Jump to address and place return address in rd.
Implementation:
t = pc+2; pc = x[rs1]; x[1] = t
Expansion:
jalr x1,rs1,0

c.add

15-13 12 11-7 6-2 1-0
100 1 rd rs2 10
Format:
c.add rd,rs2
Description:
Add the values in registers rd and rs2 and writes the result to register rd.
Implementation:
x[rd] = x[rd] + x[rs2]
Expansion:
add rd,rd,rs2

c.fsdsp

15-13 12-7 4-2 1-0
101 uimm[5:3|8:6] rs2 10
Format:
c.fsdsp rs2,uimm(x2)
Description:
Store a double-precision floating-point value in floating-point register rs2 to memory.
It computes an effective address by adding the zeroextended offset, scaled by 8, to the stack pointer, x2.
Implementation:
M[x[2] + uimm][63:0] = f[rs2]
Expansion:
fsd rs2,offset[8:3](x2)

c.swsp

15-13 12-7 4-2 1-0
110 uimm[5:2|7:6] rs2 10
Format:
c.swsp rs2,uimm(x2)
Description:
Store a 32-bit value in register rs2 to memory.
It computes an effective address by adding the zero-extended offset, scaled by 4, to the stack pointer, x2.
Implementation:
M[x[2] + uimm][31:0] = x[rs2]
Expansion:
sw rs2,offset[7:2](x2)

c.fswsp

15-13 12-7 4-2 1-0
111 uimm[5:2|7:6] rs2 10
Format:
c.fswsp rs2,uimm(rs2)
Description:
Store a single-precision floating-point value in floating-point register rs2 to memory.
It computes an effective address by adding the zero-extended offset, scaled by 4, to the stack pointer, x2.
Implementation:
M[x[2] + uimm][31:0] = f[rs2]
Expansion:
fsw rs2,offset[7:2](x2)

c.sdsp

15-13 12-7 4-2 1-0
111 uimm[5:3|8:6] rs2 10
Format:
c.sdsp rs2,uimm(x2)
Description:
Store a 64-bit value in register rs2 to memory.
It computes an effective address by adding the zero-extended offset, scaled by 8, to the stack pointer, x2.
Implementation:
M[x[2] + uimm][63:0] = x[rs2]
Expansion:
sd rs2,offset[8:3](x2)