1use super::instruction::*;
3use crate::common::InstructionBuilder;
4
5#[cfg(feature = "std")]
6use std::vec::Vec;
7#[cfg(not(feature = "std"))]
8use alloc::vec::Vec;
9
10pub struct Aarch64InstructionBuilder {
12 instructions: Vec<Instruction>,
13 #[cfg(feature = "register-tracking")]
14 register_usage: crate::common::register_usage::RegisterUsageInfo<Register>,
15}
16
17impl Aarch64InstructionBuilder {
18 pub fn new() -> Self {
19 Self {
20 instructions: Vec::new(),
21 #[cfg(feature = "register-tracking")]
22 register_usage: crate::common::register_usage::RegisterUsageInfo::new(),
23 }
24 }
25
26 #[cfg(feature = "register-tracking")]
28 fn track_written_register(&mut self, reg: Register) {
29 self.register_usage.add_written_register(reg);
30 }
31
32 #[cfg(feature = "register-tracking")]
34 fn track_read_register(&mut self, reg: Register) {
35 self.register_usage.add_read_register(reg);
36 }
37
38 #[cfg(feature = "register-tracking")]
40 fn track_read_registers(&mut self, regs: &[Register]) {
41 for ® in regs {
42 self.register_usage.add_read_register(reg);
43 }
44 }
45
46 #[cfg(not(feature = "register-tracking"))]
48 fn track_written_register(&mut self, _reg: Register) {
49 }
51
52 #[cfg(not(feature = "register-tracking"))]
53 fn track_read_register(&mut self, _reg: Register) {
54 }
56
57 #[cfg(not(feature = "register-tracking"))]
58 fn track_read_registers(&mut self, _regs: &[Register]) {
59 }
61
62 pub fn raw_instructions(&self) -> &[Instruction] {
70 &self.instructions
71 }
72
73 pub fn push(&mut self, instr: Instruction) -> &mut Self {
74 self.instructions.push(instr);
75 self
76 }
77
78 pub fn clear(&mut self) -> &mut Self {
79 self.instructions.clear();
80 #[cfg(feature = "register-tracking")]
81 self.register_usage.clear();
82 self
83 }
84
85 pub fn add(&mut self, rd: Register, rn: Register, rm: Register) -> &mut Self {
90 self.track_written_register(rd);
91 self.track_read_registers(&[rn, rm]);
92 let instr = encode_add_sub_reg(1, 0, 0, rm, 0, rn, rd); self.push(instr);
94 self
95 }
96
97 pub fn addi(&mut self, rd: Register, rn: Register, imm: u16) -> &mut Self {
100 self.track_written_register(rd);
101 self.track_read_register(rn);
102 let instr = encode_add_sub_imm(1, 0, 0, 0, imm, rn, rd); self.push(instr);
104 self
105 }
106
107 pub fn sub(&mut self, rd: Register, rn: Register, rm: Register) -> &mut Self {
110 self.track_written_register(rd);
111 self.track_read_registers(&[rn, rm]);
112 let instr = encode_add_sub_reg(1, 1, 0, rm, 0, rn, rd); self.push(instr);
114 self
115 }
116
117 pub fn subi(&mut self, rd: Register, rn: Register, imm: u16) -> &mut Self {
120 self.track_written_register(rd);
121 self.track_read_register(rn);
122 let instr = encode_add_sub_imm(1, 1, 0, 0, imm, rn, rd); self.push(instr);
124 self
125 }
126
127 pub fn mul(&mut self, rd: Register, rn: Register, rm: Register) -> &mut Self {
130 self.track_written_register(rd);
131 self.track_read_registers(&[rn, rm]);
132 let instr = encode_multiply(1, 0b000, rm, 0, Register::new(31), rn, rd); self.push(instr);
134 self
135 }
136
137 pub fn msub(&mut self, rd: Register, rn: Register, rm: Register, ra: Register) -> &mut Self {
140 self.track_written_register(rd);
141 self.track_read_registers(&[rn, rm, ra]);
142 let instr = encode_multiply(1, 0b000, rm, 1, ra, rn, rd); self.push(instr);
144 self
145 }
146
147 pub fn udiv(&mut self, rd: Register, rn: Register, rm: Register) -> &mut Self {
150 self.track_written_register(rd);
151 self.track_read_registers(&[rn, rm]);
152 let instr = encode_divide(1, 0b000010, rm, 1, rn, rd); self.push(instr);
154 self
155 }
156
157 pub fn sdiv(&mut self, rd: Register, rn: Register, rm: Register) -> &mut Self {
160 self.track_written_register(rd);
161 self.track_read_registers(&[rn, rm]);
162 let instr = encode_divide(1, 0b000011, rm, 1, rn, rd); self.push(instr);
164 self
165 }
166
167 pub fn or(&mut self, rd: Register, rn: Register, rm: Register) -> &mut Self {
196 self.track_written_register(rd);
197 self.track_read_registers(&[rn, rm]);
198 let instr = encode_logical_reg(1, 0b01, 0b00, 0, rm, 0, rn, rd); self.push(instr);
200 self
201 }
202
203 pub fn and(&mut self, rd: Register, rn: Register, rm: Register) -> &mut Self {
206 self.track_written_register(rd);
207 self.track_read_registers(&[rn, rm]);
208 let instr = encode_logical_reg(1, 0b00, 0b00, 0, rm, 0, rn, rd); self.push(instr);
210 self
211 }
212
213 pub fn xor(&mut self, rd: Register, rn: Register, rm: Register) -> &mut Self {
216 self.track_written_register(rd);
217 self.track_read_registers(&[rn, rm]);
218 let instr = encode_logical_reg(1, 0b10, 0b00, 0, rm, 0, rn, rd); self.push(instr);
220 self
221 }
222
223 pub fn mov(&mut self, rd: Register, rm: Register) -> &mut Self {
226 self.track_written_register(rd);
227 self.track_read_register(rm);
228 let instr = encode_move_reg(1, rm, rd); self.push(instr);
230 self
231 }
232
233 pub fn ret(&mut self) -> &mut Self {
236 self.track_read_register(reg::LR);
237 let instr = encode_ret(reg::LR); self.push(instr);
239 self
240 }
241
242 pub fn ret_reg(&mut self, rn: Register) -> &mut Self {
245 self.track_read_register(rn);
246 let instr = encode_ret(rn);
247 self.push(instr);
248 self
249 }
250
251 pub fn movz(&mut self, rd: Register, imm16: u16, shift: u8) -> &mut Self {
254 self.track_written_register(rd);
255 let instr = encode_movz(1, shift, imm16, rd); self.push(instr);
257 self
258 }
259
260 pub fn movk(&mut self, rd: Register, imm16: u16, shift: u8) -> &mut Self {
263 self.track_written_register(rd);
264 self.track_read_register(rd); let instr = encode_movk(1, shift, imm16, rd); self.push(instr);
267 self
268 }
269
270 pub fn mov_imm(&mut self, rd: Register, imm: u64) -> &mut Self {
272 if imm == 0 {
273 self.mov(rd, reg::XZR);
275 return self;
276 }
277
278 let chunk0 = (imm & 0xFFFF) as u16; let chunk1 = ((imm >> 16) & 0xFFFF) as u16; let chunk2 = ((imm >> 32) & 0xFFFF) as u16; let chunk3 = ((imm >> 48) & 0xFFFF) as u16; let mut first_movz_done = false;
286
287 if chunk0 != 0 {
288 self.movz(rd, chunk0, 0); first_movz_done = true;
290 }
291
292 if chunk1 != 0 {
293 if first_movz_done {
294 self.movk(rd, chunk1, 1); } else {
296 self.movz(rd, chunk1, 1); first_movz_done = true;
298 }
299 }
300
301 if chunk2 != 0 {
302 if first_movz_done {
303 self.movk(rd, chunk2, 2); } else {
305 self.movz(rd, chunk2, 2); first_movz_done = true;
307 }
308 }
309
310 if chunk3 != 0 {
311 if first_movz_done {
312 self.movk(rd, chunk3, 3); } else {
314 self.movz(rd, chunk3, 3); first_movz_done = true;
316 }
317 }
318
319 if !first_movz_done {
321 self.mov(rd, reg::XZR);
322 }
323
324 self
325 }
326
327 pub fn shl(&mut self, rd: Register, rn: Register, shift: u8) -> &mut Self {
330 if shift == 0 {
331 self.mov(rd, rn);
332 } else if shift <= 6 {
333 let multiplier = 1u16 << shift;
335 let temp_reg = reg::X17;
336 self.addi(temp_reg, reg::XZR, multiplier);
337 self.mul(rd, rn, temp_reg);
338 } else {
339 self.mov(rd, rn);
342 }
343 self
344 }
345}
346
347impl InstructionBuilder<Instruction> for Aarch64InstructionBuilder {
348 type Register = Register;
349
350 fn new() -> Self {
351 Self {
352 instructions: Vec::new(),
353 #[cfg(feature = "register-tracking")]
354 register_usage: crate::common::register_usage::RegisterUsageInfo::new(),
355 }
356 }
357
358 fn instructions(&self) -> crate::common::InstructionCollection<Instruction> {
359 crate::common::InstructionCollection::from_slice(&self.instructions)
360 }
361
362 fn push(&mut self, instr: Instruction) {
363 self.instructions.push(instr);
364 }
365
366 fn clear(&mut self) {
367 self.instructions.clear();
368 #[cfg(feature = "register-tracking")]
369 self.register_usage.clear();
370 }
371
372 #[cfg(feature = "register-tracking")]
373 fn register_usage(&self) -> &crate::common::register_usage::RegisterUsageInfo<Self::Register> {
374 &self.register_usage
375 }
376
377 #[cfg(feature = "register-tracking")]
378 fn register_usage_mut(&mut self) -> &mut crate::common::register_usage::RegisterUsageInfo<Self::Register> {
379 &mut self.register_usage
380 }
381
382 #[cfg(feature = "std")]
412 unsafe fn function<F>(&self) -> Result<crate::common::jit::CallableJitFunction<F>, crate::common::jit::JitError> {
413 let bytes = self.instructions().to_bytes();
414 crate::common::jit::CallableJitFunction::<F>::new(&bytes)
415 }
416
417 #[cfg(feature = "std")]
418 unsafe fn raw_function(&self) -> Result<crate::common::jit::RawCallableJitFunction, crate::common::jit::JitError> {
419 let bytes = self.instructions().to_bytes();
420 crate::common::jit::RawCallableJitFunction::new(&bytes)
421 }
422}