1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
|
use crate::asm::{imm_num_bits, uimm_num_bits};
/// This operand represents a signed immediate value.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct A64Imm
{
// Size in bits
pub num_bits: u8,
// The value of the immediate
pub value: i64
}
impl A64Imm {
pub fn new(value: i64) -> Self {
Self { num_bits: imm_num_bits(value), value }
}
}
/// This operand represents an unsigned immediate value.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct A64UImm
{
// Size in bits
pub num_bits: u8,
// The value of the immediate
pub value: u64
}
impl A64UImm {
pub fn new(value: u64) -> Self {
Self { num_bits: uimm_num_bits(value), value }
}
}
/// This operand represents a register.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct A64Reg
{
// Size in bits
pub num_bits: u8,
// Register index number
pub reg_no: u8,
}
#[derive(Clone, Copy, Debug)]
pub struct A64Mem
{
// Size in bits
pub num_bits: u8,
/// Base register number
pub base_reg_no: u8,
/// Constant displacement from the base, not scaled
pub disp: i32,
}
impl A64Mem {
pub fn new(reg: A64Opnd, disp: i32) -> Self {
match reg {
A64Opnd::Reg(reg) => {
Self {
num_bits: reg.num_bits,
base_reg_no: reg.reg_no,
disp
}
},
_ => panic!("Expected register operand")
}
}
}
#[derive(Clone, Copy, Debug)]
pub enum A64Opnd
{
// Dummy operand
None,
// Immediate value
Imm(A64Imm),
// Unsigned immediate
UImm(A64UImm),
// Register
Reg(A64Reg),
// Memory
Mem(A64Mem)
}
impl A64Opnd {
/// Create a new immediate value operand.
pub fn new_imm(value: i64) -> Self {
A64Opnd::Imm(A64Imm::new(value))
}
/// Create a new unsigned immediate value operand.
pub fn new_uimm(value: u64) -> Self {
A64Opnd::UImm(A64UImm::new(value))
}
/// Creates a new memory operand.
pub fn new_mem(reg: A64Opnd, disp: i32) -> Self {
A64Opnd::Mem(A64Mem::new(reg, disp))
}
/// Convenience function to check if this operand is a register.
pub fn is_reg(&self) -> bool {
match self {
A64Opnd::Reg(_) => true,
_ => false
}
}
}
pub const X0_REG: A64Reg = A64Reg { num_bits: 64, reg_no: 0 };
pub const X1_REG: A64Reg = A64Reg { num_bits: 64, reg_no: 1 };
pub const X2_REG: A64Reg = A64Reg { num_bits: 64, reg_no: 2 };
pub const X3_REG: A64Reg = A64Reg { num_bits: 64, reg_no: 3 };
pub const X12_REG: A64Reg = A64Reg { num_bits: 64, reg_no: 12 };
pub const X13_REG: A64Reg = A64Reg { num_bits: 64, reg_no: 13 };
// 64-bit registers
pub const X0: A64Opnd = A64Opnd::Reg(X0_REG);
pub const X1: A64Opnd = A64Opnd::Reg(X1_REG);
pub const X2: A64Opnd = A64Opnd::Reg(X2_REG);
pub const X3: A64Opnd = A64Opnd::Reg(X3_REG);
pub const X4: A64Opnd = A64Opnd::Reg(A64Reg { num_bits: 64, reg_no: 4 });
pub const X5: A64Opnd = A64Opnd::Reg(A64Reg { num_bits: 64, reg_no: 5 });
pub const X6: A64Opnd = A64Opnd::Reg(A64Reg { num_bits: 64, reg_no: 6 });
pub const X7: A64Opnd = A64Opnd::Reg(A64Reg { num_bits: 64, reg_no: 7 });
pub const X8: A64Opnd = A64Opnd::Reg(A64Reg { num_bits: 64, reg_no: 8 });
pub const X9: A64Opnd = A64Opnd::Reg(A64Reg { num_bits: 64, reg_no: 9 });
pub const X10: A64Opnd = A64Opnd::Reg(A64Reg { num_bits: 64, reg_no: 10 });
pub const X11: A64Opnd = A64Opnd::Reg(A64Reg { num_bits: 64, reg_no: 11 });
pub const X12: A64Opnd = A64Opnd::Reg(X12_REG);
pub const X13: A64Opnd = A64Opnd::Reg(X13_REG);
pub const X14: A64Opnd = A64Opnd::Reg(A64Reg { num_bits: 64, reg_no: 14 });
pub const X15: A64Opnd = A64Opnd::Reg(A64Reg { num_bits: 64, reg_no: 15 });
pub const X16: A64Opnd = A64Opnd::Reg(A64Reg { num_bits: 64, reg_no: 16 });
pub const X17: A64Opnd = A64Opnd::Reg(A64Reg { num_bits: 64, reg_no: 17 });
pub const X18: A64Opnd = A64Opnd::Reg(A64Reg { num_bits: 64, reg_no: 18 });
pub const X19: A64Opnd = A64Opnd::Reg(A64Reg { num_bits: 64, reg_no: 19 });
pub const X20: A64Opnd = A64Opnd::Reg(A64Reg { num_bits: 64, reg_no: 20 });
pub const X21: A64Opnd = A64Opnd::Reg(A64Reg { num_bits: 64, reg_no: 21 });
pub const X22: A64Opnd = A64Opnd::Reg(A64Reg { num_bits: 64, reg_no: 22 });
pub const X23: A64Opnd = A64Opnd::Reg(A64Reg { num_bits: 64, reg_no: 23 });
pub const X24: A64Opnd = A64Opnd::Reg(A64Reg { num_bits: 64, reg_no: 24 });
pub const X25: A64Opnd = A64Opnd::Reg(A64Reg { num_bits: 64, reg_no: 25 });
pub const X26: A64Opnd = A64Opnd::Reg(A64Reg { num_bits: 64, reg_no: 26 });
pub const X27: A64Opnd = A64Opnd::Reg(A64Reg { num_bits: 64, reg_no: 27 });
pub const X28: A64Opnd = A64Opnd::Reg(A64Reg { num_bits: 64, reg_no: 28 });
pub const X29: A64Opnd = A64Opnd::Reg(A64Reg { num_bits: 64, reg_no: 29 });
pub const X30: A64Opnd = A64Opnd::Reg(A64Reg { num_bits: 64, reg_no: 30 });
// 32-bit registers
pub const W0: A64Reg = A64Reg { num_bits: 32, reg_no: 0 };
pub const W1: A64Reg = A64Reg { num_bits: 32, reg_no: 1 };
pub const W2: A64Reg = A64Reg { num_bits: 32, reg_no: 2 };
pub const W3: A64Reg = A64Reg { num_bits: 32, reg_no: 3 };
pub const W4: A64Reg = A64Reg { num_bits: 32, reg_no: 4 };
pub const W5: A64Reg = A64Reg { num_bits: 32, reg_no: 5 };
pub const W6: A64Reg = A64Reg { num_bits: 32, reg_no: 6 };
pub const W7: A64Reg = A64Reg { num_bits: 32, reg_no: 7 };
pub const W8: A64Reg = A64Reg { num_bits: 32, reg_no: 8 };
pub const W9: A64Reg = A64Reg { num_bits: 32, reg_no: 9 };
pub const W10: A64Reg = A64Reg { num_bits: 32, reg_no: 10 };
pub const W11: A64Reg = A64Reg { num_bits: 32, reg_no: 11 };
pub const W12: A64Reg = A64Reg { num_bits: 32, reg_no: 12 };
pub const W13: A64Reg = A64Reg { num_bits: 32, reg_no: 13 };
pub const W14: A64Reg = A64Reg { num_bits: 32, reg_no: 14 };
pub const W15: A64Reg = A64Reg { num_bits: 32, reg_no: 15 };
pub const W16: A64Reg = A64Reg { num_bits: 32, reg_no: 16 };
pub const W17: A64Reg = A64Reg { num_bits: 32, reg_no: 17 };
pub const W18: A64Reg = A64Reg { num_bits: 32, reg_no: 18 };
pub const W19: A64Reg = A64Reg { num_bits: 32, reg_no: 19 };
pub const W20: A64Reg = A64Reg { num_bits: 32, reg_no: 20 };
pub const W21: A64Reg = A64Reg { num_bits: 32, reg_no: 21 };
pub const W22: A64Reg = A64Reg { num_bits: 32, reg_no: 22 };
pub const W23: A64Reg = A64Reg { num_bits: 32, reg_no: 23 };
pub const W24: A64Reg = A64Reg { num_bits: 32, reg_no: 24 };
pub const W25: A64Reg = A64Reg { num_bits: 32, reg_no: 25 };
pub const W26: A64Reg = A64Reg { num_bits: 32, reg_no: 26 };
pub const W27: A64Reg = A64Reg { num_bits: 32, reg_no: 27 };
pub const W28: A64Reg = A64Reg { num_bits: 32, reg_no: 28 };
pub const W29: A64Reg = A64Reg { num_bits: 32, reg_no: 29 };
pub const W30: A64Reg = A64Reg { num_bits: 32, reg_no: 30 };
// C argument registers
pub const C_ARG_REGS: [A64Opnd; 4] = [X0, X1, X2, X3];
|