1use std::fmt::{Debug, Formatter};
2
3use modular_bitfield::prelude::*;
4
5#[bitfield(bits = 32)]
6#[derive(Clone, Copy, Debug, Eq, PartialEq)]
7pub struct RType {
8 pub opcode: B7,
9 pub rd: B5,
10 pub funct3: B3,
11 pub rs1: B5,
12 pub rs2: B5,
13 pub funct7: B7,
14}
15
16#[bitfield(bits = 32)]
17#[derive(Clone, Copy, Debug, Eq, PartialEq)]
18pub struct IType {
19 pub opcode: B7,
20 pub rd: B5,
21 pub funct3: B3,
22 pub rs1: B5,
23 pub imm11_0: B12,
24}
25
26#[bitfield(bits = 32)]
27#[derive(Clone, Copy, Debug, Eq, PartialEq)]
28pub struct SType {
29 pub opcode: B7,
30 pub imm4_0: B5,
31 pub funct3: B3,
32 pub rs1: B5,
33 pub rs2: B5,
34 pub imm11_5: B7,
35}
36
37#[bitfield(bits = 32)]
38#[derive(Clone, Copy, Debug, Eq, PartialEq)]
39pub struct BType {
40 pub opcode: B7,
41 pub imm11: B1,
42 pub imm4_1: B4,
43 pub funct3: B3,
44 pub rs1: B5,
45 pub rs2: B5,
46 pub imm10_5: B6,
47 pub imm12: B1,
48}
49
50#[bitfield(bits = 32)]
51#[derive(Clone, Copy, Debug, Eq, PartialEq)]
52pub struct UType {
53 pub opcode: B7,
54 pub rd: B5,
55 pub imm31_12: B20,
56}
57
58#[bitfield(bits = 32)]
59#[derive(Clone, Copy, Debug, Eq, PartialEq)]
60pub struct JType {
61 pub opcode: B7,
62 pub rd: B5,
63 pub imm19_12: B8,
64 pub imm11: B1,
65 pub imm10_1: B10,
66 pub imm20: B1,
67}
68
69#[bitfield(bits = 32)]
70#[derive(Clone, Copy, Debug, Eq, PartialEq)]
71pub struct R4Type {
72 pub opcode: B7,
73 pub rd: B5,
74 pub funct3: B3,
75 pub rs1: B5,
76 pub rs2: B5,
77 pub funct2: B2,
78 pub rs3: B5,
79}
80
81#[bitfield(bits = 32)]
82#[derive(Clone, Copy, Debug, Eq, PartialEq)]
83pub struct RShamt32Type {
84 pub opcode: B7,
85 pub rd: B5,
86 pub funct3: B3,
87 pub rs1: B5,
88 pub shamt: B5,
89 pub funct7: B7,
90}
91
92#[bitfield(bits = 32)]
93#[derive(Clone, Copy, Debug, Eq, PartialEq)]
94pub struct RAType {
95 pub opcode: B7,
96 pub rd: B5,
97 pub funct3: B3,
98 pub rs1: B5,
99 pub rs2: B5,
100 pub rl: bool,
101 pub aq: bool,
102 pub funct5: B5,
103}
104
105#[bitfield(bits = 32)]
106#[derive(Clone, Copy, Debug, Eq, PartialEq)]
107pub struct RShamt64Type {
108 pub opcode: B7,
109 pub rd: B5,
110 pub funct3: B3,
111 pub rs1: B5,
112 pub shamt: B6,
113 pub funct6: B6,
114}
115
116#[bitfield(bits = 32)]
117#[derive(Clone, Copy, Debug, Eq, PartialEq)]
118pub struct FenceType {
119 pub opcode: B7,
120 pub rd: B5,
121 pub funct3: B3,
122 pub rs1: B5,
123 pub succ: B4,
124 pub pred: B4,
125 pub fm: B4,
126}
127
128#[bitfield(bits = 32)]
129#[derive(Clone, Copy, Debug, Eq, PartialEq)]
130pub struct OpcodePeek {
131 pub opcode: B7,
132 pub dummy: B25,
133}
134
135#[derive(Clone, Copy)]
137#[repr(C)]
138pub union Bytecode {
139 pub repr: u32,
140 pub peek: OpcodePeek,
141 pub r: RType,
142 pub r4: R4Type,
143 pub r_shamt32: RShamt32Type,
144 pub r_shamt64: RShamt64Type,
145 pub ra: RAType,
146 pub i: IType,
147 pub s: SType,
148 pub b: BType,
149 pub u: UType,
150 pub j: JType,
151 pub fence: FenceType,
152}
153
154#[macro_export] macro_rules! unsafe_wrapper {
155 ($ident:ident, $ty:ident) => {
156 #[inline(always)]
157 pub fn $ident(&self) -> $ty {
158 unsafe { self.$ident }
159 }
160 }
161}
162
163impl Bytecode {
164 #[inline(always)]
165 pub fn opcode(&self) -> u8 {
166 unsafe { self.peek.opcode() }
167 }
168 unsafe_wrapper!(repr, u32);
169 unsafe_wrapper!(r, RType);
170 unsafe_wrapper!(r4, R4Type);
171 unsafe_wrapper!(r_shamt32, RShamt32Type);
172 unsafe_wrapper!(r_shamt64, RShamt64Type);
173 unsafe_wrapper!(ra, RAType);
174 unsafe_wrapper!(i, IType);
175 unsafe_wrapper!(s, SType);
176 unsafe_wrapper!(b, BType);
177 unsafe_wrapper!(j, JType);
178 unsafe_wrapper!(u, UType);
179 unsafe_wrapper!(fence, FenceType);
180}
181
182impl Debug for Bytecode {
183 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
184 write!(f, "Bytecode({:#010b})", self.repr())
185 }
186}
187
188impl PartialEq for Bytecode {
189 fn eq(&self, other: &Self) -> bool {
190 self.repr() == other.repr()
191 }
192}
193
194impl Eq for Bytecode {}
195
196#[cfg(test)]
197mod tests {
198 use crate::isa::untyped::JType;
199
200 #[test]
201 fn test_layout() {
202 let instr_asm: u32 = 0b_1_1111110100_1_11111111_00000_1101111;
204 let instr = JType::from_bytes(instr_asm.to_le_bytes());
205 assert_eq!(instr.opcode(), 0b_1101111);
206 assert_eq!(instr.rd(), 0b0);
207 assert_eq!(instr.imm19_12(), 0b11111111);
208 assert_eq!(instr.imm11(), 0b1);
209 assert_eq!(instr.imm10_1(), 0b1111110100);
210 assert_eq!(instr.imm20(), 0b1);
211 }
212}