lib/std/arch/rv64/decode.rad 14.3 KiB raw
1
//! RV64 instruction decoder.
2
//!
3
//! Decodes 32-bit instruction words into structured representations.
4
5
use std::lang::gen;
6
use super::encode;
7
8
///////////////////////
9
// Field Extraction  //
10
///////////////////////
11
12
/// Extract opcode (bits 6:0).
13
pub fn opcode(instr: u32) -> u32 {
14
    return instr & 0x7F;
15
}
16
17
/// Extract rd (bits 11:7).
18
pub fn rd(instr: u32) -> u8 {
19
    return ((instr >> 7) & 0x1F) as u8;
20
}
21
22
/// Extract funct3 (bits 14:12).
23
pub fn funct3(instr: u32) -> u32 {
24
    return (instr >> 12) & 0x07;
25
}
26
27
/// Extract rs1 (bits 19:15).
28
pub fn rs1(instr: u32) -> u8 {
29
    return ((instr >> 15) & 0x1F) as u8;
30
}
31
32
/// Extract rs2 (bits 24:20).
33
pub fn rs2(instr: u32) -> u8 {
34
    return ((instr >> 20) & 0x1F) as u8;
35
}
36
37
/// Extract funct7 (bits 31:25).
38
pub fn funct7(instr: u32) -> u32 {
39
    return instr >> 25;
40
}
41
42
//////////////////////////
43
// Immediate Extraction //
44
//////////////////////////
45
46
/// Extract I-type immediate (sign-extended).
47
pub fn immI(instr: u32) -> i32 {
48
    let imm = instr >> 20;
49
    if (imm & 0x800) != 0 {
50
        return (imm | 0xFFFFF000) as i32;
51
    }
52
    return imm as i32;
53
}
54
55
/// Extract S-type immediate (sign-extended).
56
pub fn immS(instr: u32) -> i32 {
57
    let lo = (instr >> 7) & 0x1F;
58
    let hi = (instr >> 25) & 0x7F;
59
    let imm = (hi << 5) | lo;
60
    if (imm & 0x800) != 0 {
61
        return (imm | 0xFFFFF000) as i32;
62
    }
63
    return imm as i32;
64
}
65
66
/// Extract B-type immediate (sign-extended).
67
pub fn immB(instr: u32) -> i32 {
68
    let imm11 = (instr >> 7) & 0x1;
69
    let imm4_1 = (instr >> 8) & 0xF;
70
    let imm10_5 = (instr >> 25) & 0x3F;
71
    let imm12 = (instr >> 31) & 0x1;
72
    let imm = (imm12 << 12) | (imm11 << 11) | (imm10_5 << 5) | (imm4_1 << 1);
73
    if (imm & 0x1000) != 0 {
74
        return (imm | 0xFFFFE000) as i32;
75
    }
76
    return imm as i32;
77
}
78
79
/// Extract J-type immediate (sign-extended).
80
pub fn immJ(instr: u32) -> i32 {
81
    let imm19_12 = (instr >> 12) & 0xFF;
82
    let imm11 = (instr >> 20) & 0x1;
83
    let imm10_1 = (instr >> 21) & 0x3FF;
84
    let imm20 = (instr >> 31) & 0x1;
85
    let imm = (imm20 << 20) | (imm19_12 << 12) | (imm11 << 11) | (imm10_1 << 1);
86
    if (imm & 0x100000) != 0 {
87
        return (imm | 0xFFE00000) as i32;
88
    }
89
    return imm as i32;
90
}
91
92
/// Extract U-type immediate (upper 20 bits, sign-extended).
93
pub fn immU(instr: u32) -> i32 {
94
    let imm = instr >> 12;
95
    if (imm & 0x80000) != 0 {
96
        return (imm | 0xFFF00000) as i32;
97
    }
98
    return imm as i32;
99
}
100
101
/////////////////////////
102
// Decoded Instruction //
103
/////////////////////////
104
105
/// Decoded RV64 instruction.
106
pub union Instr {
107
    // R-type ALU.
108
    Add  { rd: gen::Reg, rs1: gen::Reg, rs2: gen::Reg },
109
    Sub  { rd: gen::Reg, rs1: gen::Reg, rs2: gen::Reg },
110
    Sll  { rd: gen::Reg, rs1: gen::Reg, rs2: gen::Reg },
111
    Slt  { rd: gen::Reg, rs1: gen::Reg, rs2: gen::Reg },
112
    Sltu { rd: gen::Reg, rs1: gen::Reg, rs2: gen::Reg },
113
    Xor  { rd: gen::Reg, rs1: gen::Reg, rs2: gen::Reg },
114
    Srl  { rd: gen::Reg, rs1: gen::Reg, rs2: gen::Reg },
115
    Sra  { rd: gen::Reg, rs1: gen::Reg, rs2: gen::Reg },
116
    Or   { rd: gen::Reg, rs1: gen::Reg, rs2: gen::Reg },
117
    And  { rd: gen::Reg, rs1: gen::Reg, rs2: gen::Reg },
118
119
    // R-type M extension.
120
    Mul    { rd: gen::Reg, rs1: gen::Reg, rs2: gen::Reg },
121
    Mulh   { rd: gen::Reg, rs1: gen::Reg, rs2: gen::Reg },
122
    Mulhsu { rd: gen::Reg, rs1: gen::Reg, rs2: gen::Reg },
123
    Mulhu  { rd: gen::Reg, rs1: gen::Reg, rs2: gen::Reg },
124
    Div    { rd: gen::Reg, rs1: gen::Reg, rs2: gen::Reg },
125
    Divu   { rd: gen::Reg, rs1: gen::Reg, rs2: gen::Reg },
126
    Rem    { rd: gen::Reg, rs1: gen::Reg, rs2: gen::Reg },
127
    Remu   { rd: gen::Reg, rs1: gen::Reg, rs2: gen::Reg },
128
129
    // R-type RV64 word operations.
130
    Addw  { rd: gen::Reg, rs1: gen::Reg, rs2: gen::Reg },
131
    Subw  { rd: gen::Reg, rs1: gen::Reg, rs2: gen::Reg },
132
    Sllw  { rd: gen::Reg, rs1: gen::Reg, rs2: gen::Reg },
133
    Srlw  { rd: gen::Reg, rs1: gen::Reg, rs2: gen::Reg },
134
    Sraw  { rd: gen::Reg, rs1: gen::Reg, rs2: gen::Reg },
135
    Mulw  { rd: gen::Reg, rs1: gen::Reg, rs2: gen::Reg },
136
    Divw  { rd: gen::Reg, rs1: gen::Reg, rs2: gen::Reg },
137
    Divuw { rd: gen::Reg, rs1: gen::Reg, rs2: gen::Reg },
138
    Remw  { rd: gen::Reg, rs1: gen::Reg, rs2: gen::Reg },
139
    Remuw { rd: gen::Reg, rs1: gen::Reg, rs2: gen::Reg },
140
141
    // I-type ALU.
142
    Addi  { rd: gen::Reg, rs1: gen::Reg, imm: i32 },
143
    Slti  { rd: gen::Reg, rs1: gen::Reg, imm: i32 },
144
    Sltiu { rd: gen::Reg, rs1: gen::Reg, imm: i32 },
145
    Xori  { rd: gen::Reg, rs1: gen::Reg, imm: i32 },
146
    Ori   { rd: gen::Reg, rs1: gen::Reg, imm: i32 },
147
    Andi  { rd: gen::Reg, rs1: gen::Reg, imm: i32 },
148
    Slli  { rd: gen::Reg, rs1: gen::Reg, shamt: i32 },
149
    Srli  { rd: gen::Reg, rs1: gen::Reg, shamt: i32 },
150
    Srai  { rd: gen::Reg, rs1: gen::Reg, shamt: i32 },
151
152
    // I-type RV64 word immediate operations.
153
    Addiw { rd: gen::Reg, rs1: gen::Reg, imm: i32 },
154
    Slliw { rd: gen::Reg, rs1: gen::Reg, shamt: i32 },
155
    Srliw { rd: gen::Reg, rs1: gen::Reg, shamt: i32 },
156
    Sraiw { rd: gen::Reg, rs1: gen::Reg, shamt: i32 },
157
158
    // Load instructions.
159
    Lb  { rd: gen::Reg, rs1: gen::Reg, imm: i32 },
160
    Lh  { rd: gen::Reg, rs1: gen::Reg, imm: i32 },
161
    Lw  { rd: gen::Reg, rs1: gen::Reg, imm: i32 },
162
    Ld  { rd: gen::Reg, rs1: gen::Reg, imm: i32 },
163
    Lbu { rd: gen::Reg, rs1: gen::Reg, imm: i32 },
164
    Lhu { rd: gen::Reg, rs1: gen::Reg, imm: i32 },
165
    Lwu { rd: gen::Reg, rs1: gen::Reg, imm: i32 },
166
167
    // Store instructions.
168
    Sb { rs2: gen::Reg, rs1: gen::Reg, imm: i32 },
169
    Sh { rs2: gen::Reg, rs1: gen::Reg, imm: i32 },
170
    Sw { rs2: gen::Reg, rs1: gen::Reg, imm: i32 },
171
    Sd { rs2: gen::Reg, rs1: gen::Reg, imm: i32 },
172
173
    // Branch instructions.
174
    Beq  { rs1: gen::Reg, rs2: gen::Reg, imm: i32 },
175
    Bne  { rs1: gen::Reg, rs2: gen::Reg, imm: i32 },
176
    Blt  { rs1: gen::Reg, rs2: gen::Reg, imm: i32 },
177
    Bge  { rs1: gen::Reg, rs2: gen::Reg, imm: i32 },
178
    Bltu { rs1: gen::Reg, rs2: gen::Reg, imm: i32 },
179
    Bgeu { rs1: gen::Reg, rs2: gen::Reg, imm: i32 },
180
181
    // Jump instructions.
182
    Jal  { rd: gen::Reg, imm: i32 },
183
    Jalr { rd: gen::Reg, rs1: gen::Reg, imm: i32 },
184
185
    // Upper immediate.
186
    Lui   { rd: gen::Reg, imm: i32 },
187
    Auipc { rd: gen::Reg, imm: i32 },
188
189
    // System.
190
    Ecall,
191
    Ebreak,
192
193
    // Unknown/invalid instruction.
194
    Unknown { bits: u32 },
195
}
196
197
/// Decode a 32-bit instruction word into an [`Instr`].
198
pub fn decode(instr: u32) -> Instr {
199
    let op = opcode(instr);
200
    let f3 = funct3(instr);
201
    let f7 = funct7(instr);
202
    let rd = super::reg(rd(instr));
203
    let rs1 = super::reg(rs1(instr));
204
    let rs2 = super::reg(rs2(instr));
205
206
    match op {
207
        case encode::OP_LUI => {
208
            return Instr::Lui { rd, imm: immU(instr) };
209
        },
210
        case encode::OP_AUIPC => {
211
            return Instr::Auipc { rd, imm: immU(instr) };
212
        },
213
        case encode::OP_JAL => {
214
            return Instr::Jal { rd, imm: immJ(instr) };
215
        },
216
        case encode::OP_JALR => {
217
            return Instr::Jalr { rd, rs1, imm: immI(instr) };
218
        },
219
        case encode::OP_BRANCH => {
220
            let imm = immB(instr);
221
            match f3 {
222
                case encode::F3_BEQ  => return Instr::Beq { rs1, rs2, imm },
223
                case encode::F3_BNE  => return Instr::Bne { rs1, rs2, imm },
224
                case encode::F3_BLT  => return Instr::Blt { rs1, rs2, imm },
225
                case encode::F3_BGE  => return Instr::Bge { rs1, rs2, imm },
226
                case encode::F3_BLTU => return Instr::Bltu { rs1, rs2, imm },
227
                case encode::F3_BGEU => return Instr::Bgeu { rs1, rs2, imm },
228
                else                 => return Instr::Unknown { bits: instr },
229
            }
230
        },
231
        case encode::OP_LOAD => {
232
            let imm = immI(instr);
233
            match f3 {
234
                case encode::F3_BYTE   => return Instr::Lb { rd, rs1, imm },
235
                case encode::F3_HALF   => return Instr::Lh { rd, rs1, imm },
236
                case encode::F3_WORD   => return Instr::Lw { rd, rs1, imm },
237
                case encode::F3_DWORD  => return Instr::Ld { rd, rs1, imm },
238
                case encode::F3_BYTE_U => return Instr::Lbu { rd, rs1, imm },
239
                case encode::F3_HALF_U => return Instr::Lhu { rd, rs1, imm },
240
                case encode::F3_WORD_U => return Instr::Lwu { rd, rs1, imm },
241
                else                   => return Instr::Unknown { bits: instr },
242
            }
243
        },
244
        case encode::OP_STORE => {
245
            let imm = immS(instr);
246
            match f3 {
247
                case encode::F3_BYTE  => return Instr::Sb { rs2, rs1, imm },
248
                case encode::F3_HALF  => return Instr::Sh { rs2, rs1, imm },
249
                case encode::F3_WORD  => return Instr::Sw { rs2, rs1, imm },
250
                case encode::F3_DWORD => return Instr::Sd { rs2, rs1, imm },
251
                else                  => return Instr::Unknown { bits: instr },
252
            }
253
        },
254
        case encode::OP_IMM => {
255
            let imm = immI(instr);
256
            match f3 {
257
                case encode::F3_ADD  => return Instr::Addi { rd, rs1, imm },
258
                case encode::F3_SLT  => return Instr::Slti { rd, rs1, imm },
259
                case encode::F3_SLTU => return Instr::Sltiu { rd, rs1, imm },
260
                case encode::F3_XOR  => return Instr::Xori { rd, rs1, imm },
261
                case encode::F3_OR   => return Instr::Ori { rd, rs1, imm },
262
                case encode::F3_AND  => return Instr::Andi { rd, rs1, imm },
263
                case encode::F3_SLL  => return Instr::Slli { rd, rs1, shamt: imm & 0x3F },
264
                case encode::F3_SRL  => {
265
                    let shamt = imm & 0x3F;
266
                    if (imm & 0x400) != 0 {
267
                        return Instr::Srai { rd, rs1, shamt };
268
                    } else {
269
                        return Instr::Srli { rd, rs1, shamt };
270
                    }
271
                },
272
                else => return Instr::Unknown { bits: instr },
273
            }
274
        },
275
        case encode::OP_OP => {
276
            if f7 == encode::F7_MUL {
277
                match f3 {
278
                    case encode::F3_ADD  => return Instr::Mul { rd, rs1, rs2 },
279
                    case encode::F3_SLL  => return Instr::Mulh { rd, rs1, rs2 },
280
                    case encode::F3_SLT  => return Instr::Mulhsu { rd, rs1, rs2 },
281
                    case encode::F3_SLTU => return Instr::Mulhu { rd, rs1, rs2 },
282
                    case encode::F3_XOR  => return Instr::Div { rd, rs1, rs2 },
283
                    case encode::F3_SRL  => return Instr::Divu { rd, rs1, rs2 },
284
                    case encode::F3_OR   => return Instr::Rem { rd, rs1, rs2 },
285
                    case encode::F3_AND  => return Instr::Remu { rd, rs1, rs2 },
286
                    else                 => return Instr::Unknown { bits: instr },
287
                }
288
            } else {
289
                match f3 {
290
                    case encode::F3_ADD => {
291
                        if f7 == encode::F7_SUB {
292
                            return Instr::Sub { rd, rs1, rs2 };
293
                        } else {
294
                            return Instr::Add { rd, rs1, rs2 };
295
                        }
296
                    },
297
                    case encode::F3_SLL  => return Instr::Sll { rd, rs1, rs2 },
298
                    case encode::F3_SLT  => return Instr::Slt { rd, rs1, rs2 },
299
                    case encode::F3_SLTU => return Instr::Sltu { rd, rs1, rs2 },
300
                    case encode::F3_XOR  => return Instr::Xor { rd, rs1, rs2 },
301
                    case encode::F3_SRL  => {
302
                        if f7 == encode::F7_SRA {
303
                            return Instr::Sra { rd, rs1, rs2 };
304
                        } else {
305
                            return Instr::Srl { rd, rs1, rs2 };
306
                        }
307
                    },
308
                    case encode::F3_OR  => return Instr::Or { rd, rs1, rs2 },
309
                    case encode::F3_AND => return Instr::And { rd, rs1, rs2 },
310
                    else                => return Instr::Unknown { bits: instr },
311
                }
312
            }
313
        },
314
        case encode::OP_IMM32 => {
315
            let imm = immI(instr);
316
            match f3 {
317
                case encode::F3_ADD => return Instr::Addiw { rd, rs1, imm },
318
                case encode::F3_SLL => return Instr::Slliw { rd, rs1, shamt: imm & 0x1F },
319
                case encode::F3_SRL => {
320
                    let shamt = imm & 0x1F;
321
                    if (imm & 0x400) != 0 {
322
                        return Instr::Sraiw { rd, rs1, shamt };
323
                    } else {
324
                        return Instr::Srliw { rd, rs1, shamt };
325
                    }
326
                },
327
                else => return Instr::Unknown { bits: instr },
328
            }
329
        },
330
        case encode::OP_OP32 => {
331
            if f7 == encode::F7_MUL {
332
                match f3 {
333
                    case encode::F3_ADD => return Instr::Mulw { rd, rs1, rs2 },
334
                    case encode::F3_XOR => return Instr::Divw { rd, rs1, rs2 },
335
                    case encode::F3_SRL => return Instr::Divuw { rd, rs1, rs2 },
336
                    case encode::F3_OR  => return Instr::Remw { rd, rs1, rs2 },
337
                    case encode::F3_AND => return Instr::Remuw { rd, rs1, rs2 },
338
                    else                => return Instr::Unknown { bits: instr },
339
                }
340
            } else {
341
                match f3 {
342
                    case encode::F3_ADD => {
343
                        if f7 == encode::F7_SUB {
344
                            return Instr::Subw { rd, rs1, rs2 };
345
                        } else {
346
                            return Instr::Addw { rd, rs1, rs2 };
347
                        }
348
                    },
349
                    case encode::F3_SLL => return Instr::Sllw { rd, rs1, rs2 },
350
                    case encode::F3_SRL => {
351
                        if f7 == encode::F7_SRA {
352
                            return Instr::Sraw { rd, rs1, rs2 };
353
                        } else {
354
                            return Instr::Srlw { rd, rs1, rs2 };
355
                        }
356
                    },
357
                    else => return Instr::Unknown { bits: instr },
358
                }
359
            }
360
        },
361
        case encode::OP_SYSTEM => {
362
            let imm = immI(instr);
363
            if imm == 0 {
364
                return Instr::Ecall;
365
            } else if imm == 1 {
366
                return Instr::Ebreak;
367
            } else {
368
                return Instr::Unknown { bits: instr };
369
            }
370
        },
371
        else => {
372
            return Instr::Unknown { bits: instr };
373
        }
374
    }
375
}