]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - opcodes/avr-dis.c
Use disassemble.c:disassembler select rs6000 disassembler
[thirdparty/binutils-gdb.git] / opcodes / avr-dis.c
CommitLineData
adde6300 1/* Disassemble AVR instructions.
2571583a 2 Copyright (C) 1999-2017 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>
adde6300
AM
25#include "dis-asm.h"
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));
1857fe72
DC
201 *sym = 1;
202 *sym_addr = val | 0x800000;
f36e8886 203 sprintf (buf, "0x%02x", val);
1857fe72 204 strcpy (comment, comment_start);
f36e8886
BS
205 }
206 break;
43e65147 207
bab84c47
DC
208 case 'M':
209 sprintf (buf, "0x%02X", ((insn & 0xf00) >> 4) | (insn & 0xf));
210 sprintf (comment, "%d", ((insn & 0xf00) >> 4) | (insn & 0xf));
211 break;
212
213 case 'n':
463f102c
DC
214 sprintf (buf, "??");
215 fprintf (stderr, _("Internal disassembler error"));
216 ok = 0;
bab84c47 217 break;
43e65147 218
bab84c47 219 case 'K':
463f102c
DC
220 {
221 unsigned int x;
222
223 x = (insn & 0xf) | ((insn >> 2) & 0x30);
224 sprintf (buf, "0x%02x", x);
225 sprintf (comment, "%d", x);
226 }
bab84c47 227 break;
43e65147 228
bab84c47
DC
229 case 's':
230 sprintf (buf, "%d", insn & 7);
231 break;
43e65147 232
bab84c47
DC
233 case 'S':
234 sprintf (buf, "%d", (insn >> 4) & 7);
235 break;
43e65147 236
bab84c47
DC
237 case 'P':
238 {
239 unsigned int x;
47b0e7ad 240
bab84c47
DC
241 x = (insn & 0xf);
242 x |= (insn >> 5) & 0x30;
243 sprintf (buf, "0x%02x", x);
244 sprintf (comment, "%d", x);
245 }
246 break;
247
248 case 'p':
249 {
250 unsigned int x;
43e65147 251
bab84c47
DC
252 x = (insn >> 3) & 0x1f;
253 sprintf (buf, "0x%02x", x);
254 sprintf (comment, "%d", x);
255 }
256 break;
43e65147 257
8cc66334
EW
258 case 'E':
259 sprintf (buf, "%d", (insn >> 4) & 15);
260 break;
43e65147 261
bab84c47
DC
262 case '?':
263 *buf = '\0';
264 break;
43e65147 265
bab84c47 266 default:
463f102c
DC
267 sprintf (buf, "??");
268 fprintf (stderr, _("unknown constraint `%c'"), constraint);
269 ok = 0;
bab84c47 270 }
463f102c
DC
271
272 return ok;
adde6300
AM
273}
274
0a7e1018
YQ
275/* Read the opcode from ADDR. Return 0 in success and save opcode
276 in *INSN, otherwise, return -1. */
277
278static int
279avrdis_opcode (bfd_vma addr, disassemble_info *info, uint16_t *insn)
adde6300
AM
280{
281 bfd_byte buffer[2];
282 int status;
47b0e7ad
NC
283
284 status = info->read_memory_func (addr, buffer, 2, info);
285
286 if (status == 0)
0a7e1018
YQ
287 {
288 *insn = bfd_getl16 (buffer);
289 return 0;
290 }
47b0e7ad
NC
291
292 info->memory_error_func (status, addr, info);
293 return -1;
adde6300
AM
294}
295
296
297int
47b0e7ad 298print_insn_avr (bfd_vma addr, disassemble_info *info)
adde6300 299{
0a7e1018 300 uint16_t insn, insn2;
11041102
KD
301 const struct avr_opcodes_s *opcode;
302 static unsigned int *maskptr;
adde6300
AM
303 void *stream = info->stream;
304 fprintf_ftype prin = info->fprintf_func;
11041102 305 static unsigned int *avr_bin_masks;
bab84c47 306 static int initialized;
adde6300 307 int cmd_len = 2;
463f102c
DC
308 int ok = 0;
309 char op1[20], op2[20], comment1[40], comment2[40];
246f4c05
SS
310 int sym_op1 = 0, sym_op2 = 0;
311 bfd_vma sym_addr1, sym_addr2;
adde6300 312
af692060 313
bab84c47
DC
314 if (!initialized)
315 {
11041102
KD
316 unsigned int nopcodes;
317
af692060
NC
318 /* PR 4045: Try to avoid duplicating the 0x prefix that
319 objdump_print_addr() will put on addresses when there
320 is no symbol table available. */
321 if (info->symtab_size == 0)
322 comment_start = " ";
323
11041102 324 nopcodes = sizeof (avr_opcodes) / sizeof (struct avr_opcodes_s);
43e65147 325
47b0e7ad 326 avr_bin_masks = xmalloc (nopcodes * sizeof (unsigned int));
11041102
KD
327
328 for (opcode = avr_opcodes, maskptr = avr_bin_masks;
329 opcode->name;
330 opcode++, maskptr++)
bab84c47
DC
331 {
332 char * s;
333 unsigned int bin = 0;
334 unsigned int mask = 0;
43e65147 335
bab84c47
DC
336 for (s = opcode->opcode; *s; ++s)
337 {
338 bin <<= 1;
339 mask <<= 1;
340 bin |= (*s == '1');
341 mask |= (*s == '1' || *s == '0');
342 }
343 assert (s - opcode->opcode == 16);
344 assert (opcode->bin_opcode == bin);
11041102 345 *maskptr = mask;
bab84c47 346 }
11041102
KD
347
348 initialized = 1;
bab84c47 349 }
adde6300 350
0a7e1018
YQ
351 if (avrdis_opcode (addr, info, &insn) != 0)
352 return -1;
43e65147 353
11041102
KD
354 for (opcode = avr_opcodes, maskptr = avr_bin_masks;
355 opcode->name;
356 opcode++, maskptr++)
f36e8886
BS
357 {
358 if ((opcode->isa == AVR_ISA_TINY) && (info->mach != bfd_mach_avrtiny))
359 continue;
360 if ((insn & *maskptr) == opcode->bin_opcode)
361 break;
362 }
43e65147 363
463f102c
DC
364 /* Special case: disassemble `ldd r,b+0' as `ld r,b', and
365 `std b+0,r' as `st b,r' (next entry in the table). */
366
367 if (AVR_DISP0_P (insn))
368 opcode++;
369
370 op1[0] = 0;
371 op2[0] = 0;
372 comment1[0] = 0;
373 comment2[0] = 0;
374
bab84c47 375 if (opcode->name)
adde6300 376 {
8cc66334
EW
377 char *constraints = opcode->constraints;
378 char *opcode_str = opcode->opcode;
bab84c47 379
00d2865b 380 insn2 = 0;
463f102c 381 ok = 1;
bab84c47
DC
382
383 if (opcode->insn_size > 1)
384 {
0a7e1018
YQ
385 if (avrdis_opcode (addr + 2, info, &insn2) != 0)
386 return -1;
bab84c47
DC
387 cmd_len = 4;
388 }
389
8cc66334 390 if (*constraints && *constraints != '?')
bab84c47 391 {
8cc66334 392 int regs = REGISTER_P (*constraints);
bab84c47 393
8cc66334 394 ok = avr_operand (insn, insn2, addr, *constraints, opcode_str, op1, comment1, 0, &sym_op1, &sym_addr1);
bab84c47 395
8cc66334
EW
396 if (ok && *(++constraints) == ',')
397 ok = avr_operand (insn, insn2, addr, *(++constraints), opcode_str, op2,
246f4c05 398 *comment1 ? comment2 : comment1, regs, &sym_op2, &sym_addr2);
bab84c47 399 }
463f102c 400 }
bab84c47 401
463f102c
DC
402 if (!ok)
403 {
404 /* Unknown opcode, or invalid combination of operands. */
405 sprintf (op1, "0x%04x", insn);
406 op2[0] = 0;
407 sprintf (comment1, "????");
408 comment2[0] = 0;
409 }
bab84c47 410
463f102c 411 (*prin) (stream, "%s", ok ? opcode->name : ".word");
bab84c47 412
463f102c 413 if (*op1)
246f4c05 414 (*prin) (stream, "\t%s", op1);
bab84c47 415
463f102c
DC
416 if (*op2)
417 (*prin) (stream, ", %s", op2);
418
419 if (*comment1)
420 (*prin) (stream, "\t; %s", comment1);
421
246f4c05 422 if (sym_op1)
73f643e9 423 info->print_address_func (sym_addr1, info);
246f4c05 424
463f102c
DC
425 if (*comment2)
426 (*prin) (stream, " %s", comment2);
bab84c47 427
246f4c05 428 if (sym_op2)
73f643e9 429 info->print_address_func (sym_addr2, info);
246f4c05 430
adde6300
AM
431 return cmd_len;
432}