Remove unneeded AUX register symbols.
[deliverable/binutils-gdb.git] / opcodes / arc-dis.c
CommitLineData
252b5132 1/* Instruction printing code for the ARC.
6f2750fe 2 Copyright (C) 1994-2016 Free Software Foundation, Inc.
886a2506
NC
3
4 Contributed by Claudiu Zissulescu (claziss@synopsys.com)
252b5132 5
9b201bb5
NC
6 This file is part of libopcodes.
7
8 This library is free software; you can redistribute it and/or modify
0d2bcfaf 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.
252b5132 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.
252b5132 17
0d2bcfaf
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
47b0e7ad
NC
20 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21 MA 02110-1301, USA. */
252b5132 22
5eb3690e 23#include "sysdep.h"
886a2506
NC
24#include <stdio.h>
25#include <assert.h>
252b5132
RH
26#include "dis-asm.h"
27#include "opcode/arc.h"
0d2bcfaf
NC
28#include "arc-dis.h"
29#include "arc-ext.h"
252b5132 30
252b5132 31
886a2506 32/* Globals variables. */
82b829a7 33
886a2506 34static const char * const regnames[64] =
47b0e7ad 35{
886a2506
NC
36 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
37 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
38 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
39 "r24", "r25", "gp", "fp", "sp", "ilink", "r30", "blink",
40
41 "r32", "r33", "r34", "r35", "r36", "r37", "r38", "r39",
42 "r40", "r41", "r42", "r43", "r44", "r45", "r46", "r47",
43 "r48", "r49", "r50", "r51", "r52", "r53", "r54", "r55",
44 "r56", "r57", "ACCL", "ACCH", "lp_count", "rezerved", "LIMM", "pcl"
45};
46
47/* Macros section. */
48
49#ifdef DEBUG
50# define pr_debug(fmt, args...) fprintf (stderr, fmt, ##args)
51#else
52# define pr_debug(fmt, args...)
53#endif
54
55#define ARRANGE_ENDIAN(info, buf) \
56 (info->endian == BFD_ENDIAN_LITTLE ? bfd_getm32 (bfd_getl32 (buf)) \
57 : bfd_getb32 (buf))
58
59#define BITS(word,s,e) (((word) << (sizeof (word) * 8 - 1 - e)) >> \
60 (s + (sizeof (word) * 8 - 1 - e)))
279a96ca 61#define OPCODE(word) (BITS ((word), 27, 31))
252b5132 62
886a2506 63#define OPCODE_AC(word) (BITS ((word), 11, 15))
252b5132 64
886a2506 65/* Functions implementation. */
252b5132 66
886a2506
NC
67static bfd_vma
68bfd_getm32 (unsigned int data)
0d2bcfaf 69{
886a2506 70 bfd_vma value = 0;
0d2bcfaf 71
886a2506
NC
72 value = ((data & 0xff00) | (data & 0xff)) << 16;
73 value |= ((data & 0xff0000) | (data & 0xff000000)) >> 16;
74 return value;
0d2bcfaf
NC
75}
76
886a2506
NC
77static int
78special_flag_p (const char *opname,
79 const char *flgname)
0d2bcfaf 80{
886a2506 81 const struct arc_flag_special *flg_spec;
886a2506 82 unsigned i, j, flgidx;
0d2bcfaf 83
886a2506 84 for (i = 0; i < arc_num_flag_special; i++)
252b5132 85 {
886a2506 86 flg_spec = &arc_flag_special_cases[i];
279a96ca 87
24b368f8 88 if (strcmp (opname, flg_spec->name))
886a2506 89 continue;
279a96ca 90
886a2506
NC
91 /* Found potential special case instruction. */
92 for (j=0;; ++j)
0d2bcfaf 93 {
886a2506
NC
94 flgidx = flg_spec->flags[j];
95 if (flgidx == 0)
96 break; /* End of the array. */
0d2bcfaf 97
886a2506
NC
98 if (strcmp (flgname, arc_flag_operands[flgidx].name) == 0)
99 return 1;
252b5132 100 }
0d2bcfaf 101 }
886a2506 102 return 0;
0d2bcfaf 103}
252b5132 104
886a2506 105/* Disassemble ARC instructions. */
0d2bcfaf 106
886a2506
NC
107static int
108print_insn_arc (bfd_vma memaddr,
109 struct disassemble_info *info)
0d2bcfaf 110{
886a2506
NC
111 bfd_byte buffer[4];
112 unsigned int lowbyte, highbyte;
113 int status;
114 unsigned int i;
115 int insnLen = 0;
3f94e60d
NC
116 unsigned insn[2] = { 0, 0 };
117 unsigned isa_mask;
886a2506
NC
118 const unsigned char *opidx;
119 const unsigned char *flgidx;
120 const struct arc_opcode *opcode;
121 const char *instrName;
122 int flags;
123 bfd_boolean need_comma;
124 bfd_boolean open_braket;
24b368f8 125 int size;
0d2bcfaf 126
886a2506
NC
127 lowbyte = ((info->endian == BFD_ENDIAN_LITTLE) ? 1 : 0);
128 highbyte = ((info->endian == BFD_ENDIAN_LITTLE) ? 0 : 1);
0d2bcfaf 129
886a2506
NC
130 switch (info->mach)
131 {
8699fc3e
AB
132 case bfd_mach_arc_nps400:
133 isa_mask = ARC_OPCODE_ARC700 | ARC_OPCODE_NPS400;
134 break;
135
886a2506
NC
136 case bfd_mach_arc_arc700:
137 isa_mask = ARC_OPCODE_ARC700;
138 break;
0d2bcfaf 139
886a2506
NC
140 case bfd_mach_arc_arc600:
141 isa_mask = ARC_OPCODE_ARC600;
142 break;
0d2bcfaf 143
886a2506
NC
144 case bfd_mach_arc_arcv2:
145 default:
146 isa_mask = ARC_OPCODE_ARCv2HS | ARC_OPCODE_ARCv2EM;
147 break;
0d2bcfaf
NC
148 }
149
24b368f8
CZ
150 /* This variable may be set by the instruction decoder. It suggests
151 the number of bytes objdump should display on a single line. If
152 the instruction decoder sets this, it should always set it to
153 the same value in order to get reasonable looking output. */
154
155 info->bytes_per_line = 8;
156
157 /* In the next lines, we set two info variables control the way
158 objdump displays the raw data. For example, if bytes_per_line is
159 8 and bytes_per_chunk is 4, the output will look like this:
160 00: 00000000 00000000
161 with the chunks displayed according to "display_endian". */
162
163 if (info->section
164 && !(info->section->flags & SEC_CODE))
165 {
166 /* This is not a CODE section. */
167 switch (info->section->size)
168 {
169 case 1:
170 case 2:
171 case 4:
172 size = info->section->size;
173 break;
174 default:
175 size = (info->section->size & 0x01) ? 1 : 4;
176 break;
177 }
178 info->bytes_per_chunk = 1;
179 info->display_endian = info->endian;
180 }
181 else
182 {
183 size = 2;
184 info->bytes_per_chunk = 2;
185 info->display_endian = info->endian;
186 }
187
886a2506 188 /* Read the insn into a host word. */
24b368f8 189 status = (*info->read_memory_func) (memaddr, buffer, size, info);
886a2506 190 if (status != 0)
0d2bcfaf 191 {
886a2506
NC
192 (*info->memory_error_func) (status, memaddr, info);
193 return -1;
0d2bcfaf
NC
194 }
195
886a2506
NC
196 if (info->section
197 && !(info->section->flags & SEC_CODE))
0d2bcfaf 198 {
24b368f8
CZ
199 /* Data section. */
200 unsigned long data;
201
202 data = bfd_get_bits (buffer, size * 8,
203 info->display_endian == BFD_ENDIAN_BIG);
204 switch (size)
0d2bcfaf 205 {
24b368f8
CZ
206 case 1:
207 (*info->fprintf_func) (info->stream, ".byte\t0x%02lx", data);
208 break;
209 case 2:
210 (*info->fprintf_func) (info->stream, ".short\t0x%04lx", data);
211 break;
212 case 4:
213 (*info->fprintf_func) (info->stream, ".word\t0x%08lx", data);
214 break;
215 default:
216 abort ();
0d2bcfaf 217 }
24b368f8 218 return size;
886a2506 219 }
279a96ca 220
24b368f8 221 if ( (((buffer[lowbyte] & 0xf8) > 0x38)
886a2506
NC
222 && ((buffer[lowbyte] & 0xf8) != 0x48))
223 || ((info->mach == bfd_mach_arc_arcv2)
224 && ((buffer[lowbyte] & 0xF8) == 0x48)) /* FIXME! ugly. */
225 )
226 {
227 /* This is a short instruction. */
228 insnLen = 2;
229 insn[0] = (buffer[lowbyte] << 8) | buffer[highbyte];
230 }
231 else
232 {
233 insnLen = 4;
234
235 /* This is a long instruction: Read the remaning 2 bytes. */
236 status = (*info->read_memory_func) (memaddr + 2, &buffer[2], 2, info);
237 if (status != 0)
0d2bcfaf 238 {
886a2506
NC
239 (*info->memory_error_func) (status, memaddr + 2, info);
240 return -1;
0d2bcfaf 241 }
886a2506
NC
242 insn[0] = ARRANGE_ENDIAN (info, buffer);
243 }
244
886a2506
NC
245 /* Set some defaults for the insn info. */
246 info->insn_info_valid = 1;
247 info->branch_delay_insns = 0;
248 info->data_size = 0;
249 info->insn_type = dis_nonbranch;
250 info->target = 0;
251 info->target2 = 0;
252
253 /* FIXME to be moved in dissasemble_init_for_target. */
254 info->disassembler_needs_relocs = TRUE;
255
256 /* Find the first match in the opcode table. */
257 for (i = 0; i < arc_num_opcodes; i++)
258 {
259 bfd_boolean invalid = FALSE;
260
261 opcode = &arc_opcodes[i];
279a96ca 262
886a2506 263 if (ARC_SHORT (opcode->mask) && (insnLen == 2))
0d2bcfaf 264 {
886a2506
NC
265 if (OPCODE_AC (opcode->opcode) != OPCODE_AC (insn[0]))
266 continue;
0d2bcfaf 267 }
886a2506 268 else if (!ARC_SHORT (opcode->mask) && (insnLen == 4))
0d2bcfaf 269 {
886a2506
NC
270 if (OPCODE (opcode->opcode) != OPCODE (insn[0]))
271 continue;
0d2bcfaf 272 }
886a2506
NC
273 else
274 continue;
275
276 if ((insn[0] ^ opcode->opcode) & opcode->mask)
277 continue;
279a96ca 278
886a2506
NC
279 if (!(opcode->cpu & isa_mask))
280 continue;
281
282 /* Possible candidate, check the operands. */
283 for (opidx = opcode->operands; *opidx; opidx++)
0d2bcfaf 284 {
886a2506
NC
285 int value;
286 const struct arc_operand *operand = &arc_operands[*opidx];
287
288 if (operand->flags & ARC_OPERAND_FAKE)
289 continue;
290
291 if (operand->extract)
292 value = (*operand->extract) (insn[0], &invalid);
293 else
294 value = (insn[0] >> operand->shift) & ((1 << operand->bits) - 1);
295
296 /* Check for LIMM indicator. If it is there, then make sure
297 we pick the right format. */
298 if (operand->flags & ARC_OPERAND_IR
299 && !(operand->flags & ARC_OPERAND_LIMM))
252b5132 300 {
886a2506
NC
301 if ((value == 0x3E && insnLen == 4)
302 || (value == 0x1E && insnLen == 2))
303 {
304 invalid = TRUE;
305 break;
306 }
252b5132 307 }
0d2bcfaf 308 }
252b5132 309
886a2506
NC
310 /* Check the flags. */
311 for (flgidx = opcode->flags; *flgidx; flgidx++)
0d2bcfaf 312 {
886a2506
NC
313 /* Get a valid flag class. */
314 const struct arc_flag_class *cl_flags = &arc_flag_classes[*flgidx];
315 const unsigned *flgopridx;
316 int foundA = 0, foundB = 0;
317
318 for (flgopridx = cl_flags->flags; *flgopridx; ++flgopridx)
252b5132 319 {
886a2506
NC
320 const struct arc_flag_operand *flg_operand = &arc_flag_operands[*flgopridx];
321 unsigned int value;
322
323 value = (insn[0] >> flg_operand->shift) & ((1 << flg_operand->bits) - 1);
324 if (value == flg_operand->code)
325 foundA = 1;
326 if (value)
327 foundB = 1;
252b5132 328 }
886a2506 329 if (!foundA && foundB)
252b5132 330 {
886a2506
NC
331 invalid = TRUE;
332 break;
252b5132 333 }
0d2bcfaf 334 }
279a96ca 335
886a2506
NC
336 if (invalid)
337 continue;
252b5132 338
886a2506
NC
339 /* The instruction is valid. */
340 goto found;
341 }
279a96ca 342
886a2506
NC
343 /* No instruction found. Try the extenssions. */
344 instrName = arcExtMap_instName (OPCODE (insn[0]), insn[0], &flags);
345 if (instrName)
346 {
347 opcode = &arc_opcodes[0];
348 (*info->fprintf_func) (info->stream, "%s", instrName);
349 goto print_flags;
350 }
252b5132 351
886a2506
NC
352 if (insnLen == 2)
353 (*info->fprintf_func) (info->stream, ".long %#04x", insn[0]);
354 else
355 (*info->fprintf_func) (info->stream, ".long %#08x", insn[0]);
356
357 info->insn_type = dis_noninsn;
358 return insnLen;
359
360 found:
361 /* Print the mnemonic. */
362 (*info->fprintf_func) (info->stream, "%s", opcode->name);
363
364 /* Preselect the insn class. */
365 switch (opcode->class)
366 {
367 case BRANCH:
368 case JUMP:
369 if (!strncmp (opcode->name, "bl", 2)
370 || !strncmp (opcode->name, "jl", 2))
371 info->insn_type = dis_jsr;
279a96ca 372 else
886a2506
NC
373 info->insn_type = dis_branch;
374 break;
375 case MEMORY:
376 info->insn_type = dis_dref; /* FIXME! DB indicates mov as memory! */
0d2bcfaf 377 break;
0d2bcfaf 378 default:
886a2506 379 info->insn_type = dis_nonbranch;
0d2bcfaf
NC
380 break;
381 }
279a96ca 382
886a2506 383 pr_debug ("%s: 0x%08x\n", opcode->name, opcode->opcode);
279a96ca 384
886a2506
NC
385 print_flags:
386 /* Now extract and print the flags. */
387 for (flgidx = opcode->flags; *flgidx; flgidx++)
0d2bcfaf 388 {
886a2506
NC
389 /* Get a valid flag class. */
390 const struct arc_flag_class *cl_flags = &arc_flag_classes[*flgidx];
391 const unsigned *flgopridx;
279a96ca 392
886a2506 393 for (flgopridx = cl_flags->flags; *flgopridx; ++flgopridx)
0d2bcfaf 394 {
886a2506
NC
395 const struct arc_flag_operand *flg_operand = &arc_flag_operands[*flgopridx];
396 unsigned int value;
279a96ca 397
886a2506
NC
398 if (!flg_operand->favail)
399 continue;
279a96ca 400
886a2506
NC
401 value = (insn[0] >> flg_operand->shift) & ((1 << flg_operand->bits) - 1);
402 if (value == flg_operand->code)
403 {
404 /* FIXME!: print correctly nt/t flag. */
405 if (!special_flag_p (opcode->name, flg_operand->name))
406 (*info->fprintf_func) (info->stream, ".");
407 else if (info->insn_type == dis_dref)
408 {
409 switch (flg_operand->name[0])
410 {
411 case 'b':
412 info->data_size = 1;
413 break;
414 case 'h':
415 case 'w':
416 info->data_size = 2;
417 break;
418 default:
419 info->data_size = 4;
420 break;
421 }
422 }
423 (*info->fprintf_func) (info->stream, "%s", flg_operand->name);
424 }
279a96ca 425
886a2506
NC
426 if (flg_operand->name[0] == 'd'
427 && flg_operand->name[1] == 0)
428 info->branch_delay_insns = 1;
279a96ca 429 }
886a2506 430 }
279a96ca 431
886a2506
NC
432 if (opcode->operands[0] != 0)
433 (*info->fprintf_func) (info->stream, "\t");
279a96ca 434
886a2506
NC
435 need_comma = FALSE;
436 open_braket = FALSE;
279a96ca 437
886a2506
NC
438 /* Now extract and print the operands. */
439 for (opidx = opcode->operands; *opidx; opidx++)
440 {
441 const struct arc_operand *operand = &arc_operands[*opidx];
442 int value;
279a96ca 443
886a2506 444 if (open_braket && (operand->flags & ARC_OPERAND_BRAKET))
0d2bcfaf 445 {
886a2506
NC
446 (*info->fprintf_func) (info->stream, "]");
447 open_braket = FALSE;
448 continue;
0d2bcfaf 449 }
279a96ca 450
886a2506
NC
451 /* Only take input from real operands. */
452 if ((operand->flags & ARC_OPERAND_FAKE)
453 && !(operand->flags & ARC_OPERAND_BRAKET))
454 continue;
279a96ca 455
886a2506
NC
456 if (operand->extract)
457 value = (*operand->extract) (insn[0], (int *) NULL);
0d2bcfaf 458 else
0d2bcfaf 459 {
886a2506 460 if (operand->flags & ARC_OPERAND_ALIGNED32)
0d2bcfaf 461 {
886a2506
NC
462 value = (insn[0] >> operand->shift)
463 & ((1 << (operand->bits - 2)) - 1);
464 value = value << 2;
252b5132 465 }
252b5132 466 else
886a2506
NC
467 {
468 value = (insn[0] >> operand->shift) & ((1 << operand->bits) - 1);
469 }
470 if (operand->flags & ARC_OPERAND_SIGNED)
471 {
472 int signbit = 1 << (operand->bits - 1);
473 value = (value ^ signbit) - signbit;
474 }
252b5132 475 }
279a96ca 476
886a2506
NC
477 if (operand->flags & ARC_OPERAND_IGNORE
478 && (operand->flags & ARC_OPERAND_IR
479 && value == -1))
480 continue;
279a96ca 481
886a2506
NC
482 if (need_comma)
483 (*info->fprintf_func) (info->stream, ",");
279a96ca 484
886a2506 485 if (!open_braket && (operand->flags & ARC_OPERAND_BRAKET))
0d2bcfaf 486 {
886a2506
NC
487 (*info->fprintf_func) (info->stream, "[");
488 open_braket = TRUE;
489 need_comma = FALSE;
490 continue;
0d2bcfaf 491 }
886a2506
NC
492
493 /* Read the limm operand, if required. */
494 if (operand->flags & ARC_OPERAND_LIMM
495 && !(operand->flags & ARC_OPERAND_DUPLICATE))
0d2bcfaf 496 {
886a2506
NC
497 status = (*info->read_memory_func) (memaddr + insnLen, buffer,
498 4, info);
499 if (status != 0)
0d2bcfaf 500 {
886a2506
NC
501 (*info->memory_error_func) (status, memaddr + insnLen, info);
502 return -1;
0d2bcfaf 503 }
886a2506 504 insn[1] = ARRANGE_ENDIAN (info, buffer);
0d2bcfaf 505 }
279a96ca 506
886a2506
NC
507 /* Print the operand as directed by the flags. */
508 if (operand->flags & ARC_OPERAND_IR)
509 {
510 assert (value >=0 && value < 64);
511 (*info->fprintf_func) (info->stream, "%s", regnames[value]);
512 if (operand->flags & ARC_OPERAND_TRUNCATE)
513 (*info->fprintf_func) (info->stream, "%s", regnames[value+1]);
514 }
515 else if (operand->flags & ARC_OPERAND_LIMM)
516 {
517 (*info->fprintf_func) (info->stream, "%#x", insn[1]);
518 if (info->insn_type == dis_branch
519 || info->insn_type == dis_jsr)
520 info->target = (bfd_vma) insn[1];
521 }
522 else if (operand->flags & ARC_OPERAND_PCREL)
523 {
524 /* PCL relative. */
525 if (info->flags & INSN_HAS_RELOC)
526 memaddr = 0;
527 (*info->print_address_func) ((memaddr & ~3) + value, info);
279a96ca 528
886a2506
NC
529 info->target = (bfd_vma) (memaddr & ~3) + value;
530 }
531 else if (operand->flags & ARC_OPERAND_SIGNED)
532 (*info->fprintf_func) (info->stream, "%d", value);
533 else
534 if (operand->flags & ARC_OPERAND_TRUNCATE
535 && !(operand->flags & ARC_OPERAND_ALIGNED32)
536 && !(operand->flags & ARC_OPERAND_ALIGNED16)
537 && value > 0 && value <= 14)
538 (*info->fprintf_func) (info->stream, "r13-%s",
539 regnames[13 + value - 1]);
540 else
541 (*info->fprintf_func) (info->stream, "%#x", value);
542
543 need_comma = TRUE;
544
545 /* Adjust insn len. */
546 if (operand->flags & ARC_OPERAND_LIMM
547 && !(operand->flags & ARC_OPERAND_DUPLICATE))
548 insnLen += 4;
252b5132 549 }
279a96ca 550
886a2506 551 return insnLen;
252b5132
RH
552}
553
47b0e7ad 554
886a2506
NC
555disassembler_ftype
556arc_get_disassembler (bfd *abfd)
252b5132 557{
886a2506
NC
558 /* Read the extenssion insns and registers, if any. */
559 build_ARC_extmap (abfd);
560 dump_ARC_extmap ();
252b5132 561
886a2506 562 return print_insn_arc;
252b5132
RH
563}
564
886a2506 565/* Disassemble ARC instructions. Used by debugger. */
47b0e7ad 566
886a2506
NC
567struct arcDisState
568arcAnalyzeInstr (bfd_vma memaddr,
569 struct disassemble_info *info)
0d2bcfaf 570{
886a2506
NC
571 struct arcDisState ret;
572 memset (&ret, 0, sizeof (struct arcDisState));
573
574 ret.instructionLen = print_insn_arc (memaddr, info);
575
576#if 0
577 ret.words[0] = insn[0];
578 ret.words[1] = insn[1];
579 ret._this = &ret;
580 ret.coreRegName = _coreRegName;
581 ret.auxRegName = _auxRegName;
582 ret.condCodeName = _condCodeName;
583 ret.instName = _instName;
584#endif
47b0e7ad 585
886a2506 586 return ret;
0d2bcfaf
NC
587}
588
886a2506
NC
589/* Local variables:
590 eval: (c-set-style "gnu")
591 indent-tabs-mode: t
592 End: */
This page took 1.040333 seconds and 4 git commands to generate.