asmkit/aarch64/
assembler.rs

1use 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                    // TODO: Broken
290                    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> {}