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