jit_assembler/aarch64/
instruction.rs1use core::fmt;
3use crate::common::{
4 Instruction as InstructionTrait,
5 Register as RegisterTrait,
6};
7
8#[cfg(feature = "std")]
9use std::vec::Vec;
10#[cfg(not(feature = "std"))]
11use alloc::vec::Vec;
12
13#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
15pub struct Register(pub u8);
16
17impl Register {
18 pub const fn new(reg: u8) -> Self {
19 Self(reg)
20 }
21
22 pub fn value(self) -> u8 {
23 self.0
24 }
25}
26
27impl RegisterTrait for Register {
28 fn id(&self) -> u32 {
29 self.0 as u32
30 }
31
32 fn abi_class(&self) -> crate::common::AbiClass {
33 use crate::common::AbiClass;
34
35 match self.0 {
36 0..=7 => AbiClass::CallerSaved, 8..=15 => AbiClass::CallerSaved, 16..=17 => AbiClass::CallerSaved, 18 => AbiClass::CallerSaved, 19..=28 => AbiClass::CalleeSaved, 29 => AbiClass::Special, 30 => AbiClass::Special, 31 => AbiClass::Special, _ => AbiClass::Special,
52 }
53 }
54}
55
56#[derive(Debug, Clone, Copy, PartialEq, Eq)]
58pub struct Instruction(pub u32);
59
60impl Instruction {
61 pub fn new(value: u32) -> Self {
63 Self(value)
64 }
65
66 pub fn value(self) -> u32 {
68 self.0
69 }
70
71 pub fn bytes(self) -> Vec<u8> {
73 self.0.to_le_bytes().to_vec()
74 }
75}
76
77impl InstructionTrait for Instruction {
78 fn value(&self) -> u64 {
79 self.0 as u64
80 }
81
82 fn bytes(&self) -> Vec<u8> {
83 self.0.to_le_bytes().to_vec()
84 }
85
86 fn size(&self) -> usize {
87 4
88 }
89}
90
91impl fmt::Display for Instruction {
92 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
93 write!(f, "0x{:08x}", self.0)
94 }
95}
96
97pub fn encode_add_sub_reg(sf: u8, op: u8, s: u8, rm: Register, imm6: u8, rn: Register, rd: Register) -> Instruction {
99 let instr = ((sf as u32) << 31) |
111 ((op as u32) << 30) |
112 ((s as u32) << 29) |
113 (0b01011 << 24) | (0b00 << 22) | (0 << 21) | ((rm.value() as u32) << 16) |
117 ((imm6 as u32) << 10) |
118 ((rn.value() as u32) << 5) |
119 (rd.value() as u32);
120 Instruction::new(instr)
121}
122
123pub fn encode_add_sub_imm(sf: u8, op: u8, s: u8, sh: u8, imm12: u16, rn: Register, rd: Register) -> Instruction {
125 let instr = ((sf as u32) << 31) |
126 ((op as u32) << 30) |
127 ((s as u32) << 29) |
128 (0b10001 << 24) | ((sh as u32) << 22) |
130 ((imm12 as u32) << 10) |
131 ((rn.value() as u32) << 5) |
132 (rd.value() as u32);
133 Instruction::new(instr)
134}
135
136pub fn encode_logical_reg(sf: u8, opc: u8, shift: u8, n: u8, rm: Register, imm6: u8, rn: Register, rd: Register) -> Instruction {
138 let instr = ((sf as u32) << 31) |
139 ((opc as u32) << 29) |
140 (0b01010 << 24) | ((shift as u32) << 22) |
142 ((n as u32) << 21) |
143 ((rm.value() as u32) << 16) |
144 ((imm6 as u32) << 10) |
145 ((rn.value() as u32) << 5) |
146 (rd.value() as u32);
147 Instruction::new(instr)
148}
149
150pub fn encode_multiply(sf: u8, op31: u8, rm: Register, o0: u8, ra: Register, rn: Register, rd: Register) -> Instruction {
152 let instr = ((sf as u32) << 31) | (0b00 << 29) | (0b11011 << 24) | ((op31 as u32) << 21) | ((rm.value() as u32) << 16) | ((o0 as u32) << 15) | ((ra.value() as u32) << 10) | ((rn.value() as u32) << 5) | (rd.value() as u32); Instruction::new(instr)
166}
167
168pub fn encode_divide(sf: u8, opcode: u8, rm: Register, _o0: u8, rn: Register, rd: Register) -> Instruction {
170 let instr = ((sf as u32) << 31) | (0b0 << 30) | (0b0 << 29) | (0b11010110 << 21) | ((rm.value() as u32) << 16) | ((opcode as u32) << 10) | ((rn.value() as u32) << 5) | (rd.value() as u32); Instruction::new(instr)
183}
184
185pub fn encode_move_reg(sf: u8, rm: Register, rd: Register) -> Instruction {
187 encode_logical_reg(sf, 0b01, 0b00, 0, rm, 0, Register::new(31), rd)
189}
190
191pub fn encode_ret(rn: Register) -> Instruction {
193 let instr = 0xd6000000 | (0x5f << 16) | ((rn.value() as u32) << 5); Instruction::new(instr)
201}
202
203pub fn encode_branch_reg(opc: u8, op2: u8, op3: u8, rn: Register, op4: u8) -> Instruction {
205 let instr = (0b1101011 << 25) |
206 ((opc as u32) << 21) |
207 ((op2 as u32) << 16) |
208 ((op3 as u32) << 10) |
209 ((rn.value() as u32) << 5) |
210 (op4 as u32);
211 Instruction::new(instr)
212}
213
214pub mod reg {
216 use super::Register;
217
218 pub const X0: Register = Register::new(0);
220 pub const X1: Register = Register::new(1);
221 pub const X2: Register = Register::new(2);
222 pub const X3: Register = Register::new(3);
223 pub const X4: Register = Register::new(4);
224 pub const X5: Register = Register::new(5);
225 pub const X6: Register = Register::new(6);
226 pub const X7: Register = Register::new(7);
227 pub const X8: Register = Register::new(8);
228 pub const X9: Register = Register::new(9);
229 pub const X10: Register = Register::new(10);
230 pub const X11: Register = Register::new(11);
231 pub const X12: Register = Register::new(12);
232 pub const X13: Register = Register::new(13);
233 pub const X14: Register = Register::new(14);
234 pub const X15: Register = Register::new(15);
235 pub const X16: Register = Register::new(16);
236 pub const X17: Register = Register::new(17);
237 pub const X18: Register = Register::new(18);
238 pub const X19: Register = Register::new(19);
239 pub const X20: Register = Register::new(20);
240 pub const X21: Register = Register::new(21);
241 pub const X22: Register = Register::new(22);
242 pub const X23: Register = Register::new(23);
243 pub const X24: Register = Register::new(24);
244 pub const X25: Register = Register::new(25);
245 pub const X26: Register = Register::new(26);
246 pub const X27: Register = Register::new(27);
247 pub const X28: Register = Register::new(28);
248 pub const X29: Register = Register::new(29);
249 pub const X30: Register = Register::new(30);
250
251 pub const SP: Register = Register::new(31); pub const XZR: Register = Register::new(31); pub const WZR: Register = Register::new(31); pub const FP: Register = X29; pub const LR: Register = X30; }
260
261pub fn encode_movz(sf: u8, hw: u8, imm16: u16, rd: Register) -> Instruction {
263 let instr = ((sf as u32) << 31) | (0b10 << 29) | (0b100101 << 23) | ((hw as u32) << 21) | ((imm16 as u32) << 5) | (rd.value() as u32); Instruction::new(instr)
273}
274
275pub fn encode_movk(sf: u8, hw: u8, imm16: u16, rd: Register) -> Instruction {
277 let instr = ((sf as u32) << 31) | (0b11 << 29) | (0b100101 << 23) | ((hw as u32) << 21) | ((imm16 as u32) << 5) | (rd.value() as u32); Instruction::new(instr)
287}