Sim - Use long int format instead of int to avoid compiling warning
[deliverable/binutils-gdb.git] / opcodes / avr-dis.c
CommitLineData
adde6300 1/* Disassemble AVR instructions.
4b95cf5c 2 Copyright (C) 1999-2014 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. */
bab84c47
DC
65
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;
75
76 case 'w':
77 sprintf (buf, "r%d", 24 + ((insn & 0x30) >> 3));
78 break;
79
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;
bab84c47
DC
141
142 x = (insn & 7);
143 x |= (insn >> 7) & (3 << 3);
144 x |= (insn >> 8) & (1 << 5);
145
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;
154
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. */
00988f49 161 sprintf (buf, "%#lx", (unsigned long) *sym_addr);
c8941035 162 strcpy (comment, comment_start);
bab84c47
DC
163 break;
164
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;
189
190 case 'M':
191 sprintf (buf, "0x%02X", ((insn & 0xf00) >> 4) | (insn & 0xf));
192 sprintf (comment, "%d", ((insn & 0xf00) >> 4) | (insn & 0xf));
193 break;
194
195 case 'n':
463f102c
DC
196 sprintf (buf, "??");
197 fprintf (stderr, _("Internal disassembler error"));
198 ok = 0;
bab84c47
DC
199 break;
200
201 case 'K':
463f102c
DC
202 {
203 unsigned int x;
204
205 x = (insn & 0xf) | ((insn >> 2) & 0x30);
206 sprintf (buf, "0x%02x", x);
207 sprintf (comment, "%d", x);
208 }
bab84c47
DC
209 break;
210
211 case 's':
212 sprintf (buf, "%d", insn & 7);
213 break;
214
215 case 'S':
216 sprintf (buf, "%d", (insn >> 4) & 7);
217 break;
218
219 case 'P':
220 {
221 unsigned int x;
47b0e7ad 222
bab84c47
DC
223 x = (insn & 0xf);
224 x |= (insn >> 5) & 0x30;
225 sprintf (buf, "0x%02x", x);
226 sprintf (comment, "%d", x);
227 }
228 break;
229
230 case 'p':
231 {
232 unsigned int x;
233
234 x = (insn >> 3) & 0x1f;
235 sprintf (buf, "0x%02x", x);
236 sprintf (comment, "%d", x);
237 }
238 break;
239
8cc66334
EW
240 case 'E':
241 sprintf (buf, "%d", (insn >> 4) & 15);
242 break;
243
bab84c47
DC
244 case '?':
245 *buf = '\0';
246 break;
247
248 default:
463f102c
DC
249 sprintf (buf, "??");
250 fprintf (stderr, _("unknown constraint `%c'"), constraint);
251 ok = 0;
bab84c47 252 }
463f102c
DC
253
254 return ok;
adde6300
AM
255}
256
bab84c47 257static unsigned short
47b0e7ad 258avrdis_opcode (bfd_vma addr, disassemble_info *info)
adde6300
AM
259{
260 bfd_byte buffer[2];
261 int status;
47b0e7ad
NC
262
263 status = info->read_memory_func (addr, buffer, 2, info);
264
265 if (status == 0)
266 return bfd_getl16 (buffer);
267
268 info->memory_error_func (status, addr, info);
269 return -1;
adde6300
AM
270}
271
272
273int
47b0e7ad 274print_insn_avr (bfd_vma addr, disassemble_info *info)
adde6300 275{
bab84c47 276 unsigned int insn, insn2;
11041102
KD
277 const struct avr_opcodes_s *opcode;
278 static unsigned int *maskptr;
adde6300
AM
279 void *stream = info->stream;
280 fprintf_ftype prin = info->fprintf_func;
11041102 281 static unsigned int *avr_bin_masks;
bab84c47 282 static int initialized;
adde6300 283 int cmd_len = 2;
463f102c
DC
284 int ok = 0;
285 char op1[20], op2[20], comment1[40], comment2[40];
246f4c05
SS
286 int sym_op1 = 0, sym_op2 = 0;
287 bfd_vma sym_addr1, sym_addr2;
adde6300 288
af692060 289
bab84c47
DC
290 if (!initialized)
291 {
11041102
KD
292 unsigned int nopcodes;
293
af692060
NC
294 /* PR 4045: Try to avoid duplicating the 0x prefix that
295 objdump_print_addr() will put on addresses when there
296 is no symbol table available. */
297 if (info->symtab_size == 0)
298 comment_start = " ";
299
11041102 300 nopcodes = sizeof (avr_opcodes) / sizeof (struct avr_opcodes_s);
bab84c47 301
47b0e7ad 302 avr_bin_masks = xmalloc (nopcodes * sizeof (unsigned int));
11041102
KD
303
304 for (opcode = avr_opcodes, maskptr = avr_bin_masks;
305 opcode->name;
306 opcode++, maskptr++)
bab84c47
DC
307 {
308 char * s;
309 unsigned int bin = 0;
310 unsigned int mask = 0;
311
312 for (s = opcode->opcode; *s; ++s)
313 {
314 bin <<= 1;
315 mask <<= 1;
316 bin |= (*s == '1');
317 mask |= (*s == '1' || *s == '0');
318 }
319 assert (s - opcode->opcode == 16);
320 assert (opcode->bin_opcode == bin);
11041102 321 *maskptr = mask;
bab84c47 322 }
11041102
KD
323
324 initialized = 1;
bab84c47 325 }
adde6300 326
bab84c47
DC
327 insn = avrdis_opcode (addr, info);
328
11041102
KD
329 for (opcode = avr_opcodes, maskptr = avr_bin_masks;
330 opcode->name;
331 opcode++, maskptr++)
47b0e7ad
NC
332 if ((insn & *maskptr) == opcode->bin_opcode)
333 break;
bab84c47 334
463f102c
DC
335 /* Special case: disassemble `ldd r,b+0' as `ld r,b', and
336 `std b+0,r' as `st b,r' (next entry in the table). */
337
338 if (AVR_DISP0_P (insn))
339 opcode++;
340
341 op1[0] = 0;
342 op2[0] = 0;
343 comment1[0] = 0;
344 comment2[0] = 0;
345
bab84c47 346 if (opcode->name)
adde6300 347 {
8cc66334
EW
348 char *constraints = opcode->constraints;
349 char *opcode_str = opcode->opcode;
bab84c47 350
00d2865b 351 insn2 = 0;
463f102c 352 ok = 1;
bab84c47
DC
353
354 if (opcode->insn_size > 1)
355 {
356 insn2 = avrdis_opcode (addr + 2, info);
357 cmd_len = 4;
358 }
359
8cc66334 360 if (*constraints && *constraints != '?')
bab84c47 361 {
8cc66334 362 int regs = REGISTER_P (*constraints);
bab84c47 363
8cc66334 364 ok = avr_operand (insn, insn2, addr, *constraints, opcode_str, op1, comment1, 0, &sym_op1, &sym_addr1);
bab84c47 365
8cc66334
EW
366 if (ok && *(++constraints) == ',')
367 ok = avr_operand (insn, insn2, addr, *(++constraints), opcode_str, op2,
246f4c05 368 *comment1 ? comment2 : comment1, regs, &sym_op2, &sym_addr2);
bab84c47 369 }
463f102c 370 }
bab84c47 371
463f102c
DC
372 if (!ok)
373 {
374 /* Unknown opcode, or invalid combination of operands. */
375 sprintf (op1, "0x%04x", insn);
376 op2[0] = 0;
377 sprintf (comment1, "????");
378 comment2[0] = 0;
379 }
bab84c47 380
463f102c 381 (*prin) (stream, "%s", ok ? opcode->name : ".word");
bab84c47 382
463f102c 383 if (*op1)
246f4c05 384 (*prin) (stream, "\t%s", op1);
bab84c47 385
463f102c
DC
386 if (*op2)
387 (*prin) (stream, ", %s", op2);
388
389 if (*comment1)
390 (*prin) (stream, "\t; %s", comment1);
391
246f4c05 392 if (sym_op1)
73f643e9 393 info->print_address_func (sym_addr1, info);
246f4c05 394
463f102c
DC
395 if (*comment2)
396 (*prin) (stream, " %s", comment2);
bab84c47 397
246f4c05 398 if (sym_op2)
73f643e9 399 info->print_address_func (sym_addr2, info);
246f4c05 400
adde6300
AM
401 return cmd_len;
402}
This page took 0.628089 seconds and 4 git commands to generate.