jit_assembler/riscv64/
instruction.rs1use 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#[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 1 => AbiClass::CallerSaved, 5..=7 | 28..=31 => AbiClass::CallerSaved, 10..=17 => AbiClass::CallerSaved, 2 => AbiClass::CalleeSaved, 8..=9 | 18..=27 => AbiClass::CalleeSaved, 0 => AbiClass::Special, 3 => AbiClass::Special, 4 => AbiClass::Special, _ => AbiClass::Special,
52 }
53 }
54}
55
56#[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#[derive(Debug, Clone, Copy, PartialEq, Eq)]
72pub enum Instruction {
73 Standard(u32),
75 Compressed(u16),
77}
78
79impl Instruction {
80 pub fn new(value: u32) -> Self {
82 Self::Standard(value)
83 }
84
85 pub fn new_compressed(value: u16) -> Self {
87 Self::Compressed(value)
88 }
89
90 pub fn value(self) -> u32 {
92 match self {
93 Self::Standard(val) => val,
94 Self::Compressed(val) => val as u32,
95 }
96 }
97
98 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 pub fn size(&self) -> usize {
108 match self {
109 Self::Standard(_) => 4,
110 Self::Compressed(_) => 2,
111 }
112 }
113
114 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
152pub 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
159pub 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
166pub 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
173pub 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
179pub 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
185pub 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
194pub fn encode_b_type(opcode: u8, funct3: u8, rs1: Register, rs2: Register, imm: i16) -> Instruction {
196 let imm = (imm as u32) & 0x1ffe; 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
205pub fn encode_u_type(opcode: u8, rd: Register, imm: u32) -> Instruction {
207 let imm = (imm & 0xfffff) << 12; let instr = imm | ((rd.value() as u32) << 7) | (opcode as u32);
209 Instruction::Standard(instr)
210}
211
212pub fn encode_j_type(opcode: u8, rd: Register, imm: i32) -> Instruction {
214 let imm = (imm as u32) & 0x1fffff; 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
223pub 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
239pub 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
249pub mod privileged_funct12 {
251 pub const ECALL: u16 = 0x000; pub const EBREAK: u16 = 0x001; pub const SRET: u16 = 0x102; pub const MRET: u16 = 0x302; pub const WFI: u16 = 0x105; }
257
258pub 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
268pub 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
279pub 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
287pub 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
299pub mod m_funct3 {
302 pub const MUL: u8 = 0x0; pub const MULH: u8 = 0x1; pub const MULHSU: u8 = 0x2; pub const MULHU: u8 = 0x3; pub const DIV: u8 = 0x4; pub const DIVU: u8 = 0x5; pub const REM: u8 = 0x6; pub const REMU: u8 = 0x7; }
311
312pub mod m_funct7 {
314 pub const M_EXT: u8 = 0x01;
315}
316
317pub mod csr {
319 use super::Csr;
320
321 pub const MSTATUS: Csr = Csr::new(0x300);
323 pub const MISA: Csr = Csr::new(0x301);
324 pub const MEDELEG: Csr = Csr::new(0x302);
325 pub const MIDELEG: Csr = Csr::new(0x303);
326 pub const MIE: Csr = Csr::new(0x304);
327 pub const MTVEC: Csr = Csr::new(0x305);
328 pub const MSCRATCH: Csr = Csr::new(0x340);
329 pub const MEPC: Csr = Csr::new(0x341);
330 pub const MCAUSE: Csr = Csr::new(0x342);
331 pub const MTVAL: Csr = Csr::new(0x343);
332 pub const MIP: Csr = Csr::new(0x344);
333 pub const MHARTID: Csr = Csr::new(0xf14);
334
335 pub const SSTATUS: Csr = Csr::new(0x100);
337 pub const SIE: Csr = Csr::new(0x104);
338 pub const STVEC: Csr = Csr::new(0x105);
339 pub const SSCRATCH: Csr = Csr::new(0x140);
340 pub const SEPC: Csr = Csr::new(0x141);
341 pub const SCAUSE: Csr = Csr::new(0x142);
342 pub const STVAL: Csr = Csr::new(0x143);
343 pub const SIP: Csr = Csr::new(0x144);
344}
345
346pub mod reg {
348 use super::Register;
349
350 pub const X0: Register = Register::new(0);
352 pub const X1: Register = Register::new(1);
353 pub const X2: Register = Register::new(2);
354 pub const X3: Register = Register::new(3);
355 pub const X4: Register = Register::new(4);
356 pub const X5: Register = Register::new(5);
357 pub const X6: Register = Register::new(6);
358 pub const X7: Register = Register::new(7);
359 pub const X8: Register = Register::new(8);
360 pub const X9: Register = Register::new(9);
361 pub const X10: Register = Register::new(10);
362 pub const X11: Register = Register::new(11);
363 pub const X12: Register = Register::new(12);
364 pub const X13: Register = Register::new(13);
365 pub const X14: Register = Register::new(14);
366 pub const X15: Register = Register::new(15);
367 pub const X16: Register = Register::new(16);
368 pub const X17: Register = Register::new(17);
369 pub const X18: Register = Register::new(18);
370 pub const X19: Register = Register::new(19);
371 pub const X20: Register = Register::new(20);
372 pub const X21: Register = Register::new(21);
373 pub const X22: Register = Register::new(22);
374 pub const X23: Register = Register::new(23);
375 pub const X24: Register = Register::new(24);
376 pub const X25: Register = Register::new(25);
377 pub const X26: Register = Register::new(26);
378 pub const X27: Register = Register::new(27);
379 pub const X28: Register = Register::new(28);
380 pub const X29: Register = Register::new(29);
381 pub const X30: Register = Register::new(30);
382 pub const X31: Register = Register::new(31);
383
384 pub const ZERO: Register = X0; pub const RA: Register = X1; pub const SP: Register = X2; pub const GP: Register = X3; pub const TP: Register = X4; pub const T0: Register = X5; pub const T1: Register = X6; pub const T2: Register = X7; pub const S0: Register = X8; pub const FP: Register = X8; pub const S1: Register = X9; pub const A0: Register = X10; pub const A1: Register = X11; pub const A2: Register = X12; pub const A3: Register = X13; pub const A4: Register = X14; pub const A5: Register = X15; pub const A6: Register = X16; pub const A7: Register = X17; pub const S2: Register = X18; pub const S3: Register = X19; pub const S4: Register = X20; pub const S5: Register = X21; pub const S6: Register = X22; pub const S7: Register = X23; pub const S8: Register = X24; pub const S9: Register = X25; pub const S10: Register = X26; pub const S11: Register = X27; pub const T3: Register = X28; pub const T4: Register = X29; pub const T5: Register = X30; pub const T6: Register = X31; }