Commit | Line | Data |
---|---|---|
b811d2c2 | 1 | /* Copyright (C) 2009-2020 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 | |
b6542f81 YQ |
24 | /* List of opcodes that we need for building the jump pad and relocating |
25 | an instruction. */ | |
26 | ||
27 | enum aarch64_opcodes | |
28 | { | |
29 | /* B 0001 01ii iiii iiii iiii iiii iiii iiii */ | |
30 | /* BL 1001 01ii iiii iiii iiii iiii iiii iiii */ | |
31 | /* B.COND 0101 0100 iiii iiii iiii iiii iii0 cccc */ | |
32 | /* CBZ s011 0100 iiii iiii iiii iiii iiir rrrr */ | |
33 | /* CBNZ s011 0101 iiii iiii iiii iiii iiir rrrr */ | |
34 | /* TBZ b011 0110 bbbb biii iiii iiii iiir rrrr */ | |
35 | /* TBNZ b011 0111 bbbb biii iiii iiii iiir rrrr */ | |
36 | B = 0x14000000, | |
37 | BL = 0x80000000 | B, | |
38 | BCOND = 0x40000000 | B, | |
39 | CBZ = 0x20000000 | B, | |
40 | CBNZ = 0x21000000 | B, | |
41 | TBZ = 0x36000000 | B, | |
42 | TBNZ = 0x37000000 | B, | |
43 | /* BLR 1101 0110 0011 1111 0000 00rr rrr0 0000 */ | |
44 | BLR = 0xd63f0000, | |
45 | /* RET 1101 0110 0101 1111 0000 00rr rrr0 0000 */ | |
46 | RET = 0xd65f0000, | |
47 | /* STP s010 100o o0ii iiii irrr rrrr rrrr rrrr */ | |
48 | /* LDP s010 100o o1ii iiii irrr rrrr rrrr rrrr */ | |
49 | /* STP (SIMD&VFP) ss10 110o o0ii iiii irrr rrrr rrrr rrrr */ | |
50 | /* LDP (SIMD&VFP) ss10 110o o1ii iiii irrr rrrr rrrr rrrr */ | |
51 | STP = 0x28000000, | |
52 | LDP = 0x28400000, | |
53 | STP_SIMD_VFP = 0x04000000 | STP, | |
54 | LDP_SIMD_VFP = 0x04000000 | LDP, | |
55 | /* STR ss11 100o 00xi iiii iiii xxrr rrrr rrrr */ | |
56 | /* LDR ss11 100o 01xi iiii iiii xxrr rrrr rrrr */ | |
57 | /* LDRSW 1011 100o 10xi iiii iiii xxrr rrrr rrrr */ | |
58 | STR = 0x38000000, | |
59 | LDR = 0x00400000 | STR, | |
60 | LDRSW = 0x80800000 | STR, | |
61 | /* LDAXR ss00 1000 0101 1111 1111 11rr rrrr rrrr */ | |
62 | LDAXR = 0x085ffc00, | |
63 | /* STXR ss00 1000 000r rrrr 0111 11rr rrrr rrrr */ | |
64 | STXR = 0x08007c00, | |
65 | /* STLR ss00 1000 1001 1111 1111 11rr rrrr rrrr */ | |
66 | STLR = 0x089ffc00, | |
67 | /* MOV s101 0010 1xxi iiii iiii iiii iiir rrrr */ | |
68 | /* MOVK s111 0010 1xxi iiii iiii iiii iiir rrrr */ | |
69 | MOV = 0x52800000, | |
70 | MOVK = 0x20000000 | MOV, | |
71 | /* ADD s00o ooo1 xxxx xxxx xxxx xxxx xxxx xxxx */ | |
72 | /* SUB s10o ooo1 xxxx xxxx xxxx xxxx xxxx xxxx */ | |
73 | /* SUBS s11o ooo1 xxxx xxxx xxxx xxxx xxxx xxxx */ | |
74 | ADD = 0x01000000, | |
75 | SUB = 0x40000000 | ADD, | |
76 | SUBS = 0x20000000 | SUB, | |
77 | /* AND s000 1010 xx0x xxxx xxxx xxxx xxxx xxxx */ | |
78 | /* ORR s010 1010 xx0x xxxx xxxx xxxx xxxx xxxx */ | |
79 | /* ORN s010 1010 xx1x xxxx xxxx xxxx xxxx xxxx */ | |
80 | /* EOR s100 1010 xx0x xxxx xxxx xxxx xxxx xxxx */ | |
81 | AND = 0x0a000000, | |
82 | ORR = 0x20000000 | AND, | |
83 | ORN = 0x00200000 | ORR, | |
84 | EOR = 0x40000000 | AND, | |
85 | /* LSLV s001 1010 110r rrrr 0010 00rr rrrr rrrr */ | |
86 | /* LSRV s001 1010 110r rrrr 0010 01rr rrrr rrrr */ | |
87 | /* ASRV s001 1010 110r rrrr 0010 10rr rrrr rrrr */ | |
88 | LSLV = 0x1ac02000, | |
89 | LSRV = 0x00000400 | LSLV, | |
90 | ASRV = 0x00000800 | LSLV, | |
91 | /* SBFM s001 0011 0nii iiii iiii iirr rrrr rrrr */ | |
92 | SBFM = 0x13000000, | |
93 | /* UBFM s101 0011 0nii iiii iiii iirr rrrr rrrr */ | |
94 | UBFM = 0x40000000 | SBFM, | |
95 | /* CSINC s001 1010 100r rrrr cccc 01rr rrrr rrrr */ | |
96 | CSINC = 0x9a800400, | |
97 | /* MUL s001 1011 000r rrrr 0111 11rr rrrr rrrr */ | |
98 | MUL = 0x1b007c00, | |
99 | /* MSR (register) 1101 0101 0001 oooo oooo oooo ooor rrrr */ | |
100 | /* MRS 1101 0101 0011 oooo oooo oooo ooor rrrr */ | |
101 | MSR = 0xd5100000, | |
102 | MRS = 0x00200000 | MSR, | |
103 | /* HINT 1101 0101 0000 0011 0010 oooo ooo1 1111 */ | |
104 | HINT = 0xd503201f, | |
105 | SEVL = (5 << 5) | HINT, | |
106 | WFE = (2 << 5) | HINT, | |
107 | NOP = (0 << 5) | HINT, | |
108 | }; | |
109 | ||
110 | /* Representation of a general purpose register of the form xN or wN. | |
111 | ||
112 | This type is used by emitting functions that take registers as operands. */ | |
113 | ||
114 | struct aarch64_register | |
115 | { | |
116 | unsigned num; | |
117 | int is64; | |
118 | }; | |
119 | ||
6448a3e4 YQ |
120 | enum aarch64_memory_operand_type |
121 | { | |
122 | MEMORY_OPERAND_OFFSET, | |
123 | MEMORY_OPERAND_PREINDEX, | |
124 | MEMORY_OPERAND_POSTINDEX, | |
125 | }; | |
126 | ||
b6542f81 YQ |
127 | /* Representation of a memory operand, used for load and store |
128 | instructions. | |
129 | ||
130 | The types correspond to the following variants: | |
131 | ||
132 | MEMORY_OPERAND_OFFSET: LDR rt, [rn, #offset] | |
133 | MEMORY_OPERAND_PREINDEX: LDR rt, [rn, #index]! | |
134 | MEMORY_OPERAND_POSTINDEX: LDR rt, [rn], #index */ | |
135 | ||
136 | struct aarch64_memory_operand | |
137 | { | |
138 | /* Type of the operand. */ | |
6448a3e4 YQ |
139 | enum aarch64_memory_operand_type type; |
140 | ||
b6542f81 YQ |
141 | /* Index from the base register. */ |
142 | int32_t index; | |
143 | }; | |
144 | ||
145 | /* Helper macro to mask and shift a value into a bitfield. */ | |
146 | ||
147 | #define ENCODE(val, size, offset) \ | |
148 | ((uint32_t) ((val & ((1ULL << size) - 1)) << offset)) | |
149 | ||
6ec5f4be PL |
150 | int aarch64_decode_adr (CORE_ADDR addr, uint32_t insn, int *is_adrp, |
151 | unsigned *rd, int32_t *offset); | |
787749ea PL |
152 | |
153 | int aarch64_decode_b (CORE_ADDR addr, uint32_t insn, int *is_bl, | |
154 | int32_t *offset); | |
155 | ||
156 | int aarch64_decode_bcond (CORE_ADDR addr, uint32_t insn, unsigned *cond, | |
157 | int32_t *offset); | |
158 | ||
159 | int aarch64_decode_cb (CORE_ADDR addr, uint32_t insn, int *is64, | |
160 | int *is_cbnz, unsigned *rn, int32_t *offset); | |
161 | ||
162 | int aarch64_decode_tb (CORE_ADDR addr, uint32_t insn, int *is_tbnz, | |
163 | unsigned *bit, unsigned *rt, int32_t *imm); | |
164 | ||
246994ce YQ |
165 | int aarch64_decode_ldr_literal (CORE_ADDR addr, uint32_t insn, int *is_w, |
166 | int *is64, unsigned *rt, int32_t *offset); | |
167 | ||
168 | /* Data passed to each method of aarch64_insn_visitor. */ | |
169 | ||
170 | struct aarch64_insn_data | |
171 | { | |
172 | /* The instruction address. */ | |
173 | CORE_ADDR insn_addr; | |
174 | }; | |
175 | ||
176 | /* Visit different instructions by different methods. */ | |
177 | ||
178 | struct aarch64_insn_visitor | |
179 | { | |
180 | /* Visit instruction B/BL OFFSET. */ | |
181 | void (*b) (const int is_bl, const int32_t offset, | |
182 | struct aarch64_insn_data *data); | |
183 | ||
184 | /* Visit instruction B.COND OFFSET. */ | |
185 | void (*b_cond) (const unsigned cond, const int32_t offset, | |
186 | struct aarch64_insn_data *data); | |
187 | ||
188 | /* Visit instruction CBZ/CBNZ Rn, OFFSET. */ | |
189 | void (*cb) (const int32_t offset, const int is_cbnz, | |
190 | const unsigned rn, int is64, | |
191 | struct aarch64_insn_data *data); | |
192 | ||
193 | /* Visit instruction TBZ/TBNZ Rt, #BIT, OFFSET. */ | |
194 | void (*tb) (const int32_t offset, int is_tbnz, | |
195 | const unsigned rt, unsigned bit, | |
196 | struct aarch64_insn_data *data); | |
197 | ||
198 | /* Visit instruction ADR/ADRP Rd, OFFSET. */ | |
199 | void (*adr) (const int32_t offset, const unsigned rd, | |
200 | const int is_adrp, struct aarch64_insn_data *data); | |
201 | ||
202 | /* Visit instruction LDR/LDRSW Rt, OFFSET. */ | |
203 | void (*ldr_literal) (const int32_t offset, const int is_sw, | |
204 | const unsigned rt, const int is64, | |
205 | struct aarch64_insn_data *data); | |
206 | ||
207 | /* Visit instruction INSN of other kinds. */ | |
208 | void (*others) (const uint32_t insn, struct aarch64_insn_data *data); | |
209 | }; | |
210 | ||
211 | void aarch64_relocate_instruction (uint32_t insn, | |
212 | const struct aarch64_insn_visitor *visitor, | |
213 | struct aarch64_insn_data *data); | |
214 | ||
b6542f81 YQ |
215 | #define can_encode_int32(val, bits) \ |
216 | (((val) >> (bits)) == 0 || ((val) >> (bits)) == -1) | |
217 | ||
218 | /* Write a B or BL instruction into *BUF. | |
219 | ||
220 | B #offset | |
221 | BL #offset | |
222 | ||
223 | IS_BL specifies if the link register should be updated. | |
224 | OFFSET is the immediate offset from the current PC. It is | |
225 | byte-addressed but should be 4 bytes aligned. It has a limited range of | |
226 | +/- 128MB (26 bits << 2). */ | |
227 | ||
228 | #define emit_b(buf, is_bl, offset) \ | |
e1c587c3 | 229 | aarch64_emit_insn (buf, ((is_bl) ? BL : B) | (ENCODE ((offset) >> 2, 26, 0))) |
b6542f81 YQ |
230 | |
231 | /* Write a BCOND instruction into *BUF. | |
232 | ||
233 | B.COND #offset | |
234 | ||
235 | COND specifies the condition field. | |
236 | OFFSET is the immediate offset from the current PC. It is | |
237 | byte-addressed but should be 4 bytes aligned. It has a limited range of | |
238 | +/- 1MB (19 bits << 2). */ | |
239 | ||
e1c587c3 YQ |
240 | #define emit_bcond(buf, cond, offset) \ |
241 | aarch64_emit_insn (buf, \ | |
242 | BCOND | ENCODE ((offset) >> 2, 19, 5) \ | |
243 | | ENCODE ((cond), 4, 0)) | |
b6542f81 YQ |
244 | |
245 | /* Write a CBZ or CBNZ instruction into *BUF. | |
246 | ||
247 | CBZ rt, #offset | |
248 | CBNZ rt, #offset | |
249 | ||
250 | IS_CBNZ distinguishes between CBZ and CBNZ instructions. | |
251 | RN is the register to test. | |
252 | OFFSET is the immediate offset from the current PC. It is | |
253 | byte-addressed but should be 4 bytes aligned. It has a limited range of | |
254 | +/- 1MB (19 bits << 2). */ | |
255 | ||
e1c587c3 YQ |
256 | #define emit_cb(buf, is_cbnz, rt, offset) \ |
257 | aarch64_emit_insn (buf, \ | |
258 | ((is_cbnz) ? CBNZ : CBZ) \ | |
259 | | ENCODE (rt.is64, 1, 31) /* sf */ \ | |
260 | | ENCODE (offset >> 2, 19, 5) /* imm19 */ \ | |
261 | | ENCODE (rt.num, 5, 0)) | |
b6542f81 YQ |
262 | |
263 | /* Write a LDR instruction into *BUF. | |
264 | ||
265 | LDR rt, [rn, #offset] | |
266 | LDR rt, [rn, #index]! | |
267 | LDR rt, [rn], #index | |
268 | ||
269 | RT is the register to store. | |
270 | RN is the base address register. | |
271 | OFFSET is the immediate to add to the base address. It is limited to | |
272 | 0 .. 32760 range (12 bits << 3). */ | |
273 | ||
274 | #define emit_ldr(buf, rt, rn, operand) \ | |
1c2e1515 | 275 | aarch64_emit_load_store (buf, rt.is64 ? 3 : 2, LDR, rt, rn, operand) |
b6542f81 YQ |
276 | |
277 | /* Write a LDRSW instruction into *BUF. The register size is 64-bit. | |
278 | ||
279 | LDRSW xt, [rn, #offset] | |
280 | LDRSW xt, [rn, #index]! | |
281 | LDRSW xt, [rn], #index | |
282 | ||
283 | RT is the register to store. | |
284 | RN is the base address register. | |
285 | OFFSET is the immediate to add to the base address. It is limited to | |
286 | 0 .. 16380 range (12 bits << 2). */ | |
287 | ||
288 | #define emit_ldrsw(buf, rt, rn, operand) \ | |
1c2e1515 | 289 | aarch64_emit_load_store (buf, 3, LDRSW, rt, rn, operand) |
b6542f81 YQ |
290 | |
291 | ||
292 | /* Write a TBZ or TBNZ instruction into *BUF. | |
293 | ||
294 | TBZ rt, #bit, #offset | |
295 | TBNZ rt, #bit, #offset | |
296 | ||
297 | IS_TBNZ distinguishes between TBZ and TBNZ instructions. | |
298 | RT is the register to test. | |
299 | BIT is the index of the bit to test in register RT. | |
300 | OFFSET is the immediate offset from the current PC. It is | |
301 | byte-addressed but should be 4 bytes aligned. It has a limited range of | |
302 | +/- 32KB (14 bits << 2). */ | |
303 | ||
e1c587c3 YQ |
304 | #define emit_tb(buf, is_tbnz, bit, rt, offset) \ |
305 | aarch64_emit_insn (buf, \ | |
306 | ((is_tbnz) ? TBNZ: TBZ) \ | |
307 | | ENCODE (bit >> 5, 1, 31) /* b5 */ \ | |
308 | | ENCODE (bit, 5, 19) /* b40 */ \ | |
309 | | ENCODE (offset >> 2, 14, 5) /* imm14 */ \ | |
310 | | ENCODE (rt.num, 5, 0)) | |
b6542f81 YQ |
311 | |
312 | /* Write a NOP instruction into *BUF. */ | |
313 | ||
e1c587c3 | 314 | #define emit_nop(buf) aarch64_emit_insn (buf, NOP) |
b6542f81 | 315 | |
e1c587c3 | 316 | int aarch64_emit_insn (uint32_t *buf, uint32_t insn); |
b6542f81 | 317 | |
1c2e1515 YQ |
318 | int aarch64_emit_load_store (uint32_t *buf, uint32_t size, |
319 | enum aarch64_opcodes opcode, | |
320 | struct aarch64_register rt, | |
321 | struct aarch64_register rn, | |
322 | struct aarch64_memory_operand operand); | |
b6542f81 | 323 | |
1a5c2598 | 324 | #endif /* ARCH_AARCH64_INSN_H */ |