Skip to content Search Apps Documentation Source Content File Folder Download Copy Actions State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

Community realm. Read the code first. Community realm, deployed by its author. Read the code before you interact or send coins.

decode.gno

2.54 Kb · 73 lines
 1package riscv
 2
 3// RV32 instruction decode: bit fields, not a parser.
 4//
 5// Every instruction is exactly 32 bits and the opcode is the low 7. The rest is
 6// slicing: which fields exist depends on the format, and there are six formats.
 7// This file is only the slicing; exec.gno decides what the fields mean.
 8
 9// Instruction formats. Named as the spec names them.
10const (
11	opLUI    = 0x37
12	opAUIPC  = 0x17
13	opJAL    = 0x6F
14	opJALR   = 0x67
15	opBranch = 0x63
16	opLoad   = 0x03
17	opStore  = 0x23
18	opImm    = 0x13
19	opReg    = 0x33
20	opSystem = 0x73
21	opFence  = 0x0F
22)
23
24// opcode returns the low 7 bits.
25func opcode(inst uint32) uint32 { return inst & 0x7F }
26
27// rd, rs1 and rs2 are register selectors, 5 bits each, always in the same place
28// when the format has them.
29func rd(inst uint32) uint32  { return (inst >> 7) & 0x1F }
30func rs1(inst uint32) uint32 { return (inst >> 15) & 0x1F }
31func rs2(inst uint32) uint32 { return (inst >> 20) & 0x1F }
32
33// funct3 and funct7 narrow an opcode to an operation.
34func funct3(inst uint32) uint32 { return (inst >> 12) & 0x7 }
35func funct7(inst uint32) uint32 { return inst >> 25 }
36
37// The immediates. Each format scatters the bits differently, and every one of
38// them is SIGN EXTENDED from its top bit: RISC-V has no zero-extended immediate
39// in the base set, and getting that wrong is the classic decoder bug because
40// small positive programs still work.
41//
42// The shift-right-on-int32 idiom is the sign extension: Go defines >> on a
43// signed type as arithmetic.
44
45// immI is the 12-bit immediate of I-type (loads, ALU-immediate, JALR, ECALL).
46func immI(inst uint32) uint32 { return uint32(int32(inst) >> 20) }
47
48// immS is S-type (stores), split across two fields.
49func immS(inst uint32) uint32 {
50	return uint32(int32(inst)>>25<<5) | ((inst >> 7) & 0x1F)
51}
52
53// immB is B-type (branches): S-type with the bits rotated, and bit 0 always
54// zero because a branch target is 2-byte aligned.
55func immB(inst uint32) uint32 {
56	imm := uint32(int32(inst)>>31) << 12 // sign, bit 12
57	imm |= ((inst >> 7) & 0x1) << 11     // bit 11
58	imm |= ((inst >> 25) & 0x3F) << 5    // bits 10:5
59	imm |= ((inst >> 8) & 0xF) << 1      // bits 4:1
60	return imm
61}
62
63// immU is U-type (LUI, AUIPC): the top 20 bits, already in place.
64func immU(inst uint32) uint32 { return inst & 0xFFFFF000 }
65
66// immJ is J-type (JAL), the most scattered of the six.
67func immJ(inst uint32) uint32 {
68	imm := uint32(int32(inst)>>31) << 20 // sign, bit 20
69	imm |= ((inst >> 12) & 0xFF) << 12   // bits 19:12
70	imm |= ((inst >> 20) & 0x1) << 11    // bit 11
71	imm |= ((inst >> 21) & 0x3FF) << 1   // bits 10:1
72	return imm
73}