]>
Commit | Line | Data |
---|---|---|
1d506c26 | 1 | /* Copyright (C) 2009-2024 Free Software Foundation, Inc. |
787749ea PL |
2 | Contributed by ARM Ltd. |
3 | ||
4 | This file is part of GDB. | |
5 | ||
6 | This program is free software; you can redistribute it and/or modify | |
7 | it under the terms of the GNU General Public License as published by | |
8 | the Free Software Foundation; either version 3 of the License, or | |
9 | (at your option) any later version. | |
10 | ||
11 | This program is distributed in the hope that it will be useful, | |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | GNU General Public License for more details. | |
15 | ||
16 | You should have received a copy of the GNU General Public License | |
17 | along with this program. If not, see <http://www.gnu.org/licenses/>. */ | |
18 | ||
1a5c2598 TT |
19 | #ifndef ARCH_AARCH64_INSN_H |
20 | #define ARCH_AARCH64_INSN_H | |
787749ea | 21 | |
491144b5 | 22 | extern bool aarch64_debug; |
787749ea | 23 | |
c6185dce SM |
24 | /* Print an "aarch64" debug statement. */ |
25 | ||
26 | #define aarch64_debug_printf(fmt, ...) \ | |
27 | debug_prefixed_printf_cond (aarch64_debug, "aarch64", fmt, ##__VA_ARGS__) | |
28 | ||
5382f971 LM |
29 | /* Support routines for instruction parsing. */ |
30 | ||
31 | /* Create a mask of X bits. */ | |
32 | #define submask(x) ((1L << ((x) + 1)) - 1) | |
33 | ||
34 | /* Extract the bitfield from OBJ starting at bit ST and ending at bit FN. */ | |
35 | #define bits(obj,st,fn) (((obj) >> (st)) & submask ((fn) - (st))) | |
36 | ||
37 | /* Extract bit ST from OBJ. */ | |
38 | #define bit(obj,st) (((obj) >> (st)) & 1) | |
39 | ||
40 | /* Extract the signed bitfield from OBJ starting at bit ST and ending at | |
41 | bit FN. The result is sign-extended. */ | |
42 | #define sbits(obj,st,fn) \ | |
43 | ((long) (bits(obj,st,fn) | ((long) bit(obj,fn) * ~ submask (fn - st)))) | |
44 | ||
37989733 LM |
45 | /* Prologue analyzer helper macros. */ |
46 | ||
47 | /* Is the instruction "bti"? */ | |
48 | #define IS_BTI(instruction) ((instruction & 0xffffff3f) == 0xd503241f) | |
49 | ||
b6542f81 YQ |
50 | /* List of opcodes that we need for building the jump pad and relocating |
51 | an instruction. */ | |
52 | ||
53 | enum aarch64_opcodes | |
54 | { | |
55 | /* B 0001 01ii iiii iiii iiii iiii iiii iiii */ | |
56 | /* BL 1001 01ii iiii iiii iiii iiii iiii iiii */ | |
57 | /* B.COND 0101 0100 iiii iiii iiii iiii iii0 cccc */ | |
58 | /* CBZ s011 0100 iiii iiii iiii iiii iiir rrrr */ | |
59 | /* CBNZ s011 0101 iiii iiii iiii iiii iiir rrrr */ | |
60 | /* TBZ b011 0110 bbbb biii iiii iiii iiir rrrr */ | |
61 | /* TBNZ b011 0111 bbbb biii iiii iiii iiir rrrr */ | |
62 | B = 0x14000000, | |
63 | BL = 0x80000000 | B, | |
64 | BCOND = 0x40000000 | B, | |
65 | CBZ = 0x20000000 | B, | |
66 | CBNZ = 0x21000000 | B, | |
67 | TBZ = 0x36000000 | B, | |
68 | TBNZ = 0x37000000 | B, | |
807f647c | 69 | /* BR 1101 0110 0001 1111 0000 00rr rrr0 0000 */ |
b6542f81 | 70 | /* BLR 1101 0110 0011 1111 0000 00rr rrr0 0000 */ |
807f647c | 71 | BR = 0xd61f0000, |
b6542f81 YQ |
72 | BLR = 0xd63f0000, |
73 | /* RET 1101 0110 0101 1111 0000 00rr rrr0 0000 */ | |
74 | RET = 0xd65f0000, | |
75 | /* STP s010 100o o0ii iiii irrr rrrr rrrr rrrr */ | |
76 | /* LDP s010 100o o1ii iiii irrr rrrr rrrr rrrr */ | |
77 | /* STP (SIMD&VFP) ss10 110o o0ii iiii irrr rrrr rrrr rrrr */ | |
78 | /* LDP (SIMD&VFP) ss10 110o o1ii iiii irrr rrrr rrrr rrrr */ | |
79 | STP = 0x28000000, | |
80 | LDP = 0x28400000, | |
81 | STP_SIMD_VFP = 0x04000000 | STP, | |
82 | LDP_SIMD_VFP = 0x04000000 | LDP, | |
83 | /* STR ss11 100o 00xi iiii iiii xxrr rrrr rrrr */ | |
84 | /* LDR ss11 100o 01xi iiii iiii xxrr rrrr rrrr */ | |
85 | /* LDRSW 1011 100o 10xi iiii iiii xxrr rrrr rrrr */ | |
86 | STR = 0x38000000, | |
87 | LDR = 0x00400000 | STR, | |
88 | LDRSW = 0x80800000 | STR, | |
89 | /* LDAXR ss00 1000 0101 1111 1111 11rr rrrr rrrr */ | |
90 | LDAXR = 0x085ffc00, | |
91 | /* STXR ss00 1000 000r rrrr 0111 11rr rrrr rrrr */ | |
92 | STXR = 0x08007c00, | |
93 | /* STLR ss00 1000 1001 1111 1111 11rr rrrr rrrr */ | |
94 | STLR = 0x089ffc00, | |
95 | /* MOV s101 0010 1xxi iiii iiii iiii iiir rrrr */ | |
96 | /* MOVK s111 0010 1xxi iiii iiii iiii iiir rrrr */ | |
97 | MOV = 0x52800000, | |
98 | MOVK = 0x20000000 | MOV, | |
99 | /* ADD s00o ooo1 xxxx xxxx xxxx xxxx xxxx xxxx */ | |
100 | /* SUB s10o ooo1 xxxx xxxx xxxx xxxx xxxx xxxx */ | |
101 | /* SUBS s11o ooo1 xxxx xxxx xxxx xxxx xxxx xxxx */ | |
102 | ADD = 0x01000000, | |
103 | SUB = 0x40000000 | ADD, | |
104 | SUBS = 0x20000000 | SUB, | |
105 | /* AND s000 1010 xx0x xxxx xxxx xxxx xxxx xxxx */ | |
106 | /* ORR s010 1010 xx0x xxxx xxxx xxxx xxxx xxxx */ | |
107 | /* ORN s010 1010 xx1x xxxx xxxx xxxx xxxx xxxx */ | |
108 | /* EOR s100 1010 xx0x xxxx xxxx xxxx xxxx xxxx */ | |
109 | AND = 0x0a000000, | |
110 | ORR = 0x20000000 | AND, | |
111 | ORN = 0x00200000 | ORR, | |
112 | EOR = 0x40000000 | AND, | |
113 | /* LSLV s001 1010 110r rrrr 0010 00rr rrrr rrrr */ | |
114 | /* LSRV s001 1010 110r rrrr 0010 01rr rrrr rrrr */ | |
115 | /* ASRV s001 1010 110r rrrr 0010 10rr rrrr rrrr */ | |
116 | LSLV = 0x1ac02000, | |
117 | LSRV = 0x00000400 | LSLV, | |
118 | ASRV = 0x00000800 | LSLV, | |
119 | /* SBFM s001 0011 0nii iiii iiii iirr rrrr rrrr */ | |
120 | SBFM = 0x13000000, | |
121 | /* UBFM s101 0011 0nii iiii iiii iirr rrrr rrrr */ | |
122 | UBFM = 0x40000000 | SBFM, | |
123 | /* CSINC s001 1010 100r rrrr cccc 01rr rrrr rrrr */ | |
124 | CSINC = 0x9a800400, | |
125 | /* MUL s001 1011 000r rrrr 0111 11rr rrrr rrrr */ | |
126 | MUL = 0x1b007c00, | |
127 | /* MSR (register) 1101 0101 0001 oooo oooo oooo ooor rrrr */ | |
128 | /* MRS 1101 0101 0011 oooo oooo oooo ooor rrrr */ | |
129 | MSR = 0xd5100000, | |
130 | MRS = 0x00200000 | MSR, | |
131 | /* HINT 1101 0101 0000 0011 0010 oooo ooo1 1111 */ | |
132 | HINT = 0xd503201f, | |
133 | SEVL = (5 << 5) | HINT, | |
134 | WFE = (2 << 5) | HINT, | |
135 | NOP = (0 << 5) | HINT, | |
136 | }; | |
137 | ||
807f647c MM |
138 | /* List of useful masks. */ |
139 | enum aarch64_masks | |
140 | { | |
141 | /* Used for masking out an Rn argument from an opcode. */ | |
142 | CLEAR_Rn_MASK = 0xfffffc1f, | |
143 | }; | |
144 | ||
b6542f81 YQ |
145 | /* Representation of a general purpose register of the form xN or wN. |
146 | ||
147 | This type is used by emitting functions that take registers as operands. */ | |
148 | ||
149 | struct aarch64_register | |
150 | { | |
151 | unsigned num; | |
152 | int is64; | |
153 | }; | |
154 | ||
6448a3e4 YQ |
155 | enum aarch64_memory_operand_type |
156 | { | |
157 | MEMORY_OPERAND_OFFSET, | |
158 | MEMORY_OPERAND_PREINDEX, | |
159 | MEMORY_OPERAND_POSTINDEX, | |
160 | }; | |
161 | ||
b6542f81 YQ |
162 | /* Representation of a memory operand, used for load and store |
163 | instructions. | |
164 | ||
165 | The types correspond to the following variants: | |
166 | ||
167 | MEMORY_OPERAND_OFFSET: LDR rt, [rn, #offset] | |
168 | MEMORY_OPERAND_PREINDEX: LDR rt, [rn, #index]! | |
169 | MEMORY_OPERAND_POSTINDEX: LDR rt, [rn], #index */ | |
170 | ||
171 | struct aarch64_memory_operand | |
172 | { | |
173 | /* Type of the operand. */ | |
6448a3e4 YQ |
174 | enum aarch64_memory_operand_type type; |
175 | ||
b6542f81 YQ |
176 | /* Index from the base register. */ |
177 | int32_t index; | |
178 | }; | |
179 | ||
180 | /* Helper macro to mask and shift a value into a bitfield. */ | |
181 | ||
182 | #define ENCODE(val, size, offset) \ | |
183 | ((uint32_t) ((val & ((1ULL << size) - 1)) << offset)) | |
184 | ||
6ec5f4be PL |
185 | int aarch64_decode_adr (CORE_ADDR addr, uint32_t insn, int *is_adrp, |
186 | unsigned *rd, int32_t *offset); | |
787749ea PL |
187 | |
188 | int aarch64_decode_b (CORE_ADDR addr, uint32_t insn, int *is_bl, | |
189 | int32_t *offset); | |
190 | ||
191 | int aarch64_decode_bcond (CORE_ADDR addr, uint32_t insn, unsigned *cond, | |
192 | int32_t *offset); | |
193 | ||
194 | int aarch64_decode_cb (CORE_ADDR addr, uint32_t insn, int *is64, | |
195 | int *is_cbnz, unsigned *rn, int32_t *offset); | |
196 | ||
197 | int aarch64_decode_tb (CORE_ADDR addr, uint32_t insn, int *is_tbnz, | |
198 | unsigned *bit, unsigned *rt, int32_t *imm); | |
199 | ||
246994ce YQ |
200 | int aarch64_decode_ldr_literal (CORE_ADDR addr, uint32_t insn, int *is_w, |
201 | int *is64, unsigned *rt, int32_t *offset); | |
202 | ||
203 | /* Data passed to each method of aarch64_insn_visitor. */ | |
204 | ||
205 | struct aarch64_insn_data | |
206 | { | |
207 | /* The instruction address. */ | |
208 | CORE_ADDR insn_addr; | |
209 | }; | |
210 | ||
211 | /* Visit different instructions by different methods. */ | |
212 | ||
213 | struct aarch64_insn_visitor | |
214 | { | |
215 | /* Visit instruction B/BL OFFSET. */ | |
216 | void (*b) (const int is_bl, const int32_t offset, | |
217 | struct aarch64_insn_data *data); | |
218 | ||
219 | /* Visit instruction B.COND OFFSET. */ | |
220 | void (*b_cond) (const unsigned cond, const int32_t offset, | |
221 | struct aarch64_insn_data *data); | |
222 | ||
223 | /* Visit instruction CBZ/CBNZ Rn, OFFSET. */ | |
224 | void (*cb) (const int32_t offset, const int is_cbnz, | |
225 | const unsigned rn, int is64, | |
226 | struct aarch64_insn_data *data); | |
227 | ||
228 | /* Visit instruction TBZ/TBNZ Rt, #BIT, OFFSET. */ | |
229 | void (*tb) (const int32_t offset, int is_tbnz, | |
230 | const unsigned rt, unsigned bit, | |
231 | struct aarch64_insn_data *data); | |
232 | ||
233 | /* Visit instruction ADR/ADRP Rd, OFFSET. */ | |
234 | void (*adr) (const int32_t offset, const unsigned rd, | |
235 | const int is_adrp, struct aarch64_insn_data *data); | |
236 | ||
237 | /* Visit instruction LDR/LDRSW Rt, OFFSET. */ | |
238 | void (*ldr_literal) (const int32_t offset, const int is_sw, | |
239 | const unsigned rt, const int is64, | |
240 | struct aarch64_insn_data *data); | |
241 | ||
242 | /* Visit instruction INSN of other kinds. */ | |
243 | void (*others) (const uint32_t insn, struct aarch64_insn_data *data); | |
244 | }; | |
245 | ||
246 | void aarch64_relocate_instruction (uint32_t insn, | |
247 | const struct aarch64_insn_visitor *visitor, | |
248 | struct aarch64_insn_data *data); | |
249 | ||
b6542f81 YQ |
250 | #define can_encode_int32(val, bits) \ |
251 | (((val) >> (bits)) == 0 || ((val) >> (bits)) == -1) | |
252 | ||
253 | /* Write a B or BL instruction into *BUF. | |
254 | ||
255 | B #offset | |
256 | BL #offset | |
257 | ||
258 | IS_BL specifies if the link register should be updated. | |
259 | OFFSET is the immediate offset from the current PC. It is | |
260 | byte-addressed but should be 4 bytes aligned. It has a limited range of | |
261 | +/- 128MB (26 bits << 2). */ | |
262 | ||
263 | #define emit_b(buf, is_bl, offset) \ | |
e1c587c3 | 264 | aarch64_emit_insn (buf, ((is_bl) ? BL : B) | (ENCODE ((offset) >> 2, 26, 0))) |
b6542f81 YQ |
265 | |
266 | /* Write a BCOND instruction into *BUF. | |
267 | ||
268 | B.COND #offset | |
269 | ||
270 | COND specifies the condition field. | |
271 | OFFSET is the immediate offset from the current PC. It is | |
272 | byte-addressed but should be 4 bytes aligned. It has a limited range of | |
273 | +/- 1MB (19 bits << 2). */ | |
274 | ||
e1c587c3 YQ |
275 | #define emit_bcond(buf, cond, offset) \ |
276 | aarch64_emit_insn (buf, \ | |
277 | BCOND | ENCODE ((offset) >> 2, 19, 5) \ | |
278 | | ENCODE ((cond), 4, 0)) | |
b6542f81 YQ |
279 | |
280 | /* Write a CBZ or CBNZ instruction into *BUF. | |
281 | ||
282 | CBZ rt, #offset | |
283 | CBNZ rt, #offset | |
284 | ||
285 | IS_CBNZ distinguishes between CBZ and CBNZ instructions. | |
286 | RN is the register to test. | |
287 | OFFSET is the immediate offset from the current PC. It is | |
288 | byte-addressed but should be 4 bytes aligned. It has a limited range of | |
289 | +/- 1MB (19 bits << 2). */ | |
290 | ||
e1c587c3 YQ |
291 | #define emit_cb(buf, is_cbnz, rt, offset) \ |
292 | aarch64_emit_insn (buf, \ | |
293 | ((is_cbnz) ? CBNZ : CBZ) \ | |
294 | | ENCODE (rt.is64, 1, 31) /* sf */ \ | |
295 | | ENCODE (offset >> 2, 19, 5) /* imm19 */ \ | |
296 | | ENCODE (rt.num, 5, 0)) | |
b6542f81 YQ |
297 | |
298 | /* Write a LDR instruction into *BUF. | |
299 | ||
300 | LDR rt, [rn, #offset] | |
301 | LDR rt, [rn, #index]! | |
302 | LDR rt, [rn], #index | |
303 | ||
304 | RT is the register to store. | |
305 | RN is the base address register. | |
306 | OFFSET is the immediate to add to the base address. It is limited to | |
307 | 0 .. 32760 range (12 bits << 3). */ | |
308 | ||
309 | #define emit_ldr(buf, rt, rn, operand) \ | |
1c2e1515 | 310 | aarch64_emit_load_store (buf, rt.is64 ? 3 : 2, LDR, rt, rn, operand) |
b6542f81 YQ |
311 | |
312 | /* Write a LDRSW instruction into *BUF. The register size is 64-bit. | |
313 | ||
314 | LDRSW xt, [rn, #offset] | |
315 | LDRSW xt, [rn, #index]! | |
316 | LDRSW xt, [rn], #index | |
317 | ||
318 | RT is the register to store. | |
319 | RN is the base address register. | |
320 | OFFSET is the immediate to add to the base address. It is limited to | |
321 | 0 .. 16380 range (12 bits << 2). */ | |
322 | ||
323 | #define emit_ldrsw(buf, rt, rn, operand) \ | |
1c2e1515 | 324 | aarch64_emit_load_store (buf, 3, LDRSW, rt, rn, operand) |
b6542f81 YQ |
325 | |
326 | ||
327 | /* Write a TBZ or TBNZ instruction into *BUF. | |
328 | ||
329 | TBZ rt, #bit, #offset | |
330 | TBNZ rt, #bit, #offset | |
331 | ||
332 | IS_TBNZ distinguishes between TBZ and TBNZ instructions. | |
333 | RT is the register to test. | |
334 | BIT is the index of the bit to test in register RT. | |
335 | OFFSET is the immediate offset from the current PC. It is | |
336 | byte-addressed but should be 4 bytes aligned. It has a limited range of | |
337 | +/- 32KB (14 bits << 2). */ | |
338 | ||
e1c587c3 YQ |
339 | #define emit_tb(buf, is_tbnz, bit, rt, offset) \ |
340 | aarch64_emit_insn (buf, \ | |
341 | ((is_tbnz) ? TBNZ: TBZ) \ | |
342 | | ENCODE (bit >> 5, 1, 31) /* b5 */ \ | |
343 | | ENCODE (bit, 5, 19) /* b40 */ \ | |
344 | | ENCODE (offset >> 2, 14, 5) /* imm14 */ \ | |
345 | | ENCODE (rt.num, 5, 0)) | |
b6542f81 YQ |
346 | |
347 | /* Write a NOP instruction into *BUF. */ | |
348 | ||
e1c587c3 | 349 | #define emit_nop(buf) aarch64_emit_insn (buf, NOP) |
b6542f81 | 350 | |
e1c587c3 | 351 | int aarch64_emit_insn (uint32_t *buf, uint32_t insn); |
b6542f81 | 352 | |
1c2e1515 YQ |
353 | int aarch64_emit_load_store (uint32_t *buf, uint32_t size, |
354 | enum aarch64_opcodes opcode, | |
355 | struct aarch64_register rt, | |
356 | struct aarch64_register rn, | |
357 | struct aarch64_memory_operand operand); | |
b6542f81 | 358 | |
1a5c2598 | 359 | #endif /* ARCH_AARCH64_INSN_H */ |