-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathriscv.go
190 lines (168 loc) · 3.36 KB
/
riscv.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
// RISC-V specific implementation logic - contains register enum and first step
// in instruction decode process.
package main
import (
"fmt"
"github.com/davecgh/go-spew/spew"
)
// Register represents a single riscv register file
type Register uint8
// variants of the risc-v register
const (
Zero Register = iota
Ra
Sp
Gp
Tp
T0
T1
T2
S0 // also FP
S1
A0
A1
A2
A3
A4
A5
A6
A7
S2
S3
S4
S5
S6
S7
S8
S9
S10
S11
T3
T4
T5
T6
Pc
)
func GetReg(reg uint32) Register {
if reg > 32 {
return Zero
}
return Register(uint8(reg))
}
type Instruction interface {
Decode(inst uint32) Instruction
}
// Rtype instructions represent register to register computations
type Rtype struct {
rd Register
funct3 uint32
rs1 Register
rs2 Register
funct7 uint32
}
func (Rtype) Decode(inst uint32) Instruction {
return Rtype{
rd: GetReg((inst >> 7) & 0b11111),
funct3: (inst >> 12) & 0b111,
rs1: GetReg((inst >> 15) & 0b11111),
rs2: GetReg((inst >> 20) & 0b11111),
funct7: (inst >> 25) & 0b1111111,
}
}
// Itype for loads and short immediate operations
type Itype struct {
rd Register
funct3 uint32
rs1 Register
imm int32
}
func (Itype) Decode(inst uint32) Instruction {
return Itype{
rd: GetReg((inst >> 7) & 0b11111),
funct3: (inst >> 12) & 0b111,
rs1: GetReg((inst >> 15) & 0b11111),
imm: int32(inst) >> 20,
}
}
// Stype for stores
type Stype struct {
funct3 uint32
rs1 Register
rs2 Register
imm int32
}
func (Stype) Decode(inst uint32) Instruction {
imm115 := (inst >> 25) & 0b1111111
imm40 := (inst >> 7) & 0b11111
imm := (imm115 << 5) | imm40
// sign extend imm
simm := (int32(imm) << 20) >> 20
return Stype{
funct3: (inst >> 12) & 0b111,
rs1: GetReg((inst >> 15) & 0b11111),
rs2: GetReg((inst >> 20) & 0b11111),
imm: simm,
}
}
// Btype for conditional branch operation
type Btype struct {
imm int32
funct3 uint32
rs1 Register
rs2 Register
}
func (Btype) Decode(inst uint32) Instruction {
imm12 := (inst >> 31) & 1
imm105 := (inst >> 25) & 0b111111
imm41 := (inst >> 8) & 0b1111
imm11 := (inst >> 7) & 1
imm := (imm12 << 12) | (imm11 << 11) | (imm105 << 5) | (imm41 << 1)
simm := (int32(imm) << 19) >> 19
return Btype{
rs1: GetReg((inst >> 15) & 0b11111),
rs2: GetReg((inst >> 20) & 0b11111),
funct3: (inst >> 12) & 0b111,
imm: simm,
}
}
// Utype for long immediate operations
type Utype struct {
rd Register
imm int32
}
func (Utype) Decode(inst uint32) Instruction {
imm := (inst >> 12) & 0xfffff
//simm := (int32(imm) << 11) >> 11
return Utype{
rd: GetReg((inst >> 7) & 0b11111),
imm: int32(imm),
}
}
// Jtype for unconditional jump operations
type Jtype struct {
rd Register
imm int32
}
func (Jtype) Decode(inst uint32) Instruction {
imm20 := (inst >> 31) & 1
imm101 := (inst >> 21) & 0b1111111111
imm11 := (inst >> 20) & 1
imm1912 := (inst >> 12) & 0b11111111
// shift bits to their position
imm := (imm20 << 20) | (imm1912 << 12) | (imm11 << 11) | (imm101 << 1)
// sign extend immediate
simm := (int32(imm) << 11) >> 11
return Jtype{
rd: GetReg((inst >> 7) & 0b11111),
imm: simm,
}
}
// Decode converts the binary instruction into its struct type
func Decode(inst uint32, instruction Instruction) Instruction {
dec := instruction.Decode(inst)
if VERBOSE_INST_DECODE {
spew.Dump(dec)
fmt.Println("")
}
return dec
}