1use core::ops::{Add, Deref};
2
3use alloc::{boxed::Box, vec::Vec};
4
5use crate::{
6 flags::Flags,
7 operand::{Operand, OperandKind, Reg},
8};
9
10pub const INSN_ALIAS: u32 = 1 << 0;
11
12#[derive(Copy, Clone, Default, Debug, PartialEq, Eq)]
13pub struct Opcode(pub u32);
14
15impl Opcode {
16 pub const INVALID: Self = Self(0);
17}
18
19impl Add<u32> for Opcode {
20 type Output = Self;
21
22 fn add(self, rhs: u32) -> Self {
23 Self(self.0 + rhs)
24 }
25}
26
27#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
28pub struct Slot(u16);
29
30impl Default for Slot {
31 fn default() -> Self {
32 Self::NONE
33 }
34}
35
36impl Slot {
37 pub const NONE: Self = Self::new(0xffff);
38
39 pub const fn new(id: u16) -> Self {
40 Self(id)
41 }
42
43 pub const fn raw(&self) -> u16 {
44 self.0
45 }
46}
47
48#[derive(Clone, Default)]
49pub struct Insn {
50 opcode: Opcode,
51 flags: Flags,
52 operands: Vec<Operand>,
53 slot: Slot,
54}
55
56impl Insn {
57 pub fn clear(&mut self) {
58 self.opcode = Opcode::INVALID;
59 self.flags = Flags::empty();
60 self.operands.clear();
61 self.slot = Slot::NONE;
62 }
63
64 pub fn flags(&self) -> &Flags {
65 &self.flags
66 }
67
68 pub fn flags_mut(&mut self) -> &mut Flags {
69 &mut self.flags
70 }
71
72 pub fn is_alias(&self) -> bool {
73 self.flags.any(INSN_ALIAS)
74 }
75
76 pub fn set_alias(&mut self) {
77 self.flags.set(INSN_ALIAS);
78 }
79
80 pub fn slot(&self) -> Slot {
81 self.slot
82 }
83
84 pub fn set_slot(&mut self, slot: Slot) {
85 self.slot = slot;
86 }
87
88 pub fn opcode(&self) -> Opcode {
89 self.opcode
90 }
91
92 pub fn set_opcode(&mut self, opcode: Opcode) {
93 self.opcode = opcode;
94 }
95
96 pub fn operands(&self) -> &[Operand] {
97 self.operands.as_slice()
98 }
99
100 pub fn push_operand<T>(&mut self, operand: T)
101 where
102 T: Into<Operand>,
103 {
104 self.operands.push(operand.into());
105 }
106
107 pub fn push_operand_if_some<T>(&mut self, operand: Option<T>)
108 where
109 T: Into<Operand>,
110 {
111 if let Some(operand) = operand {
112 self.operands.push(operand.into());
113 }
114 }
115
116 pub fn push_reg(&mut self, reg: Reg) {
117 self.push_operand(OperandKind::Reg(reg));
118 }
119
120 pub fn push_offset(&mut self, reg: Reg, offset: i64) {
121 self.push_operand(OperandKind::Relative(reg, offset));
122 }
123
124 pub fn push_imm(&mut self, value: i64) {
125 self.push_operand(OperandKind::Imm(value));
126 }
127
128 pub fn push_uimm(&mut self, value: u64) {
129 self.push_operand(OperandKind::Uimm(value));
130 }
131
132 pub fn push_absolute(&mut self, addr: u64) {
133 self.push_operand(OperandKind::Absolute(addr));
134 }
135
136 pub fn push_indirect(&mut self, reg: Reg) {
137 self.push_operand(OperandKind::Indirect(reg));
138 }
139
140 pub fn push_pc_rel(&mut self, base: u64, offset: i64) {
141 self.push_operand(OperandKind::PcRelative(base, offset));
142 }
143
144 pub fn push_arch_spec(&mut self, a: u64, b: u64, c: u64) {
145 self.push_operand(OperandKind::ArchSpec(a, b, c));
146 }
147
148 pub fn push_arch_spec3(&mut self, a: impl Into<u64>, b: impl Into<u64>, c: impl Into<u64>) {
149 self.push_arch_spec(a.into(), b.into(), c.into());
150 }
151
152 pub fn push_arch_spec2(&mut self, a: impl Into<u64>, b: impl Into<u64>) {
153 self.push_arch_spec3(a, b, 0_u64);
154 }
155
156 pub fn push_arch_spec1(&mut self, a: impl Into<u64>) {
157 self.push_arch_spec2(a, 0_u64);
158 }
159}
160
161pub struct Bundle {
162 len: usize,
163 latency: u8,
164 insn: Box<[Insn]>,
165}
166
167impl Bundle {
168 pub fn empty() -> Self {
169 Self {
170 len: 0,
171 latency: 1,
172 insn: Box::new([]),
173 }
174 }
175
176 #[inline]
177 pub fn set_latency(&mut self, latency: u8) {
178 self.latency = latency;
179 }
180
181 #[inline]
182 pub fn latency(&self) -> usize {
183 self.latency as usize
184 }
185
186 pub fn as_slice(&self) -> &[Insn] {
187 &self.insn[..self.len]
188 }
189
190 pub fn clear(&mut self) {
191 self.len = 0;
192 self.latency = 1;
193 }
194
195 pub fn peek(&mut self) -> &mut Insn {
197 if self.insn.len() <= self.len {
198 let mut vec = core::mem::take(&mut self.insn).into_vec();
199 vec.resize(self.len + 4, Insn::default());
200 self.insn = vec.into_boxed_slice();
201 }
202 let insn = &mut self.insn[self.len];
203 insn.clear();
204 insn
205 }
206
207 pub fn next(&mut self) {
209 self.len += 1;
210 }
211
212 pub fn push_with<F>(&mut self, opcode: Opcode, mut f: F)
213 where
214 F: FnMut(&mut Insn),
215 {
216 let insn = self.peek();
217 insn.set_opcode(opcode);
218 f(insn);
219 self.next();
220 }
221
222 pub fn push(&mut self, opcode: Opcode) {
223 self.push_with(opcode, |_| ());
224 }
225}
226
227impl Deref for Bundle {
228 type Target = [Insn];
229
230 fn deref(&self) -> &Self::Target {
231 self.as_slice()
232 }
233}
234
235impl<'a> IntoIterator for &'a Bundle {
236 type Item = &'a Insn;
237 type IntoIter = core::slice::Iter<'a, Insn>;
238
239 fn into_iter(self) -> Self::IntoIter {
240 self.iter()
241 }
242}