asmkit/aarch64/
assembler.rs1use crate::aarch64::opcodes::{Encoding, Opcode, INST_INFO};
2use crate::core::buffer::LabelUse;
3use crate::core::operand::*;
4use crate::core::{buffer::CodeBuffer, emitter::Emitter};
5use crate::AsmError;
6
7use super::emitter::A64EmitterExplicit;
8pub struct Assembler<'a> {
9 pub buffer: &'a mut CodeBuffer,
10 last_error: Option<AsmError>,
11}
12
13impl<'a> Assembler<'a> {
14 pub fn last_error(&self) -> Option<&AsmError> {
15 self.last_error.as_ref()
16 }
17
18 pub fn new(buffer: &'a mut CodeBuffer) -> Self {
19 Assembler {
20 buffer,
21 last_error: None,
22 }
23 }
24
25 fn use_label(&mut self, label: &Operand, kind: LabelUse) {
26 let off = self.buffer.cur_offset();
27 self.buffer
28 .use_label_at_offset(off, label.as_::<Label>(), kind);
29 }
30}
31
32macro_rules! enc_ops1 {
33 ($op0:ident) => {
34 OperandType::$op0 as u32
35 };
36}
37
38macro_rules! enc_ops2 {
39 ($op0:ident, $op1:ident) => {
40 (OperandType::$op0 as u32) | ((OperandType::$op1 as u32) << 3)
41 };
42}
43
44macro_rules! enc_ops3 {
45 ($op0:ident, $op1:ident, $op2:ident) => {
46 (OperandType::$op0 as u32)
47 | ((OperandType::$op1 as u32) << 3)
48 | ((OperandType::$op2 as u32) << 6)
49 };
50}
51
52macro_rules! enc_ops4 {
53 ($op0:ident, $op1:ident, $op2:ident, $op3:ident) => {
54 (OperandType::$op0 as u32)
55 | ((OperandType::$op1 as u32) << 3)
56 | ((OperandType::$op2 as u32) << 6)
57 | ((OperandType::$op3 as u32) << 9)
58 };
59}
60
61impl<'a> Emitter for Assembler<'a> {
62 fn emit_n(&mut self, opcode: i64, ops: &[&Operand]) {
63 assert!(opcode < Opcode::LAST as i64);
64
65 let opcode: Opcode = unsafe { core::mem::transmute(opcode as u16) };
66
67 let info = &INST_INFO[opcode as usize];
68
69 let isign3 = match ops {
70 [] => 0,
71 [op0] => op0.op_type() as u32,
72 [op0, op1] => op0.op_type() as u32 + ((op1.op_type() as u32) << 3),
73 [op0, op1, op2, ..] => {
74 op0.op_type() as u32 + ((op1.op_type() as u32) << 3) + ((op2.op_type() as u32) << 6)
75 }
76 };
77
78 let isign4 = match ops {
79 [] => 0,
80 [op0] => op0.op_type() as u32,
81 [op0, op1] => op0.op_type() as u32 + ((op1.op_type() as u32) << 3),
82 [op0, op1, op2] => {
83 op0.op_type() as u32 + ((op1.op_type() as u32) << 3) + ((op2.op_type() as u32) << 6)
84 }
85 [op0, op1, op2, op3, ..] => {
86 op0.op_type() as u32
87 + ((op1.op_type() as u32) << 3)
88 + ((op2.op_type() as u32) << 6)
89 + ((op3.op_type() as u32) << 9)
90 }
91 };
92
93 let err = match info.encoding {
94 Encoding::Empty => {
95 self.buffer.put4(info.val);
96 return;
97 }
98
99 Encoding::CondRelAddr19 => {
100 if isign3 == enc_ops2!(Imm, Label) {
101 let cond = ops[0].as_::<Imm>().value() as u32;
102
103 self.use_label(ops[1], LabelUse::A64Branch19);
104 self.buffer
105 .put4(info.val | (0 & 0x7ffff) << 5 | ((cond & 0xf) << 0));
106 return;
107 } else if isign3 == enc_ops2!(Imm, Imm) {
108 let cond = ops[0].as_::<Imm>().value() as u32;
109 let imm = ops[1].as_::<Imm>().value() as u32;
110 self.buffer
111 .put4(info.val | ((imm & 0x7ffff) << 5) | ((cond & 0xf) << 0));
112 return;
113 } else {
114 Some(AsmError::InvalidOperand)
115 }
116 }
117
118 Encoding::Const0 => {
119 self.buffer.put4(info.val | (0 & 0xf) << 8);
120 return;
121 }
122
123 Encoding::Const15 => {
124 self.buffer.put4(info.val | (15 & 0xf) << 8);
125 return;
126 }
127
128 Encoding::FpConst0 => {
129 if isign3 == enc_ops1!(Reg) {
130 let rn = ops[0].id();
131 self.buffer
132 .put4(info.val | (0 & 0x1f) << 16 | (rn & 0x1f) << 5);
133 return;
134 }
135
136 Some(AsmError::InvalidOperand)
137 }
138
139 Encoding::FpFp => {
140 if isign3 == enc_ops2!(Reg, Reg) {
141 let rm = ops[0].id();
142 let rn = ops[1].id();
143 self.buffer
144 .put4(info.val | (rm & 0x1f) << 16 | (rn & 0x1f) << 5);
145 return;
146 }
147
148 Some(AsmError::InvalidOperand)
149 }
150
151 Encoding::FpFpConst0 => {
152 if isign3 == enc_ops2!(Reg, Reg) {
153 let rd = ops[0].id();
154 let rn = ops[1].id();
155 self.buffer
156 .put4(info.val | (0 & 0x7) << 16 | (rn & 0x1f) << 5 | (rd & 0x1f) << 0);
157 return;
158 }
159
160 Some(AsmError::InvalidOperand)
161 }
162
163 Encoding::FpFpFp => {
164 if isign3 == enc_ops3!(Reg, Reg, Reg) {
165 let rd = ops[0].id();
166 let rn = ops[1].id();
167 let rm = ops[2].id();
168
169 self.buffer.put4(
170 info.val | ((rm & 0x1f) << 16) | (rn & 0x1f) << 5 | ((rd & 0x1f) << 0),
171 );
172 return;
173 }
174
175 Some(AsmError::InvalidOperand)
176 }
177
178 Encoding::FpFpFpCond => {
179 if isign4 == enc_ops4!(Reg, Reg, Reg, Imm) {
180 let rd = ops[0].id();
181 let rn = ops[1].id();
182 let rm = ops[2].id();
183 let cond = ops[3].as_::<Imm>().value();
184
185 self.buffer.put4(
186 info.val
187 | ((rm & 0x1f) << 16)
188 | ((cond as u32 & 0xf) << 12)
189 | (rn & 0x1f) << 5
190 | ((rd & 0x1f) << 0),
191 );
192 return;
193 }
194 Some(AsmError::InvalidOperand)
195 }
196
197 Encoding::FpFpFpFp => {
198 if isign4 == enc_ops4!(Reg, Reg, Reg, Reg) {
199 let rd = ops[0].id();
200 let rn = ops[1].id();
201 let rm = ops[2].id();
202 let ra = ops[3].id();
203
204 self.buffer.put4(
205 info.val
206 | ((rm & 0x1f) << 16)
207 | ((ra & 0x1f) << 10)
208 | (rn & 0x1f) << 5
209 | ((rd & 0x1f) << 0),
210 );
211 return;
212 }
213
214 Some(AsmError::InvalidOperand)
215 }
216
217 Encoding::FpFpFpImm => {
218 if isign4 == enc_ops4!(Reg, Reg, Reg, Imm) {
219 let rd = ops[0].id();
220 let rn = ops[1].id();
221 let rm = ops[2].id();
222 let imm4 = ops[3].as_::<Imm>().value() as i32 as u32;
223
224 self.buffer.put4(
225 info.val
226 | ((rm & 0x1f) << 16)
227 | ((imm4 & 0xf) << 11)
228 | ((rn & 0x1f) << 5)
229 | ((rd & 0x1f) << 0),
230 );
231 return;
232 }
233
234 Some(AsmError::InvalidOperand)
235 }
236
237 Encoding::FpFpFpImmRotAdd => {
238 if isign4 == enc_ops4!(Reg, Reg, Reg, Imm) {
239 let rd = ops[0].id();
240 let rn = ops[1].id();
241 let rm = ops[2].id();
242 let rot = ops[3].as_::<Imm>().value() as i32 as u32;
243 if rot == 90 || rot == 270 {
244 self.buffer.put4(
245 info.val
246 | ((rm & 0x1f) << 16)
247 | (((rot / 90 - 1) & 0x3) << 11)
248 | ((rn & 0x1f) << 5)
249 | ((rd & 0x1f) << 0),
250 );
251 return;
252 } else {
253 Some(AsmError::InvalidOperand)
254 }
255 } else {
256 Some(AsmError::InvalidOperand)
257 }
258 }
259
260 Encoding::FpFpFpImmRotMul => {
261 if isign4 == enc_ops4!(Reg, Reg, Reg, Imm) {
262 let rd = ops[0].id();
263 let rn = ops[1].id();
264 let rm = ops[2].id();
265 let rot = ops[3].as_::<Imm>().value() as i32 as u32;
266 if rot < 360 && rot % 90 == 0 {
267 self.buffer.put4(
268 info.val
269 | ((rm & 0x1f) << 16)
270 | (((rot / 90) & 0x3) << 11)
271 | ((rn & 0x1f) << 5)
272 | ((rd & 0x1f) << 0),
273 );
274 return;
275 } else {
276 Some(AsmError::InvalidOperand)
277 }
278 } else {
279 Some(AsmError::InvalidOperand)
280 }
281 }
282
283 Encoding::FpFpFpVelElemIdx0_1 => {
284 if isign4 == enc_ops4!(Reg, Reg, Reg, Imm) {
285 let rd = ops[0].id();
286 let rn = ops[1].id();
287 let mrm = ops[2].id();
288 let elemidx = ops[3].as_::<Imm>().value() as u32;
289 if mrm < 16 && elemidx < (1 << (4 - 1)) {
291 let v = info.val ^ mrm << 16
292 | ((((elemidx << 1) >> 2) & 0x1) << 21)
293 | ((((elemidx << 1) >> 1) & 0x1) << 20)
294 | (((((elemidx << 1) & 1) << 3) & 0xf) << 16)
295 | ((((elemidx << 1) >> 3) & 0x1) << 11)
296 | ((rn & 0x1f) << 5)
297 | ((rd & 0x1f) << 0);
298
299 self.buffer.put4(v);
300 return;
301 } else {
302 Some(AsmError::InvalidOperand)
303 }
304 } else {
305 Some(AsmError::InvalidOperand)
306 }
307 }
308
309 Encoding::FpFpFpVelElemIdx1 => {
310 if isign4 == enc_ops4!(Reg, Reg, Reg, Imm) {
311 let rd = ops[0].id();
312 let rn = ops[1].id();
313 let mrm = ops[2].id();
314
315 let elemidx = ops[3].id() as u32;
316 let val = (info.val)
317 | ((((elemidx << 1) >> 2) & 0x1) << 21)
318 | ((((elemidx << 1) >> 1) & 0x1) << 20)
319 | (((0) & 0xf) << 16)
320 | ((((elemidx << 1) >> 3) & 0x1) << 11)
321 | ((mrm & 0x1f) << 16)
322 | ((rn & 0x1f) << 5)
323 | ((rd & 0x1f) << 0);
324
325 self.buffer.put4(val);
326 return;
327 }
328
329 Some(AsmError::InvalidOperand)
330 }
331
332 _ => None,
333 };
334 self.last_error = err;
335 }
336
337 fn emit(&mut self, opcode: i64, op0: &Operand, op1: &Operand, op2: &Operand, op3: &Operand) {
338 let _ = opcode;
339 let _ = op0;
340 let _ = op1;
341 let _ = op2;
342 let _ = op3;
343 todo!()
344 }
345}
346
347impl<'a> A64EmitterExplicit for Assembler<'a> {}