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