valheim_asm/isa/
untyped.rs

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/// untyped instruction
136#[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    // jal x0, -6*4
203    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}