-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDecoder.cpp
More file actions
189 lines (160 loc) · 6.07 KB
/
Decoder.cpp
File metadata and controls
189 lines (160 loc) · 6.07 KB
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
#include "Decoder.h"
#include "Constants.h"
Decoder::Decoder() {
initDecodeTable();
}
int32_t Decoder::signExtend(uint32_t value, int bitWidth) {
int32_t signedValue = (int32_t)(value << (32 - bitWidth));
return signedValue >> (32 - bitWidth);
}
Decoder::DecodedInstr Decoder::decode(uint32_t instr) {
uint8_t opcode = instr & 0x7F;
if (decodeTable[opcode]) {
return decodeTable[opcode](instr);
}
else {
std::cout << "Unknown Opcode " << std::to_string(opcode) << std::endl;
return DecodedInstr{};
}
}
void Decoder::initDecodeTable() {
decodeTable[0b0110011] = decodeR; // OP
decodeTable[0b0010011] = decodeI; // OP-IMM
decodeTable[0b0000011] = decodeI; // LOAD
decodeTable[0b1100111] = decodeI; // JALR
decodeTable[0b1110011] = decodeI; // SYSTEM
decodeTable[0b0100011] = decodeS; // STORE
decodeTable[0b1100011] = decodeB; // BRANCH
decodeTable[0b0110111] = decodeU; // LUI
decodeTable[0b0010111] = decodeU; // AUIPC
decodeTable[0b1101111] = decodeJ; // JAL
}
Decoder::DecodedInstr Decoder::decodeR(uint32_t instr) {
return DecodedInstr(
uint8_t(instr & 0x7F), // opcode
uint8_t((instr >> 12) & 0x07), // funct3
uint8_t((instr >> 25) & 0x7F), // funct7
uint8_t((instr >> 7) & 0x1F), // rd
uint8_t((instr >> 15) & 0x1F), // rs1
uint8_t((instr >> 20) & 0x1F), // rs2
0, // imm
"R" // type
);
}
Decoder::DecodedInstr Decoder::decodeI(uint32_t instr) {
uint32_t opcode = uint8_t(instr & 0x7F);
uint32_t funct3 = uint8_t((instr >> 12) & 0x07);
uint32_t rd = uint8_t((instr >> 7) & 0x1F);
uint32_t rs1 = uint8_t((instr >> 15) & 0x1F);
uint32_t imm12 = (instr >> 20) & 0xFFF;
int32_t imm = signExtend(imm12, 12);
// Detect ECALL instruction: opcode=0x73, funct3=0, rd=0, rs1=0, imm12=0
if (opcode == 0x73 && funct3 == 0 && rd == 0 && rs1 == 0 && imm12 == 0) {
return DecodedInstr(
opcode, // opcode
funct3, // funct3
0, // funct7 unused
rd, // rd
rs1, // rs1
0, // rs2 unused
0, // imm unused for ECALL
"ECALL" // type
);
}
// Detect JALR: opcode=0x67 (0b1100111), funct3=0
if (opcode == 0x67 && funct3 == 0) {
// JALR is I-type with rs1 and imm
return DecodedInstr(
opcode,
funct3,
0, // funct7 unused
rd,
rs1,
0,
imm,
"JALR"
);
}
// normal I-type
return DecodedInstr(
opcode, // opcode
funct3, // funct3
0, // funct7 unused
rd, // rd
rs1, // rs1
0, // rs2 unused
imm, // signed immediate
"I" // type
);
}
Decoder::DecodedInstr Decoder::decodeS(uint32_t instr) {
uint8_t imm4_0 = (instr >> 7) & 0x1F; // bits 11:7
uint8_t imm11_5 = (instr >> 25) & 0x7F; // bits 31:25
int32_t imm = signExtend((imm11_5 << 5) | imm4_0, BITWIDTH_12);
return DecodedInstr(
uint8_t(instr & 0x7F), // opcode
uint8_t((instr >> 12) & 0x07), // funct3
0, // funct7 unused
0, // rd unused
uint8_t((instr >> 15) & 0x1F), // rs1
uint8_t((instr >> 20) & 0x1F), // rs2
imm, // signed immediate
"S" // type
);
}
Decoder::DecodedInstr Decoder::decodeB(uint32_t instr) {
uint32_t imm12 = (instr >> 31) & 0x1; // bit 31
uint32_t imm10_5 = (instr >> 25) & 0x3F; // bits 30:25
uint32_t imm4_1 = (instr >> 8) & 0xF; // bits 11:8
uint32_t imm11 = (instr >> 7) & 0x1; // bit 7
uint32_t immCombined =
(imm12 << 12) |
(imm11 << 11) |
(imm10_5 << 5) |
(imm4_1 << 1);
int32_t imm = signExtend(immCombined, 13);
return DecodedInstr(
uint8_t(instr & 0x7F), // opcode
uint8_t((instr >> 12) & 0x07), // funct3
0, // funct7 unused
0, // rd unused
uint8_t((instr >> 15) & 0x1F), // rs1
uint8_t((instr >> 20) & 0x1F), // rs2
imm, // signed immediate
"B" // type
);
}
Decoder::DecodedInstr Decoder::decodeU(uint32_t instr) {
return DecodedInstr(
uint8_t(instr & 0x7F), // opcode
0, // funct3
0, // funct7 unused
uint8_t((instr >> 7) & 0x1F), // rd
0, // rs1
0, // rs2
uint32_t(instr & 0xFFFFF000), // immediate
"U" // type
);
}
Decoder::DecodedInstr Decoder::decodeJ(uint32_t instr) {
uint32_t imm20 = (instr >> 31) & 0x1; // bit 31
uint32_t imm10_1 = (instr >> 21) & 0x3FF; // bits [30:21]
uint32_t imm11 = (instr >> 20) & 0x1; // bit 20
uint32_t imm19_12 = (instr >> 12) & 0xFF; // bits [19:12]
uint32_t immCombined =
(imm20 << 20) |
(imm19_12 << 12) |
(imm11 << 11) |
(imm10_1 << 1);
int32_t imm = signExtend(immCombined, 21);
return DecodedInstr(
uint8_t(instr & 0x7F), // opcode
0, // funct3 unused
0, // funct7 unused
uint8_t((instr >> 7) & 0x1F), // rd
0, // rs1 unused
0, // rs2 unused
imm, // signed immediate
"J" // type
);
}