gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / opcodes / avr-dis.c
CommitLineData
adde6300 1/* Disassemble AVR instructions.
b3adc24a 2 Copyright (C) 1999-2020 Free Software Foundation, Inc.
adde6300
AM
3
4 Contributed by Denis Chertykov <denisc@overta.ru>
5
9b201bb5
NC
6 This file is part of libopcodes.
7
8 This library is free software; you can redistribute it and/or modify
47b0e7ad 9 it under the terms of the GNU General Public License as published by
9b201bb5
NC
10 the Free Software Foundation; either version 3, or (at your option)
11 any later version.
adde6300 12
9b201bb5
NC
13 It is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
16 License for more details.
adde6300 17
47b0e7ad
NC
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
9b201bb5
NC
20 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21 MA 02110-1301, USA. */
adde6300 22
0d8dfecf 23#include "sysdep.h"
df7b86aa 24#include <assert.h>
88c1242d 25#include "disassemble.h"
adde6300 26#include "opintl.h"
11041102 27#include "libiberty.h"
0a7e1018 28#include "bfd_stdint.h"
3c504221 29
bab84c47 30struct avr_opcodes_s
adde6300 31{
bab84c47
DC
32 char *name;
33 char *constraints;
34 char *opcode;
47b0e7ad 35 int insn_size; /* In words. */
bab84c47
DC
36 int isa;
37 unsigned int bin_opcode;
bab84c47 38};
adde6300 39
bab84c47 40#define AVR_INSN(NAME, CONSTR, OPCODE, SIZE, ISA, BIN) \
11041102 41{#NAME, CONSTR, OPCODE, SIZE, ISA, BIN},
adde6300 42
11041102 43const struct avr_opcodes_s avr_opcodes[] =
adde6300 44{
bab84c47 45 #include "opcode/avr.h"
11041102 46 {NULL, NULL, NULL, 0, 0, 0}
bab84c47 47};
adde6300 48
af692060
NC
49static const char * comment_start = "0x";
50
463f102c 51static int
246f4c05 52avr_operand (unsigned int insn, unsigned int insn2, unsigned int pc, int constraint,
8cc66334 53 char *opcode_str, char *buf, char *comment, int regs, int *sym, bfd_vma *sym_addr)
adde6300 54{
463f102c 55 int ok = 1;
246f4c05 56 *sym = 0;
463f102c 57
bab84c47
DC
58 switch (constraint)
59 {
60 /* Any register operand. */
61 case 'r':
62 if (regs)
47b0e7ad 63 insn = (insn & 0xf) | ((insn & 0x0200) >> 5); /* Source register. */
bab84c47 64 else
47b0e7ad 65 insn = (insn & 0x01f0) >> 4; /* Destination register. */
43e65147 66
bab84c47
DC
67 sprintf (buf, "r%d", insn);
68 break;
69
70 case 'd':
71 if (regs)
72 sprintf (buf, "r%d", 16 + (insn & 0xf));
73 else
74 sprintf (buf, "r%d", 16 + ((insn & 0xf0) >> 4));
75 break;
43e65147 76
bab84c47
DC
77 case 'w':
78 sprintf (buf, "r%d", 24 + ((insn & 0x30) >> 3));
79 break;
43e65147 80
bab84c47
DC
81 case 'a':
82 if (regs)
83 sprintf (buf, "r%d", 16 + (insn & 7));
84 else
85 sprintf (buf, "r%d", 16 + ((insn >> 4) & 7));
86 break;
adde6300 87
bab84c47
DC
88 case 'v':
89 if (regs)
90 sprintf (buf, "r%d", (insn & 0xf) * 2);
91 else
92 sprintf (buf, "r%d", ((insn & 0xf0) >> 3));
93 break;
94
95 case 'e':
463f102c
DC
96 {
97 char *xyz;
98
99 switch (insn & 0x100f)
100 {
101 case 0x0000: xyz = "Z"; break;
102 case 0x1001: xyz = "Z+"; break;
103 case 0x1002: xyz = "-Z"; break;
104 case 0x0008: xyz = "Y"; break;
105 case 0x1009: xyz = "Y+"; break;
106 case 0x100a: xyz = "-Y"; break;
107 case 0x100c: xyz = "X"; break;
108 case 0x100d: xyz = "X+"; break;
109 case 0x100e: xyz = "-X"; break;
110 default: xyz = "??"; ok = 0;
111 }
c8941035 112 strcpy (buf, xyz);
463f102c
DC
113
114 if (AVR_UNDEF_P (insn))
115 sprintf (comment, _("undefined"));
116 }
bab84c47
DC
117 break;
118
119 case 'z':
120 *buf++ = 'Z';
8cc66334
EW
121
122 /* Check for post-increment. */
123 char *s;
124 for (s = opcode_str; *s; ++s)
125 {
126 if (*s == '+')
127 {
5d73b1f1
NC
128 if (insn & (1 << (15 - (s - opcode_str))))
129 *buf++ = '+';
8cc66334
EW
130 break;
131 }
132 }
133
bab84c47 134 *buf = '\0';
463f102c
DC
135 if (AVR_UNDEF_P (insn))
136 sprintf (comment, _("undefined"));
bab84c47
DC
137 break;
138
139 case 'b':
140 {
463f102c 141 unsigned int x;
43e65147 142
bab84c47
DC
143 x = (insn & 7);
144 x |= (insn >> 7) & (3 << 3);
145 x |= (insn >> 8) & (1 << 5);
43e65147 146
bab84c47
DC
147 if (insn & 0x8)
148 *buf++ = 'Y';
149 else
150 *buf++ = 'Z';
151 sprintf (buf, "+%d", x);
152 sprintf (comment, "0x%02x", x);
153 }
154 break;
43e65147 155
bab84c47 156 case 'h':
246f4c05
SS
157 *sym = 1;
158 *sym_addr = ((((insn & 1) | ((insn & 0x1f0) >> 3)) << 16) | insn2) * 2;
c4f5c3d7 159 /* See PR binutils/2454. Ideally we would like to display the hex
52f16a0e
NC
160 value of the address only once, but this would mean recoding
161 objdump_print_address() which would affect many targets. */
43e65147 162 sprintf (buf, "%#lx", (unsigned long) *sym_addr);
c8941035 163 strcpy (comment, comment_start);
bab84c47 164 break;
43e65147 165
bab84c47
DC
166 case 'L':
167 {
168 int rel_addr = (((insn & 0xfff) ^ 0x800) - 0x800) * 2;
169 sprintf (buf, ".%+-8d", rel_addr);
246f4c05
SS
170 *sym = 1;
171 *sym_addr = pc + 2 + rel_addr;
c8941035 172 strcpy (comment, comment_start);
bab84c47
DC
173 }
174 break;
175
176 case 'l':
177 {
178 int rel_addr = ((((insn >> 3) & 0x7f) ^ 0x40) - 0x40) * 2;
af692060 179
bab84c47 180 sprintf (buf, ".%+-8d", rel_addr);
246f4c05
SS
181 *sym = 1;
182 *sym_addr = pc + 2 + rel_addr;
c8941035 183 strcpy (comment, comment_start);
bab84c47
DC
184 }
185 break;
186
187 case 'i':
1857fe72
DC
188 {
189 unsigned int val = insn2 | 0x800000;
190 *sym = 1;
191 *sym_addr = val;
192 sprintf (buf, "0x%04X", insn2);
193 strcpy (comment, comment_start);
194 }
bab84c47 195 break;
f36e8886
BS
196
197 case 'j':
198 {
199 unsigned int val = ((insn & 0xf) | ((insn & 0x600) >> 5)
200 | ((insn & 0x100) >> 2));
1d378749
NC
201 if ((insn & 0x100) == 0)
202 val |= 0x80;
1857fe72
DC
203 *sym = 1;
204 *sym_addr = val | 0x800000;
f36e8886 205 sprintf (buf, "0x%02x", val);
1857fe72 206 strcpy (comment, comment_start);
f36e8886
BS
207 }
208 break;
43e65147 209
bab84c47
DC
210 case 'M':
211 sprintf (buf, "0x%02X", ((insn & 0xf00) >> 4) | (insn & 0xf));
212 sprintf (comment, "%d", ((insn & 0xf00) >> 4) | (insn & 0xf));
213 break;
214
215 case 'n':
463f102c 216 sprintf (buf, "??");
a6743a54
AM
217 /* xgettext:c-format */
218 opcodes_error_handler (_("internal disassembler error"));
463f102c 219 ok = 0;
bab84c47 220 break;
43e65147 221
bab84c47 222 case 'K':
463f102c
DC
223 {
224 unsigned int x;
225
226 x = (insn & 0xf) | ((insn >> 2) & 0x30);
227 sprintf (buf, "0x%02x", x);
228 sprintf (comment, "%d", x);
229 }
bab84c47 230 break;
43e65147 231
bab84c47
DC
232 case 's':
233 sprintf (buf, "%d", insn & 7);
234 break;
43e65147 235
bab84c47
DC
236 case 'S':
237 sprintf (buf, "%d", (insn >> 4) & 7);
238 break;
43e65147 239
bab84c47
DC
240 case 'P':
241 {
242 unsigned int x;
47b0e7ad 243
bab84c47
DC
244 x = (insn & 0xf);
245 x |= (insn >> 5) & 0x30;
246 sprintf (buf, "0x%02x", x);
247 sprintf (comment, "%d", x);
248 }
249 break;
250
251 case 'p':
252 {
253 unsigned int x;
43e65147 254
bab84c47
DC
255 x = (insn >> 3) & 0x1f;
256 sprintf (buf, "0x%02x", x);
257 sprintf (comment, "%d", x);
258 }
259 break;
43e65147 260
8cc66334
EW
261 case 'E':
262 sprintf (buf, "%d", (insn >> 4) & 15);
263 break;
43e65147 264
bab84c47
DC
265 case '?':
266 *buf = '\0';
267 break;
43e65147 268
bab84c47 269 default:
463f102c 270 sprintf (buf, "??");
a6743a54
AM
271 /* xgettext:c-format */
272 opcodes_error_handler (_("unknown constraint `%c'"), constraint);
463f102c 273 ok = 0;
bab84c47 274 }
463f102c
DC
275
276 return ok;
adde6300
AM
277}
278
0a7e1018
YQ
279/* Read the opcode from ADDR. Return 0 in success and save opcode
280 in *INSN, otherwise, return -1. */
281
282static int
283avrdis_opcode (bfd_vma addr, disassemble_info *info, uint16_t *insn)
adde6300
AM
284{
285 bfd_byte buffer[2];
286 int status;
47b0e7ad
NC
287
288 status = info->read_memory_func (addr, buffer, 2, info);
289
290 if (status == 0)
0a7e1018
YQ
291 {
292 *insn = bfd_getl16 (buffer);
293 return 0;
294 }
47b0e7ad
NC
295
296 info->memory_error_func (status, addr, info);
297 return -1;
adde6300
AM
298}
299
300
301int
47b0e7ad 302print_insn_avr (bfd_vma addr, disassemble_info *info)
adde6300 303{
0a7e1018 304 uint16_t insn, insn2;
11041102
KD
305 const struct avr_opcodes_s *opcode;
306 static unsigned int *maskptr;
adde6300
AM
307 void *stream = info->stream;
308 fprintf_ftype prin = info->fprintf_func;
11041102 309 static unsigned int *avr_bin_masks;
bab84c47 310 static int initialized;
adde6300 311 int cmd_len = 2;
463f102c
DC
312 int ok = 0;
313 char op1[20], op2[20], comment1[40], comment2[40];
246f4c05
SS
314 int sym_op1 = 0, sym_op2 = 0;
315 bfd_vma sym_addr1, sym_addr2;
adde6300 316
af692060 317
bab84c47
DC
318 if (!initialized)
319 {
11041102
KD
320 unsigned int nopcodes;
321
af692060
NC
322 /* PR 4045: Try to avoid duplicating the 0x prefix that
323 objdump_print_addr() will put on addresses when there
324 is no symbol table available. */
325 if (info->symtab_size == 0)
326 comment_start = " ";
327
11041102 328 nopcodes = sizeof (avr_opcodes) / sizeof (struct avr_opcodes_s);
43e65147 329
47b0e7ad 330 avr_bin_masks = xmalloc (nopcodes * sizeof (unsigned int));
11041102
KD
331
332 for (opcode = avr_opcodes, maskptr = avr_bin_masks;
333 opcode->name;
334 opcode++, maskptr++)
bab84c47
DC
335 {
336 char * s;
337 unsigned int bin = 0;
338 unsigned int mask = 0;
43e65147 339
bab84c47
DC
340 for (s = opcode->opcode; *s; ++s)
341 {
342 bin <<= 1;
343 mask <<= 1;
344 bin |= (*s == '1');
345 mask |= (*s == '1' || *s == '0');
346 }
347 assert (s - opcode->opcode == 16);
348 assert (opcode->bin_opcode == bin);
11041102 349 *maskptr = mask;
bab84c47 350 }
11041102
KD
351
352 initialized = 1;
bab84c47 353 }
adde6300 354
0a7e1018
YQ
355 if (avrdis_opcode (addr, info, &insn) != 0)
356 return -1;
43e65147 357
11041102
KD
358 for (opcode = avr_opcodes, maskptr = avr_bin_masks;
359 opcode->name;
360 opcode++, maskptr++)
f36e8886
BS
361 {
362 if ((opcode->isa == AVR_ISA_TINY) && (info->mach != bfd_mach_avrtiny))
363 continue;
364 if ((insn & *maskptr) == opcode->bin_opcode)
365 break;
366 }
43e65147 367
463f102c
DC
368 /* Special case: disassemble `ldd r,b+0' as `ld r,b', and
369 `std b+0,r' as `st b,r' (next entry in the table). */
370
371 if (AVR_DISP0_P (insn))
372 opcode++;
373
374 op1[0] = 0;
375 op2[0] = 0;
376 comment1[0] = 0;
377 comment2[0] = 0;
378
bab84c47 379 if (opcode->name)
adde6300 380 {
8cc66334
EW
381 char *constraints = opcode->constraints;
382 char *opcode_str = opcode->opcode;
bab84c47 383
00d2865b 384 insn2 = 0;
463f102c 385 ok = 1;
bab84c47
DC
386
387 if (opcode->insn_size > 1)
388 {
0a7e1018
YQ
389 if (avrdis_opcode (addr + 2, info, &insn2) != 0)
390 return -1;
bab84c47
DC
391 cmd_len = 4;
392 }
393
8cc66334 394 if (*constraints && *constraints != '?')
bab84c47 395 {
8cc66334 396 int regs = REGISTER_P (*constraints);
bab84c47 397
8cc66334 398 ok = avr_operand (insn, insn2, addr, *constraints, opcode_str, op1, comment1, 0, &sym_op1, &sym_addr1);
bab84c47 399
8cc66334
EW
400 if (ok && *(++constraints) == ',')
401 ok = avr_operand (insn, insn2, addr, *(++constraints), opcode_str, op2,
246f4c05 402 *comment1 ? comment2 : comment1, regs, &sym_op2, &sym_addr2);
bab84c47 403 }
463f102c 404 }
bab84c47 405
463f102c
DC
406 if (!ok)
407 {
408 /* Unknown opcode, or invalid combination of operands. */
409 sprintf (op1, "0x%04x", insn);
410 op2[0] = 0;
411 sprintf (comment1, "????");
412 comment2[0] = 0;
413 }
bab84c47 414
463f102c 415 (*prin) (stream, "%s", ok ? opcode->name : ".word");
bab84c47 416
463f102c 417 if (*op1)
246f4c05 418 (*prin) (stream, "\t%s", op1);
bab84c47 419
463f102c
DC
420 if (*op2)
421 (*prin) (stream, ", %s", op2);
422
423 if (*comment1)
424 (*prin) (stream, "\t; %s", comment1);
425
246f4c05 426 if (sym_op1)
73f643e9 427 info->print_address_func (sym_addr1, info);
246f4c05 428
463f102c
DC
429 if (*comment2)
430 (*prin) (stream, " %s", comment2);
bab84c47 431
246f4c05 432 if (sym_op2)
73f643e9 433 info->print_address_func (sym_addr2, info);
246f4c05 434
adde6300
AM
435 return cmd_len;
436}
This page took 0.976476 seconds and 4 git commands to generate.