]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/arch/aarch64-insn.c
gdb, gdbserver, gdbsupport: remove includes of early headers
[thirdparty/binutils-gdb.git] / gdb / arch / aarch64-insn.c
CommitLineData
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
787749ea
PL
19#include "aarch64-insn.h"
20
21/* Toggle this file's internal debugging dump. */
491144b5 22bool aarch64_debug = false;
787749ea 23
787749ea
PL
24/* Determine if specified bits within an instruction opcode matches a
25 specific pattern.
26
27 INSN is the instruction opcode.
28
29 MASK specifies the bits within the opcode that are to be tested
30baf67b 30 against for a match with PATTERN. */
787749ea
PL
31
32static int
33decode_masked_match (uint32_t insn, uint32_t mask, uint32_t pattern)
34{
35 return (insn & mask) == pattern;
36}
37
6ec5f4be 38/* Decode an opcode if it represents an ADR or ADRP instruction.
787749ea
PL
39
40 ADDR specifies the address of the opcode.
41 INSN specifies the opcode to test.
6ec5f4be 42 IS_ADRP receives the 'op' field from the decoded instruction.
787749ea 43 RD receives the 'rd' field from the decoded instruction.
6ec5f4be 44 OFFSET receives the 'immhi:immlo' field from the decoded instruction.
787749ea
PL
45
46 Return 1 if the opcodes matches and is decoded, otherwise 0. */
47
48int
6ec5f4be
PL
49aarch64_decode_adr (CORE_ADDR addr, uint32_t insn, int *is_adrp,
50 unsigned *rd, int32_t *offset)
787749ea 51{
6ec5f4be
PL
52 /* adr 0ii1 0000 iiii iiii iiii iiii iiir rrrr */
53 /* adrp 1ii1 0000 iiii iiii iiii iiii iiir rrrr */
54 if (decode_masked_match (insn, 0x1f000000, 0x10000000))
787749ea 55 {
6ec5f4be 56 uint32_t immlo = (insn >> 29) & 0x3;
5382f971 57 int32_t immhi = sbits (insn, 5, 23) * 4;
6ec5f4be
PL
58
59 *is_adrp = (insn >> 31) & 0x1;
787749ea
PL
60 *rd = (insn >> 0) & 0x1f;
61
6ec5f4be
PL
62 if (*is_adrp)
63 {
64 /* The ADRP instruction has an offset with a -/+ 4GB range,
65 encoded as (immhi:immlo * 4096). */
66 *offset = (immhi | immlo) * 4096;
67 }
68 else
69 *offset = (immhi | immlo);
70
c6185dce
SM
71 aarch64_debug_printf ("decode: 0x%s 0x%x %s x%u, #?",
72 core_addr_to_string_nz (addr), insn,
73 *is_adrp ? "adrp" : "adr", *rd);
787749ea
PL
74 return 1;
75 }
76 return 0;
77}
78
79/* Decode an opcode if it represents an branch immediate or branch
80 and link immediate instruction.
81
82 ADDR specifies the address of the opcode.
83 INSN specifies the opcode to test.
84 IS_BL receives the 'op' bit from the decoded instruction.
85 OFFSET receives the immediate offset from the decoded instruction.
86
87 Return 1 if the opcodes matches and is decoded, otherwise 0. */
88
89int
90aarch64_decode_b (CORE_ADDR addr, uint32_t insn, int *is_bl,
91 int32_t *offset)
92{
93 /* b 0001 01ii iiii iiii iiii iiii iiii iiii */
94 /* bl 1001 01ii iiii iiii iiii iiii iiii iiii */
95 if (decode_masked_match (insn, 0x7c000000, 0x14000000))
96 {
97 *is_bl = (insn >> 31) & 0x1;
5382f971 98 *offset = sbits (insn, 0, 25) * 4;
787749ea 99
b081c003
JB
100 aarch64_debug_printf ("decode: 0x%s 0x%x %s 0x%s",
101 core_addr_to_string_nz (addr), insn,
102 *is_bl ? "bl" : "b",
103 core_addr_to_string_nz (addr + *offset));
787749ea
PL
104
105 return 1;
106 }
107 return 0;
108}
109
110/* Decode an opcode if it represents a conditional branch instruction.
111
112 ADDR specifies the address of the opcode.
113 INSN specifies the opcode to test.
114 COND receives the branch condition field from the decoded
115 instruction.
116 OFFSET receives the immediate offset from the decoded instruction.
117
118 Return 1 if the opcodes matches and is decoded, otherwise 0. */
119
120int
121aarch64_decode_bcond (CORE_ADDR addr, uint32_t insn, unsigned *cond,
122 int32_t *offset)
123{
124 /* b.cond 0101 0100 iiii iiii iiii iiii iii0 cccc */
125 if (decode_masked_match (insn, 0xff000010, 0x54000000))
126 {
127 *cond = (insn >> 0) & 0xf;
5382f971 128 *offset = sbits (insn, 5, 23) * 4;
787749ea 129
b081c003
JB
130 aarch64_debug_printf ("decode: 0x%s 0x%x b<%u> 0x%s",
131 core_addr_to_string_nz (addr), insn, *cond,
132 core_addr_to_string_nz (addr + *offset));
787749ea
PL
133 return 1;
134 }
135 return 0;
136}
137
138/* Decode an opcode if it represents a CBZ or CBNZ instruction.
139
140 ADDR specifies the address of the opcode.
141 INSN specifies the opcode to test.
142 IS64 receives the 'sf' field from the decoded instruction.
143 IS_CBNZ receives the 'op' field from the decoded instruction.
144 RN receives the 'rn' field from the decoded instruction.
145 OFFSET receives the 'imm19' field from the decoded instruction.
146
147 Return 1 if the opcodes matches and is decoded, otherwise 0. */
148
149int
150aarch64_decode_cb (CORE_ADDR addr, uint32_t insn, int *is64, int *is_cbnz,
151 unsigned *rn, int32_t *offset)
152{
153 /* cbz T011 010o iiii iiii iiii iiii iiir rrrr */
154 /* cbnz T011 010o iiii iiii iiii iiii iiir rrrr */
155 if (decode_masked_match (insn, 0x7e000000, 0x34000000))
156 {
157 *rn = (insn >> 0) & 0x1f;
158 *is64 = (insn >> 31) & 0x1;
159 *is_cbnz = (insn >> 24) & 0x1;
5382f971 160 *offset = sbits (insn, 5, 23) * 4;
787749ea 161
b081c003
JB
162 aarch64_debug_printf ("decode: 0x%s 0x%x %s 0x%s",
163 core_addr_to_string_nz (addr), insn,
164 *is_cbnz ? "cbnz" : "cbz",
165 core_addr_to_string_nz (addr + *offset));
787749ea
PL
166 return 1;
167 }
168 return 0;
169}
170
171/* Decode an opcode if it represents a TBZ or TBNZ instruction.
172
173 ADDR specifies the address of the opcode.
174 INSN specifies the opcode to test.
175 IS_TBNZ receives the 'op' field from the decoded instruction.
176 BIT receives the bit position field from the decoded instruction.
177 RT receives 'rt' field from the decoded instruction.
178 IMM receives 'imm' field from the decoded instruction.
179
180 Return 1 if the opcodes matches and is decoded, otherwise 0. */
181
182int
183aarch64_decode_tb (CORE_ADDR addr, uint32_t insn, int *is_tbnz,
184 unsigned *bit, unsigned *rt, int32_t *imm)
185{
186 /* tbz b011 0110 bbbb biii iiii iiii iiir rrrr */
187 /* tbnz B011 0111 bbbb biii iiii iiii iiir rrrr */
188 if (decode_masked_match (insn, 0x7e000000, 0x36000000))
189 {
190 *rt = (insn >> 0) & 0x1f;
191 *is_tbnz = (insn >> 24) & 0x1;
192 *bit = ((insn >> (31 - 4)) & 0x20) | ((insn >> 19) & 0x1f);
5382f971 193 *imm = sbits (insn, 5, 18) * 4;
787749ea 194
b081c003
JB
195 aarch64_debug_printf ("decode: 0x%s 0x%x %s x%u, #%u, 0x%s",
196 core_addr_to_string_nz (addr), insn,
197 *is_tbnz ? "tbnz" : "tbz", *rt, *bit,
198 core_addr_to_string_nz (addr + *imm));
787749ea
PL
199 return 1;
200 }
201 return 0;
202}
246994ce
YQ
203
204/* Decode an opcode if it represents an LDR or LDRSW instruction taking a
205 literal offset from the current PC.
206
207 ADDR specifies the address of the opcode.
208 INSN specifies the opcode to test.
209 IS_W is set if the instruction is LDRSW.
210 IS64 receives size field from the decoded instruction.
211 RT receives the 'rt' field from the decoded instruction.
212 OFFSET receives the 'imm' field from the decoded instruction.
213
214 Return 1 if the opcodes matches and is decoded, otherwise 0. */
215
216int
217aarch64_decode_ldr_literal (CORE_ADDR addr, uint32_t insn, int *is_w,
218 int *is64, unsigned *rt, int32_t *offset)
219{
220 /* LDR 0T01 1000 iiii iiii iiii iiii iiir rrrr */
221 /* LDRSW 1001 1000 iiii iiii iiii iiii iiir rrrr */
222 if ((insn & 0x3f000000) == 0x18000000)
223 {
224 *is_w = (insn >> 31) & 0x1;
225
226 if (*is_w)
227 {
228 /* LDRSW always takes a 64-bit destination registers. */
229 *is64 = 1;
230 }
231 else
232 *is64 = (insn >> 30) & 0x1;
233
234 *rt = (insn >> 0) & 0x1f;
5382f971 235 *offset = sbits (insn, 5, 23) * 4;
246994ce 236
b081c003
JB
237 aarch64_debug_printf ("decode: %s 0x%x %s %s%u, #?",
238 core_addr_to_string_nz (addr), insn,
239 *is_w ? "ldrsw" : "ldr",
240 *is64 ? "x" : "w", *rt);
246994ce
YQ
241
242 return 1;
243 }
244
245 return 0;
246}
247
248/* Visit an instruction INSN by VISITOR with all needed information in DATA.
249
250 PC relative instructions need to be handled specifically:
251
252 - B/BL
253 - B.COND
254 - CBZ/CBNZ
255 - TBZ/TBNZ
256 - ADR/ADRP
257 - LDR/LDRSW (literal) */
258
259void
260aarch64_relocate_instruction (uint32_t insn,
261 const struct aarch64_insn_visitor *visitor,
262 struct aarch64_insn_data *data)
263{
264 int is_bl;
265 int is64;
266 int is_sw;
267 int is_cbnz;
268 int is_tbnz;
269 int is_adrp;
270 unsigned rn;
271 unsigned rt;
272 unsigned rd;
273 unsigned cond;
274 unsigned bit;
275 int32_t offset;
276
277 if (aarch64_decode_b (data->insn_addr, insn, &is_bl, &offset))
278 visitor->b (is_bl, offset, data);
279 else if (aarch64_decode_bcond (data->insn_addr, insn, &cond, &offset))
280 visitor->b_cond (cond, offset, data);
281 else if (aarch64_decode_cb (data->insn_addr, insn, &is64, &is_cbnz, &rn,
282 &offset))
283 visitor->cb (offset, is_cbnz, rn, is64, data);
284 else if (aarch64_decode_tb (data->insn_addr, insn, &is_tbnz, &bit, &rt,
285 &offset))
286 visitor->tb (offset, is_tbnz, rt, bit, data);
287 else if (aarch64_decode_adr (data->insn_addr, insn, &is_adrp, &rd, &offset))
288 visitor->adr (offset, rd, is_adrp, data);
289 else if (aarch64_decode_ldr_literal (data->insn_addr, insn, &is_sw, &is64,
290 &rt, &offset))
291 visitor->ldr_literal (offset, is_sw, rt, is64, data);
292 else
293 visitor->others (insn, data);
294}
b6542f81
YQ
295
296/* Write a 32-bit unsigned integer INSN info *BUF. Return the number of
297 instructions written (aka. 1). */
298
299int
e1c587c3 300aarch64_emit_insn (uint32_t *buf, uint32_t insn)
b6542f81
YQ
301{
302 *buf = insn;
303 return 1;
304}
305
306/* Helper function emitting a load or store instruction. */
307
308int
1c2e1515
YQ
309aarch64_emit_load_store (uint32_t *buf, uint32_t size,
310 enum aarch64_opcodes opcode,
311 struct aarch64_register rt,
312 struct aarch64_register rn,
313 struct aarch64_memory_operand operand)
b6542f81
YQ
314{
315 uint32_t op;
316
317 switch (operand.type)
318 {
319 case MEMORY_OPERAND_OFFSET:
320 {
321 op = ENCODE (1, 1, 24);
322
e1c587c3
YQ
323 return aarch64_emit_insn (buf, opcode | ENCODE (size, 2, 30) | op
324 | ENCODE (operand.index >> 3, 12, 10)
325 | ENCODE (rn.num, 5, 5)
326 | ENCODE (rt.num, 5, 0));
b6542f81
YQ
327 }
328 case MEMORY_OPERAND_POSTINDEX:
329 {
330 uint32_t post_index = ENCODE (1, 2, 10);
331
332 op = ENCODE (0, 1, 24);
333
e1c587c3
YQ
334 return aarch64_emit_insn (buf, opcode | ENCODE (size, 2, 30) | op
335 | post_index | ENCODE (operand.index, 9, 12)
336 | ENCODE (rn.num, 5, 5)
337 | ENCODE (rt.num, 5, 0));
b6542f81
YQ
338 }
339 case MEMORY_OPERAND_PREINDEX:
340 {
341 uint32_t pre_index = ENCODE (3, 2, 10);
342
343 op = ENCODE (0, 1, 24);
344
e1c587c3
YQ
345 return aarch64_emit_insn (buf, opcode | ENCODE (size, 2, 30) | op
346 | pre_index | ENCODE (operand.index, 9, 12)
347 | ENCODE (rn.num, 5, 5)
348 | ENCODE (rt.num, 5, 0));
b6542f81
YQ
349 }
350 default:
351 return 0;
352 }
353}