jit_assembler/riscv64/
instruction.rs

1/// RISC-V instruction formats and encoding
2use core::fmt;
3use crate::common::{
4    Instruction as InstructionTrait,
5    Register as RegisterTrait,
6};
7
8#[cfg(feature = "std")]
9use std::vec::Vec;
10#[cfg(not(feature = "std"))]
11use alloc::vec::Vec;
12
13/// RISC-V register representation
14#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
15pub struct Register(pub u8);
16
17impl Register {
18    pub const fn new(reg: u8) -> Self {
19        Self(reg)
20    }
21
22    pub fn value(self) -> u8 {
23        self.0
24    }
25}
26
27impl RegisterTrait for Register {
28    fn id(&self) -> u32 {
29        self.0 as u32
30    }
31    
32    fn abi_class(&self) -> crate::common::AbiClass {
33        use crate::common::AbiClass;
34        
35        match self.0 {
36            // Caller-saved registers (do not need to be preserved across calls)
37            1 => AbiClass::CallerSaved,         // RA (return address) - caller-saved
38            5..=7 | 28..=31 => AbiClass::CallerSaved,  // T0-T2, T3-T6 (temporaries)
39            10..=17 => AbiClass::CallerSaved,   // A0-A7 (arguments/return values)
40            
41            // Callee-saved registers (must be preserved across calls)
42            2 => AbiClass::CalleeSaved,         // SP (stack pointer) - callee-saved
43            8..=9 | 18..=27 => AbiClass::CalleeSaved,  // S0-S1, S2-S11 (saved registers)
44            
45            // Special-purpose registers
46            0 => AbiClass::Special,  // X0 (zero register) - hardwired to zero
47            3 => AbiClass::Special,  // GP (global pointer) - special purpose
48            4 => AbiClass::Special,  // TP (thread pointer) - special purpose
49
50            // Default to Special for any unhandled registers
51            _ => AbiClass::Special,
52        }
53    }
54}
55
56/// RISC-V CSR representation
57#[derive(Debug, Clone, Copy, PartialEq, Eq)]
58pub struct Csr(pub u16);
59
60impl Csr {
61    pub const fn new(csr: u16) -> Self {
62        Self(csr)
63    }
64
65    pub fn value(self) -> u16 {
66        self.0
67    }
68}
69
70/// RISC-V instruction representation (supports both 32-bit and 16-bit compressed instructions)
71#[derive(Debug, Clone, Copy, PartialEq, Eq)]
72pub enum Instruction {
73    /// 32-bit standard instruction
74    Standard(u32),
75    /// 16-bit compressed instruction (C extension)
76    Compressed(u16),
77}
78
79impl Instruction {
80    /// Create a new 32-bit instruction
81    pub fn new(value: u32) -> Self {
82        Self::Standard(value)
83    }
84    
85    /// Create a new 16-bit compressed instruction
86    pub fn new_compressed(value: u16) -> Self {
87        Self::Compressed(value)
88    }
89
90    /// Get the instruction value as u64 (for compatibility)
91    pub fn value(self) -> u32 {
92        match self {
93            Self::Standard(val) => val,
94            Self::Compressed(val) => val as u32,
95        }
96    }
97
98    /// Get the instruction as bytes with proper length
99    pub fn bytes(self) -> Vec<u8> {
100        match self {
101            Self::Standard(val) => val.to_le_bytes().to_vec(),
102            Self::Compressed(val) => val.to_le_bytes().to_vec(),
103        }
104    }
105    
106    /// Get the size of this instruction in bytes
107    pub fn size(&self) -> usize {
108        match self {
109            Self::Standard(_) => 4,
110            Self::Compressed(_) => 2,
111        }
112    }
113
114    /// Check if this is a compressed instruction
115    pub fn is_compressed(&self) -> bool {
116        matches!(self, Self::Compressed(_))
117    }
118}
119
120impl InstructionTrait for Instruction {
121    fn value(&self) -> u64 {
122        match self {
123            Self::Standard(val) => *val as u64,
124            Self::Compressed(val) => *val as u64,
125        }
126    }
127
128    fn bytes(&self) -> Vec<u8> {
129        match self {
130            Self::Standard(val) => val.to_le_bytes().to_vec(),
131            Self::Compressed(val) => val.to_le_bytes().to_vec(),
132        }
133    }
134
135    fn size(&self) -> usize {
136        match self {
137            Self::Standard(_) => 4,
138            Self::Compressed(_) => 2,
139        }
140    }
141}
142
143impl fmt::Display for Instruction {
144    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
145        match self {
146            Self::Standard(val) => write!(f, "0x{:08x}", val),
147            Self::Compressed(val) => write!(f, "0x{:04x}c", val),
148        }
149    }
150}
151
152/// I-type instruction encoding
153pub fn encode_i_type(opcode: u8, rd: Register, funct3: u8, rs1: Register, imm: i16) -> Instruction {
154    let imm = imm as u32 & 0xfff;
155    let instr = (imm << 20) | ((rs1.value() as u32) << 15) | ((funct3 as u32) << 12) | ((rd.value() as u32) << 7) | (opcode as u32);
156    Instruction::Standard(instr)
157}
158
159/// CSR instruction encoding (I-type variant)
160pub fn encode_csr_type(opcode: u8, rd: Register, funct3: u8, rs1: Register, csr: Csr) -> Instruction {
161    let csr_val = csr.value() as u32;
162    let instr = (csr_val << 20) | ((rs1.value() as u32) << 15) | ((funct3 as u32) << 12) | ((rd.value() as u32) << 7) | (opcode as u32);
163    Instruction::Standard(instr)
164}
165
166/// CSR immediate instruction encoding
167pub fn encode_csr_imm_type(opcode: u8, rd: Register, funct3: u8, uimm: u8, csr: Csr) -> Instruction {
168    let csr_val = csr.value() as u32;
169    let instr = (csr_val << 20) | ((uimm as u32) << 15) | ((funct3 as u32) << 12) | ((rd.value() as u32) << 7) | (opcode as u32);
170    Instruction::Standard(instr)
171}
172
173/// Privileged instruction encoding (special SYSTEM instructions)
174pub fn encode_privileged_type(opcode: u8, funct12: u16) -> Instruction {
175    let instr = ((funct12 as u32) << 20) | (opcode as u32);
176    Instruction::Standard(instr)
177}
178
179/// R-type instruction encoding
180pub fn encode_r_type(opcode: u8, rd: Register, funct3: u8, rs1: Register, rs2: Register, funct7: u8) -> Instruction {
181    let instr = ((funct7 as u32) << 25) | ((rs2.value() as u32) << 20) | ((rs1.value() as u32) << 15) | ((funct3 as u32) << 12) | ((rd.value() as u32) << 7) | (opcode as u32);
182    Instruction::Standard(instr)
183}
184
185/// S-type instruction encoding (Store)
186pub fn encode_s_type(opcode: u8, funct3: u8, rs1: Register, rs2: Register, imm: i16) -> Instruction {
187    let imm = imm as u32 & 0xfff;
188    let imm_11_5 = (imm >> 5) & 0x7f;
189    let imm_4_0 = imm & 0x1f;
190    let instr = (imm_11_5 << 25) | ((rs2.value() as u32) << 20) | ((rs1.value() as u32) << 15) | ((funct3 as u32) << 12) | (imm_4_0 << 7) | (opcode as u32);
191    Instruction::Standard(instr)
192}
193
194/// B-type instruction encoding (Branch)
195pub fn encode_b_type(opcode: u8, funct3: u8, rs1: Register, rs2: Register, imm: i16) -> Instruction {
196    let imm = (imm as u32) & 0x1ffe; // 13-bit signed immediate
197    let imm_12 = (imm >> 12) & 0x1;
198    let imm_10_5 = (imm >> 5) & 0x3f;
199    let imm_4_1 = (imm >> 1) & 0xf;
200    let imm_11 = (imm >> 11) & 0x1;
201    let instr = (imm_12 << 31) | (imm_10_5 << 25) | ((rs2.value() as u32) << 20) | ((rs1.value() as u32) << 15) | ((funct3 as u32) << 12) | (imm_4_1 << 8) | (imm_11 << 7) | (opcode as u32);
202    Instruction::Standard(instr)
203}
204
205/// U-type instruction encoding (Upper immediate)
206pub fn encode_u_type(opcode: u8, rd: Register, imm: u32) -> Instruction {
207    let imm = (imm & 0xfffff) << 12; // 20-bit immediate shifted to upper bits
208    let instr = imm | ((rd.value() as u32) << 7) | (opcode as u32);
209    Instruction::Standard(instr)
210}
211
212/// J-type instruction encoding (Jump)
213pub fn encode_j_type(opcode: u8, rd: Register, imm: i32) -> Instruction {
214    let imm = (imm as u32) & 0x1fffff; // 21-bit signed immediate
215    let imm_20 = (imm >> 20) & 0x1;
216    let imm_10_1 = (imm >> 1) & 0x3ff;
217    let imm_11 = (imm >> 11) & 0x1;
218    let imm_19_12 = (imm >> 12) & 0xff;
219    let instr = (imm_20 << 31) | (imm_10_1 << 21) | (imm_11 << 20) | (imm_19_12 << 12) | ((rd.value() as u32) << 7) | (opcode as u32);
220    Instruction::Standard(instr)
221}
222
223/// Common RISC-V opcodes
224pub mod opcodes {
225    pub const SYSTEM: u8 = 0x73;
226    pub const OP_IMM: u8 = 0x13;
227    pub const OP: u8 = 0x33;
228    pub const LOAD: u8 = 0x03;
229    pub const STORE: u8 = 0x23;
230    pub const BRANCH: u8 = 0x63;
231    pub const JAL: u8 = 0x6f;
232    pub const JALR: u8 = 0x67;
233    pub const LUI: u8 = 0x37;
234    pub const AUIPC: u8 = 0x17;
235    pub const OP_IMM_32: u8 = 0x1b;
236    pub const OP_32: u8 = 0x3b;
237}
238
239/// SYSTEM instruction function codes
240pub mod system_funct3 {
241    pub const CSRRW: u8 = 0x1;
242    pub const CSRRS: u8 = 0x2;
243    pub const CSRRC: u8 = 0x3;
244    pub const CSRRWI: u8 = 0x5;
245    pub const CSRRSI: u8 = 0x6;
246    pub const CSRRCI: u8 = 0x7;
247}
248
249/// Privileged instruction function codes (funct12 field)
250pub mod privileged_funct12 {
251    pub const ECALL: u16 = 0x000;  // Environment call
252    pub const EBREAK: u16 = 0x001; // Environment break
253    pub const SRET: u16 = 0x102;   // Supervisor return
254    pub const MRET: u16 = 0x302;   // Machine return
255    pub const WFI: u16 = 0x105;    // Wait for interrupt
256}
257
258/// Branch instruction function codes
259pub mod branch_funct3 {
260    pub const BEQ: u8 = 0x0;
261    pub const BNE: u8 = 0x1;
262    pub const BLT: u8 = 0x4;
263    pub const BGE: u8 = 0x5;
264    pub const BLTU: u8 = 0x6;
265    pub const BGEU: u8 = 0x7;
266}
267
268/// Load instruction function codes
269pub mod load_funct3 {
270    pub const LB: u8 = 0x0;
271    pub const LH: u8 = 0x1;
272    pub const LW: u8 = 0x2;
273    pub const LD: u8 = 0x3;
274    pub const LBU: u8 = 0x4;
275    pub const LHU: u8 = 0x5;
276    pub const LWU: u8 = 0x6;
277}
278
279/// Store instruction function codes
280pub mod store_funct3 {
281    pub const SB: u8 = 0x0;
282    pub const SH: u8 = 0x1;
283    pub const SW: u8 = 0x2;
284    pub const SD: u8 = 0x3;
285}
286
287/// Arithmetic/Logic instruction function codes
288pub mod alu_funct3 {
289    pub const ADD_SUB: u8 = 0x0;
290    pub const SLL: u8 = 0x1;
291    pub const SLT: u8 = 0x2;
292    pub const SLTU: u8 = 0x3;
293    pub const XOR: u8 = 0x4;
294    pub const SRL_SRA: u8 = 0x5;
295    pub const OR: u8 = 0x6;
296    pub const AND: u8 = 0x7;
297}
298
299/// M Extension (Multiply/Divide) instruction function codes
300/// All M-extension instructions use funct7 = 0x01 and opcode = OP (0x33)
301pub mod m_funct3 {
302    pub const MUL: u8 = 0x0;      // Multiply (low 64 bits)
303    pub const MULH: u8 = 0x1;     // Multiply high (signed × signed)
304    pub const MULHSU: u8 = 0x2;   // Multiply high (signed × unsigned)
305    pub const MULHU: u8 = 0x3;    // Multiply high (unsigned × unsigned)
306    pub const DIV: u8 = 0x4;      // Divide (signed)
307    pub const DIVU: u8 = 0x5;     // Divide (unsigned)
308    pub const REM: u8 = 0x6;      // Remainder (signed)
309    pub const REMU: u8 = 0x7;     // Remainder (unsigned)
310}
311
312/// M Extension funct7 code
313pub mod m_funct7 {
314    pub const M_EXT: u8 = 0x01;
315}
316
317/// Common CSR addresses
318pub mod csr {
319    use super::Csr;
320    
321    // Machine Information Registers
322    pub const MVENDORID: Csr = Csr::new(0xf11);
323    pub const MARCHID: Csr = Csr::new(0xf12);
324    pub const MIMPID: Csr = Csr::new(0xf13);
325    pub const MHARTID: Csr = Csr::new(0xf14);
326    pub const MCONFIGPTR: Csr = Csr::new(0xf15);
327    
328    // Machine Trap Setup
329    pub const MSTATUS: Csr = Csr::new(0x300);
330    pub const MISA: Csr = Csr::new(0x301);
331    pub const MEDELEG: Csr = Csr::new(0x302);
332    pub const MIDELEG: Csr = Csr::new(0x303);
333    pub const MIE: Csr = Csr::new(0x304);
334    pub const MTVEC: Csr = Csr::new(0x305);
335    pub const MCOUNTEREN: Csr = Csr::new(0x306);
336    pub const MSTATUSH: Csr = Csr::new(0x310);
337    
338    // Machine Trap Handling
339    pub const MSCRATCH: Csr = Csr::new(0x340);
340    pub const MEPC: Csr = Csr::new(0x341);
341    pub const MCAUSE: Csr = Csr::new(0x342);
342    pub const MTVAL: Csr = Csr::new(0x343);
343    pub const MIP: Csr = Csr::new(0x344);
344    pub const MTINST: Csr = Csr::new(0x34a);
345    pub const MTVAL2: Csr = Csr::new(0x34b);
346    
347    // Machine Configuration
348    pub const MENVCFG: Csr = Csr::new(0x30a);
349    pub const MENVCFGH: Csr = Csr::new(0x31a);
350    pub const MSECCFG: Csr = Csr::new(0x747);
351    pub const MSECCFGH: Csr = Csr::new(0x757);
352    
353    // Machine Memory Protection - Configuration
354    pub const PMPCFG0: Csr = Csr::new(0x3a0);
355    pub const PMPCFG1: Csr = Csr::new(0x3a1);
356    pub const PMPCFG2: Csr = Csr::new(0x3a2);
357    pub const PMPCFG3: Csr = Csr::new(0x3a3);
358    pub const PMPCFG4: Csr = Csr::new(0x3a4);
359    pub const PMPCFG5: Csr = Csr::new(0x3a5);
360    pub const PMPCFG6: Csr = Csr::new(0x3a6);
361    pub const PMPCFG7: Csr = Csr::new(0x3a7);
362    pub const PMPCFG8: Csr = Csr::new(0x3a8);
363    pub const PMPCFG9: Csr = Csr::new(0x3a9);
364    pub const PMPCFG10: Csr = Csr::new(0x3aa);
365    pub const PMPCFG11: Csr = Csr::new(0x3ab);
366    pub const PMPCFG12: Csr = Csr::new(0x3ac);
367    pub const PMPCFG13: Csr = Csr::new(0x3ad);
368    pub const PMPCFG14: Csr = Csr::new(0x3ae);
369    pub const PMPCFG15: Csr = Csr::new(0x3af);
370    
371    // Machine Memory Protection - Address
372    pub const PMPADDR0: Csr = Csr::new(0x3b0);
373    pub const PMPADDR1: Csr = Csr::new(0x3b1);
374    pub const PMPADDR2: Csr = Csr::new(0x3b2);
375    pub const PMPADDR3: Csr = Csr::new(0x3b3);
376    pub const PMPADDR4: Csr = Csr::new(0x3b4);
377    pub const PMPADDR5: Csr = Csr::new(0x3b5);
378    pub const PMPADDR6: Csr = Csr::new(0x3b6);
379    pub const PMPADDR7: Csr = Csr::new(0x3b7);
380    pub const PMPADDR8: Csr = Csr::new(0x3b8);
381    pub const PMPADDR9: Csr = Csr::new(0x3b9);
382    pub const PMPADDR10: Csr = Csr::new(0x3ba);
383    pub const PMPADDR11: Csr = Csr::new(0x3bb);
384    pub const PMPADDR12: Csr = Csr::new(0x3bc);
385    pub const PMPADDR13: Csr = Csr::new(0x3bd);
386    pub const PMPADDR14: Csr = Csr::new(0x3be);
387    pub const PMPADDR15: Csr = Csr::new(0x3bf);
388    pub const PMPADDR16: Csr = Csr::new(0x3c0);
389    pub const PMPADDR17: Csr = Csr::new(0x3c1);
390    pub const PMPADDR18: Csr = Csr::new(0x3c2);
391    pub const PMPADDR19: Csr = Csr::new(0x3c3);
392    pub const PMPADDR20: Csr = Csr::new(0x3c4);
393    pub const PMPADDR21: Csr = Csr::new(0x3c5);
394    pub const PMPADDR22: Csr = Csr::new(0x3c6);
395    pub const PMPADDR23: Csr = Csr::new(0x3c7);
396    pub const PMPADDR24: Csr = Csr::new(0x3c8);
397    pub const PMPADDR25: Csr = Csr::new(0x3c9);
398    pub const PMPADDR26: Csr = Csr::new(0x3ca);
399    pub const PMPADDR27: Csr = Csr::new(0x3cb);
400    pub const PMPADDR28: Csr = Csr::new(0x3cc);
401    pub const PMPADDR29: Csr = Csr::new(0x3cd);
402    pub const PMPADDR30: Csr = Csr::new(0x3ce);
403    pub const PMPADDR31: Csr = Csr::new(0x3cf);
404    pub const PMPADDR32: Csr = Csr::new(0x3d0);
405    pub const PMPADDR33: Csr = Csr::new(0x3d1);
406    pub const PMPADDR34: Csr = Csr::new(0x3d2);
407    pub const PMPADDR35: Csr = Csr::new(0x3d3);
408    pub const PMPADDR36: Csr = Csr::new(0x3d4);
409    pub const PMPADDR37: Csr = Csr::new(0x3d5);
410    pub const PMPADDR38: Csr = Csr::new(0x3d6);
411    pub const PMPADDR39: Csr = Csr::new(0x3d7);
412    pub const PMPADDR40: Csr = Csr::new(0x3d8);
413    pub const PMPADDR41: Csr = Csr::new(0x3d9);
414    pub const PMPADDR42: Csr = Csr::new(0x3da);
415    pub const PMPADDR43: Csr = Csr::new(0x3db);
416    pub const PMPADDR44: Csr = Csr::new(0x3dc);
417    pub const PMPADDR45: Csr = Csr::new(0x3dd);
418    pub const PMPADDR46: Csr = Csr::new(0x3de);
419    pub const PMPADDR47: Csr = Csr::new(0x3df);
420    pub const PMPADDR48: Csr = Csr::new(0x3e0);
421    pub const PMPADDR49: Csr = Csr::new(0x3e1);
422    pub const PMPADDR50: Csr = Csr::new(0x3e2);
423    pub const PMPADDR51: Csr = Csr::new(0x3e3);
424    pub const PMPADDR52: Csr = Csr::new(0x3e4);
425    pub const PMPADDR53: Csr = Csr::new(0x3e5);
426    pub const PMPADDR54: Csr = Csr::new(0x3e6);
427    pub const PMPADDR55: Csr = Csr::new(0x3e7);
428    pub const PMPADDR56: Csr = Csr::new(0x3e8);
429    pub const PMPADDR57: Csr = Csr::new(0x3e9);
430    pub const PMPADDR58: Csr = Csr::new(0x3ea);
431    pub const PMPADDR59: Csr = Csr::new(0x3eb);
432    pub const PMPADDR60: Csr = Csr::new(0x3ec);
433    pub const PMPADDR61: Csr = Csr::new(0x3ed);
434    pub const PMPADDR62: Csr = Csr::new(0x3ee);
435    pub const PMPADDR63: Csr = Csr::new(0x3ef);
436    
437    // Machine Counter/Timers
438    pub const MCYCLE: Csr = Csr::new(0xb00);
439    pub const MINSTRET: Csr = Csr::new(0xb02);
440    pub const MHPMCOUNTER3: Csr = Csr::new(0xb03);
441    pub const MHPMCOUNTER4: Csr = Csr::new(0xb04);
442    pub const MHPMCOUNTER5: Csr = Csr::new(0xb05);
443    pub const MHPMCOUNTER6: Csr = Csr::new(0xb06);
444    pub const MHPMCOUNTER7: Csr = Csr::new(0xb07);
445    pub const MHPMCOUNTER8: Csr = Csr::new(0xb08);
446    pub const MHPMCOUNTER9: Csr = Csr::new(0xb09);
447    pub const MHPMCOUNTER10: Csr = Csr::new(0xb0a);
448    pub const MHPMCOUNTER11: Csr = Csr::new(0xb0b);
449    pub const MHPMCOUNTER12: Csr = Csr::new(0xb0c);
450    pub const MHPMCOUNTER13: Csr = Csr::new(0xb0d);
451    pub const MHPMCOUNTER14: Csr = Csr::new(0xb0e);
452    pub const MHPMCOUNTER15: Csr = Csr::new(0xb0f);
453    pub const MHPMCOUNTER16: Csr = Csr::new(0xb10);
454    pub const MHPMCOUNTER17: Csr = Csr::new(0xb11);
455    pub const MHPMCOUNTER18: Csr = Csr::new(0xb12);
456    pub const MHPMCOUNTER19: Csr = Csr::new(0xb13);
457    pub const MHPMCOUNTER20: Csr = Csr::new(0xb14);
458    pub const MHPMCOUNTER21: Csr = Csr::new(0xb15);
459    pub const MHPMCOUNTER22: Csr = Csr::new(0xb16);
460    pub const MHPMCOUNTER23: Csr = Csr::new(0xb17);
461    pub const MHPMCOUNTER24: Csr = Csr::new(0xb18);
462    pub const MHPMCOUNTER25: Csr = Csr::new(0xb19);
463    pub const MHPMCOUNTER26: Csr = Csr::new(0xb1a);
464    pub const MHPMCOUNTER27: Csr = Csr::new(0xb1b);
465    pub const MHPMCOUNTER28: Csr = Csr::new(0xb1c);
466    pub const MHPMCOUNTER29: Csr = Csr::new(0xb1d);
467    pub const MHPMCOUNTER30: Csr = Csr::new(0xb1e);
468    pub const MHPMCOUNTER31: Csr = Csr::new(0xb1f);
469    
470    // Machine Counter/Timers - High (for RV32)
471    pub const MCYCLEH: Csr = Csr::new(0xb80);
472    pub const MINSTRETH: Csr = Csr::new(0xb82);
473    pub const MHPMCOUNTER3H: Csr = Csr::new(0xb83);
474    pub const MHPMCOUNTER4H: Csr = Csr::new(0xb84);
475    pub const MHPMCOUNTER5H: Csr = Csr::new(0xb85);
476    pub const MHPMCOUNTER6H: Csr = Csr::new(0xb86);
477    pub const MHPMCOUNTER7H: Csr = Csr::new(0xb87);
478    pub const MHPMCOUNTER8H: Csr = Csr::new(0xb88);
479    pub const MHPMCOUNTER9H: Csr = Csr::new(0xb89);
480    pub const MHPMCOUNTER10H: Csr = Csr::new(0xb8a);
481    pub const MHPMCOUNTER11H: Csr = Csr::new(0xb8b);
482    pub const MHPMCOUNTER12H: Csr = Csr::new(0xb8c);
483    pub const MHPMCOUNTER13H: Csr = Csr::new(0xb8d);
484    pub const MHPMCOUNTER14H: Csr = Csr::new(0xb8e);
485    pub const MHPMCOUNTER15H: Csr = Csr::new(0xb8f);
486    pub const MHPMCOUNTER16H: Csr = Csr::new(0xb90);
487    pub const MHPMCOUNTER17H: Csr = Csr::new(0xb91);
488    pub const MHPMCOUNTER18H: Csr = Csr::new(0xb92);
489    pub const MHPMCOUNTER19H: Csr = Csr::new(0xb93);
490    pub const MHPMCOUNTER20H: Csr = Csr::new(0xb94);
491    pub const MHPMCOUNTER21H: Csr = Csr::new(0xb95);
492    pub const MHPMCOUNTER22H: Csr = Csr::new(0xb96);
493    pub const MHPMCOUNTER23H: Csr = Csr::new(0xb97);
494    pub const MHPMCOUNTER24H: Csr = Csr::new(0xb98);
495    pub const MHPMCOUNTER25H: Csr = Csr::new(0xb99);
496    pub const MHPMCOUNTER26H: Csr = Csr::new(0xb9a);
497    pub const MHPMCOUNTER27H: Csr = Csr::new(0xb9b);
498    pub const MHPMCOUNTER28H: Csr = Csr::new(0xb9c);
499    pub const MHPMCOUNTER29H: Csr = Csr::new(0xb9d);
500    pub const MHPMCOUNTER30H: Csr = Csr::new(0xb9e);
501    pub const MHPMCOUNTER31H: Csr = Csr::new(0xb9f);
502    
503    // Machine Counter Setup
504    pub const MCOUNTINHIBIT: Csr = Csr::new(0x320);
505    pub const MHPMEVENT3: Csr = Csr::new(0x323);
506    pub const MHPMEVENT4: Csr = Csr::new(0x324);
507    pub const MHPMEVENT5: Csr = Csr::new(0x325);
508    pub const MHPMEVENT6: Csr = Csr::new(0x326);
509    pub const MHPMEVENT7: Csr = Csr::new(0x327);
510    pub const MHPMEVENT8: Csr = Csr::new(0x328);
511    pub const MHPMEVENT9: Csr = Csr::new(0x329);
512    pub const MHPMEVENT10: Csr = Csr::new(0x32a);
513    pub const MHPMEVENT11: Csr = Csr::new(0x32b);
514    pub const MHPMEVENT12: Csr = Csr::new(0x32c);
515    pub const MHPMEVENT13: Csr = Csr::new(0x32d);
516    pub const MHPMEVENT14: Csr = Csr::new(0x32e);
517    pub const MHPMEVENT15: Csr = Csr::new(0x32f);
518    pub const MHPMEVENT16: Csr = Csr::new(0x330);
519    pub const MHPMEVENT17: Csr = Csr::new(0x331);
520    pub const MHPMEVENT18: Csr = Csr::new(0x332);
521    pub const MHPMEVENT19: Csr = Csr::new(0x333);
522    pub const MHPMEVENT20: Csr = Csr::new(0x334);
523    pub const MHPMEVENT21: Csr = Csr::new(0x335);
524    pub const MHPMEVENT22: Csr = Csr::new(0x336);
525    pub const MHPMEVENT23: Csr = Csr::new(0x337);
526    pub const MHPMEVENT24: Csr = Csr::new(0x338);
527    pub const MHPMEVENT25: Csr = Csr::new(0x339);
528    pub const MHPMEVENT26: Csr = Csr::new(0x33a);
529    pub const MHPMEVENT27: Csr = Csr::new(0x33b);
530    pub const MHPMEVENT28: Csr = Csr::new(0x33c);
531    pub const MHPMEVENT29: Csr = Csr::new(0x33d);
532    pub const MHPMEVENT30: Csr = Csr::new(0x33e);
533    pub const MHPMEVENT31: Csr = Csr::new(0x33f);
534    
535    // Supervisor-mode CSRs
536    pub const SSTATUS: Csr = Csr::new(0x100);
537    pub const SIE: Csr = Csr::new(0x104);
538    pub const STVEC: Csr = Csr::new(0x105);
539    pub const SSCRATCH: Csr = Csr::new(0x140);
540    pub const SEPC: Csr = Csr::new(0x141);
541    pub const SCAUSE: Csr = Csr::new(0x142);
542    pub const STVAL: Csr = Csr::new(0x143);
543    pub const SIP: Csr = Csr::new(0x144);
544}
545
546/// Common registers
547pub mod reg {
548    use super::Register;
549    
550    // Standard register names (x0-x31)
551    pub const X0: Register = Register::new(0);
552    pub const X1: Register = Register::new(1);
553    pub const X2: Register = Register::new(2);
554    pub const X3: Register = Register::new(3);
555    pub const X4: Register = Register::new(4);
556    pub const X5: Register = Register::new(5);
557    pub const X6: Register = Register::new(6);
558    pub const X7: Register = Register::new(7);
559    pub const X8: Register = Register::new(8);
560    pub const X9: Register = Register::new(9);
561    pub const X10: Register = Register::new(10);
562    pub const X11: Register = Register::new(11);
563    pub const X12: Register = Register::new(12);
564    pub const X13: Register = Register::new(13);
565    pub const X14: Register = Register::new(14);
566    pub const X15: Register = Register::new(15);
567    pub const X16: Register = Register::new(16);
568    pub const X17: Register = Register::new(17);
569    pub const X18: Register = Register::new(18);
570    pub const X19: Register = Register::new(19);
571    pub const X20: Register = Register::new(20);
572    pub const X21: Register = Register::new(21);
573    pub const X22: Register = Register::new(22);
574    pub const X23: Register = Register::new(23);
575    pub const X24: Register = Register::new(24);
576    pub const X25: Register = Register::new(25);
577    pub const X26: Register = Register::new(26);
578    pub const X27: Register = Register::new(27);
579    pub const X28: Register = Register::new(28);
580    pub const X29: Register = Register::new(29);
581    pub const X30: Register = Register::new(30);
582    pub const X31: Register = Register::new(31);
583
584    // RISC-V ABI register aliases
585    pub const ZERO: Register = X0;  // Hard-wired zero
586    pub const RA: Register = X1;    // Return address
587    pub const SP: Register = X2;    // Stack pointer
588    pub const GP: Register = X3;    // Global pointer
589    pub const TP: Register = X4;    // Thread pointer
590    pub const T0: Register = X5;    // Temporary register 0
591    pub const T1: Register = X6;    // Temporary register 1
592    pub const T2: Register = X7;    // Temporary register 2
593    pub const S0: Register = X8;    // Saved register 0 / Frame pointer
594    pub const FP: Register = X8;    // Frame pointer (alias for s0)
595    pub const S1: Register = X9;    // Saved register 1
596    pub const A0: Register = X10;   // Function argument 0 / Return value 0
597    pub const A1: Register = X11;   // Function argument 1 / Return value 1
598    pub const A2: Register = X12;   // Function argument 2
599    pub const A3: Register = X13;   // Function argument 3
600    pub const A4: Register = X14;   // Function argument 4
601    pub const A5: Register = X15;   // Function argument 5
602    pub const A6: Register = X16;   // Function argument 6
603    pub const A7: Register = X17;   // Function argument 7
604    pub const S2: Register = X18;   // Saved register 2
605    pub const S3: Register = X19;   // Saved register 3
606    pub const S4: Register = X20;   // Saved register 4
607    pub const S5: Register = X21;   // Saved register 5
608    pub const S6: Register = X22;   // Saved register 6
609    pub const S7: Register = X23;   // Saved register 7
610    pub const S8: Register = X24;   // Saved register 8
611    pub const S9: Register = X25;   // Saved register 9
612    pub const S10: Register = X26;  // Saved register 10
613    pub const S11: Register = X27;  // Saved register 11
614    pub const T3: Register = X28;   // Temporary register 3
615    pub const T4: Register = X29;   // Temporary register 4
616    pub const T5: Register = X30;   // Temporary register 5
617    pub const T6: Register = X31;   // Temporary register 6
618}