]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - opcodes/arc-dis.c
gdb/riscv: Handle empty C++ structs during argument passing
[thirdparty/binutils-gdb.git] / opcodes / arc-dis.c
CommitLineData
252b5132 1/* Instruction printing code for the ARC.
82704155 2 Copyright (C) 1994-2019 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"
37fd5ef3 28#include "elf/arc.h"
0d2bcfaf
NC
29#include "arc-dis.h"
30#include "arc-ext.h"
37fd5ef3
CZ
31#include "elf-bfd.h"
32#include "libiberty.h"
33#include "opintl.h"
252b5132 34
4eb6f892
AB
35/* Structure used to iterate over, and extract the values for, operands of
36 an opcode. */
37
38struct arc_operand_iterator
39{
bdfe53e3
AB
40 /* The complete instruction value to extract operands from. */
41 unsigned long long insn;
4eb6f892 42
bdfe53e3
AB
43 /* The LIMM if this is being tracked separately. This field is only
44 valid if we find the LIMM operand in the operand list. */
45 unsigned limm;
4eb6f892 46
bdfe53e3
AB
47 /* The opcode this iterator is operating on. */
48 const struct arc_opcode *opcode;
4eb6f892 49
bdfe53e3
AB
50 /* The index into the opcodes operand index list. */
51 const unsigned char *opidx;
4eb6f892 52};
252b5132 53
6ec7c1ae
CZ
54/* A private data used by ARC decoder. */
55struct arc_disassemble_info
56{
57 /* The current disassembled arc opcode. */
58 const struct arc_opcode *opcode;
59
60 /* Instruction length w/o limm field. */
61 unsigned insn_len;
62
63 /* TRUE if we have limm. */
64 bfd_boolean limm_p;
65
66 /* LIMM value, if exists. */
67 unsigned limm;
68
69 /* Condition code, if exists. */
70 unsigned condition_code;
71
72 /* Writeback mode. */
73 unsigned writeback_mode;
74
75 /* Number of operands. */
76 unsigned operands_count;
77
78 struct arc_insn_operand operands[MAX_INSN_ARGS];
79};
80
886a2506 81/* Globals variables. */
82b829a7 82
886a2506 83static const char * const regnames[64] =
47b0e7ad 84{
886a2506
NC
85 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
86 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
87 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
88 "r24", "r25", "gp", "fp", "sp", "ilink", "r30", "blink",
89
90 "r32", "r33", "r34", "r35", "r36", "r37", "r38", "r39",
91 "r40", "r41", "r42", "r43", "r44", "r45", "r46", "r47",
92 "r48", "r49", "r50", "r51", "r52", "r53", "r54", "r55",
93 "r56", "r57", "ACCL", "ACCH", "lp_count", "rezerved", "LIMM", "pcl"
94};
95
db18dbab
GM
96static const char * const addrtypenames[ARC_NUM_ADDRTYPES] =
97{
98 "bd", "jid", "lbd", "mbd", "sd", "sm", "xa", "xd",
99 "cd", "cbd", "cjid", "clbd", "cm", "csd", "cxa", "cxd"
100};
101
102static int addrtypenames_max = ARC_NUM_ADDRTYPES - 1;
103
104static const char * const addrtypeunknown = "unknown";
105
37fd5ef3
CZ
106/* This structure keeps track which instruction class(es)
107 should be ignored durring disassembling. */
108
109typedef struct skipclass
110{
111 insn_class_t insn_class;
112 insn_subclass_t subclass;
113 struct skipclass *nxt;
114} skipclass_t, *linkclass;
115
116/* Intial classes of instructions to be consider first when
117 disassembling. */
118static linkclass decodelist = NULL;
119
10045478
AK
120/* ISA mask value enforced via disassembler info options. ARC_OPCODE_NONE
121 value means that no CPU is enforced. */
122
123static unsigned enforced_isa_mask = ARC_OPCODE_NONE;
124
fdddd290 125/* True if we want to print using only hex numbers. */
126static bfd_boolean print_hex = FALSE;
127
886a2506
NC
128/* Macros section. */
129
130#ifdef DEBUG
131# define pr_debug(fmt, args...) fprintf (stderr, fmt, ##args)
132#else
133# define pr_debug(fmt, args...)
134#endif
135
136#define ARRANGE_ENDIAN(info, buf) \
137 (info->endian == BFD_ENDIAN_LITTLE ? bfd_getm32 (bfd_getl32 (buf)) \
138 : bfd_getb32 (buf))
139
140#define BITS(word,s,e) (((word) << (sizeof (word) * 8 - 1 - e)) >> \
141 (s + (sizeof (word) * 8 - 1 - e)))
bdfe53e3 142#define OPCODE_32BIT_INSN(word) (BITS ((word), 27, 31))
252b5132 143
886a2506 144/* Functions implementation. */
252b5132 145
6ec7c1ae
CZ
146/* Initialize private data. */
147static bfd_boolean
148init_arc_disasm_info (struct disassemble_info *info)
149{
150 struct arc_disassemble_info *arc_infop
151 = calloc (sizeof (*arc_infop), 1);
152
153 if (arc_infop == NULL)
154 return FALSE;
155
156 info->private_data = arc_infop;
157 return TRUE;
158}
159
37fd5ef3
CZ
160/* Add a new element to the decode list. */
161
162static void
163add_to_decodelist (insn_class_t insn_class,
164 insn_subclass_t subclass)
165{
166 linkclass t = (linkclass) xmalloc (sizeof (skipclass_t));
167
168 t->insn_class = insn_class;
169 t->subclass = subclass;
170 t->nxt = decodelist;
171 decodelist = t;
172}
173
174/* Return TRUE if we need to skip the opcode from being
175 disassembled. */
176
177static bfd_boolean
ee881e5d 178skip_this_opcode (const struct arc_opcode *opcode)
37fd5ef3
CZ
179{
180 linkclass t = decodelist;
37fd5ef3
CZ
181
182 /* Check opcode for major 0x06, return if it is not in. */
bdfe53e3
AB
183 if (arc_opcode_len (opcode) == 4
184 && OPCODE_32BIT_INSN (opcode->opcode) != 0x06)
37fd5ef3
CZ
185 return FALSE;
186
ee881e5d
CZ
187 /* or not a known truble class. */
188 switch (opcode->insn_class)
189 {
190 case FLOAT:
191 case DSP:
3334eba7 192 case ARITH:
ee881e5d
CZ
193 break;
194 default:
195 return FALSE;
196 }
197
198 while (t != NULL)
37fd5ef3
CZ
199 {
200 if ((t->insn_class == opcode->insn_class)
201 && (t->subclass == opcode->subclass))
ee881e5d 202 return FALSE;
37fd5ef3
CZ
203 t = t->nxt;
204 }
205
ee881e5d 206 return TRUE;
37fd5ef3
CZ
207}
208
886a2506
NC
209static bfd_vma
210bfd_getm32 (unsigned int data)
0d2bcfaf 211{
886a2506 212 bfd_vma value = 0;
0d2bcfaf 213
886a2506
NC
214 value = ((data & 0xff00) | (data & 0xff)) << 16;
215 value |= ((data & 0xff0000) | (data & 0xff000000)) >> 16;
216 return value;
0d2bcfaf
NC
217}
218
37fd5ef3 219static bfd_boolean
886a2506
NC
220special_flag_p (const char *opname,
221 const char *flgname)
0d2bcfaf 222{
886a2506 223 const struct arc_flag_special *flg_spec;
886a2506 224 unsigned i, j, flgidx;
0d2bcfaf 225
886a2506 226 for (i = 0; i < arc_num_flag_special; i++)
252b5132 227 {
886a2506 228 flg_spec = &arc_flag_special_cases[i];
279a96ca 229
24b368f8 230 if (strcmp (opname, flg_spec->name))
886a2506 231 continue;
279a96ca 232
886a2506
NC
233 /* Found potential special case instruction. */
234 for (j=0;; ++j)
0d2bcfaf 235 {
886a2506
NC
236 flgidx = flg_spec->flags[j];
237 if (flgidx == 0)
238 break; /* End of the array. */
0d2bcfaf 239
886a2506 240 if (strcmp (flgname, arc_flag_operands[flgidx].name) == 0)
37fd5ef3 241 return TRUE;
252b5132 242 }
0d2bcfaf 243 }
37fd5ef3 244 return FALSE;
0d2bcfaf 245}
252b5132 246
4eb6f892
AB
247/* Find opcode from ARC_TABLE given the instruction described by INSN and
248 INSNLEN. The ISA_MASK restricts the possible matches in ARC_TABLE. */
249
b99747ae 250static const struct arc_opcode *
37fd5ef3
CZ
251find_format_from_table (struct disassemble_info *info,
252 const struct arc_opcode *arc_table,
bdfe53e3 253 unsigned long long insn,
37fd5ef3
CZ
254 unsigned int insn_len,
255 unsigned isa_mask,
256 bfd_boolean *has_limm,
257 bfd_boolean overlaps)
b99747ae
CZ
258{
259 unsigned int i = 0;
260 const struct arc_opcode *opcode = NULL;
ee881e5d 261 const struct arc_opcode *t_op = NULL;
b99747ae
CZ
262 const unsigned char *opidx;
263 const unsigned char *flgidx;
ee881e5d 264 bfd_boolean warn_p = FALSE;
b99747ae 265
37fd5ef3
CZ
266 do
267 {
268 bfd_boolean invalid = FALSE;
b99747ae 269
37fd5ef3 270 opcode = &arc_table[i++];
b99747ae 271
bdfe53e3 272 if (!(opcode->cpu & isa_mask))
37fd5ef3 273 continue;
b99747ae 274
bdfe53e3 275 if (arc_opcode_len (opcode) != (int) insn_len)
37fd5ef3 276 continue;
b99747ae 277
bdfe53e3 278 if ((insn & opcode->mask) != opcode->opcode)
37fd5ef3 279 continue;
b99747ae 280
37fd5ef3 281 *has_limm = FALSE;
4eb6f892 282
37fd5ef3
CZ
283 /* Possible candidate, check the operands. */
284 for (opidx = opcode->operands; *opidx; opidx++)
285 {
e5b06ef0 286 int value, limmind;
37fd5ef3 287 const struct arc_operand *operand = &arc_operands[*opidx];
b99747ae 288
37fd5ef3
CZ
289 if (operand->flags & ARC_OPERAND_FAKE)
290 continue;
b99747ae 291
37fd5ef3 292 if (operand->extract)
bdfe53e3 293 value = (*operand->extract) (insn, &invalid);
37fd5ef3 294 else
bdfe53e3 295 value = (insn >> operand->shift) & ((1 << operand->bits) - 1);
37fd5ef3
CZ
296
297 /* Check for LIMM indicator. If it is there, then make sure
298 we pick the right format. */
e5b06ef0 299 limmind = (isa_mask & ARC_OPCODE_ARCV2) ? 0x1E : 0x3E;
37fd5ef3
CZ
300 if (operand->flags & ARC_OPERAND_IR
301 && !(operand->flags & ARC_OPERAND_LIMM))
302 {
303 if ((value == 0x3E && insn_len == 4)
e5b06ef0 304 || (value == limmind && insn_len == 2))
37fd5ef3
CZ
305 {
306 invalid = TRUE;
307 break;
308 }
309 }
310
311 if (operand->flags & ARC_OPERAND_LIMM
312 && !(operand->flags & ARC_OPERAND_DUPLICATE))
313 *has_limm = TRUE;
314 }
315
316 /* Check the flags. */
317 for (flgidx = opcode->flags; *flgidx; flgidx++)
318 {
319 /* Get a valid flag class. */
320 const struct arc_flag_class *cl_flags = &arc_flag_classes[*flgidx];
321 const unsigned *flgopridx;
322 int foundA = 0, foundB = 0;
323 unsigned int value;
324
325 /* Check first the extensions. */
326 if (cl_flags->flag_class & F_CLASS_EXTEND)
327 {
bdfe53e3 328 value = (insn & 0x1F);
37fd5ef3
CZ
329 if (arcExtMap_condCodeName (value))
330 continue;
331 }
332
6ec7c1ae
CZ
333 /* Check for the implicit flags. */
334 if (cl_flags->flag_class & F_CLASS_IMPLICIT)
335 continue;
336
37fd5ef3
CZ
337 for (flgopridx = cl_flags->flags; *flgopridx; ++flgopridx)
338 {
339 const struct arc_flag_operand *flg_operand =
340 &arc_flag_operands[*flgopridx];
341
bdfe53e3 342 value = (insn >> flg_operand->shift)
37fd5ef3
CZ
343 & ((1 << flg_operand->bits) - 1);
344 if (value == flg_operand->code)
345 foundA = 1;
346 if (value)
347 foundB = 1;
348 }
349
350 if (!foundA && foundB)
351 {
352 invalid = TRUE;
353 break;
354 }
355 }
356
357 if (invalid)
358 continue;
359
360 if (insn_len == 4
ee881e5d
CZ
361 && overlaps)
362 {
363 warn_p = TRUE;
364 t_op = opcode;
365 if (skip_this_opcode (opcode))
366 continue;
367 }
37fd5ef3
CZ
368
369 /* The instruction is valid. */
370 return opcode;
371 }
372 while (opcode->mask);
b99747ae 373
ee881e5d
CZ
374 if (warn_p)
375 {
376 info->fprintf_func (info->stream,
377 _("\nWarning: disassembly may be wrong due to "
378 "guessed opcode class choice.\n"
379 "Use -M<class[,class]> to select the correct "
380 "opcode class(es).\n\t\t\t\t"));
381 return t_op;
382 }
383
b99747ae
CZ
384 return NULL;
385}
386
4eb6f892
AB
387/* Find opcode for INSN, trying various different sources. The instruction
388 length in INSN_LEN will be updated if the instruction requires a LIMM
bdfe53e3 389 extension.
4eb6f892
AB
390
391 A pointer to the opcode is placed into OPCODE_RESULT, and ITER is
bdfe53e3
AB
392 initialised, ready to iterate over the operands of the found opcode. If
393 the found opcode requires a LIMM then the LIMM value will be loaded into a
394 field of ITER.
4eb6f892
AB
395
396 This function returns TRUE in almost all cases, FALSE is reserved to
bdfe53e3
AB
397 indicate an error (failing to find an opcode is not an error) a returned
398 result of FALSE would indicate that the disassembler can't continue.
4eb6f892 399
bdfe53e3
AB
400 If no matching opcode is found then the returned result will be TRUE, the
401 value placed into OPCODE_RESULT will be NULL, ITER will be undefined, and
402 INSN_LEN will be unchanged.
4eb6f892 403
bdfe53e3
AB
404 If a matching opcode is found, then the returned result will be TRUE, the
405 opcode pointer is placed into OPCODE_RESULT, INSN_LEN will be increased by
406 4 if the instruction requires a LIMM, and the LIMM value will have been
407 loaded into a field of ITER. Finally, ITER will have been initialised so
408 that calls to OPERAND_ITERATOR_NEXT will iterate over the opcode's
409 operands. */
4eb6f892
AB
410
411static bfd_boolean
37fd5ef3 412find_format (bfd_vma memaddr,
bdfe53e3 413 unsigned long long insn,
37fd5ef3
CZ
414 unsigned int * insn_len,
415 unsigned isa_mask,
416 struct disassemble_info * info,
417 const struct arc_opcode ** opcode_result,
418 struct arc_operand_iterator * iter)
4eb6f892 419{
37fd5ef3 420 const struct arc_opcode *opcode = NULL;
4eb6f892 421 bfd_boolean needs_limm;
f807f43d 422 const extInstruction_t *einsn, *i;
bdfe53e3 423 unsigned limm = 0;
6ec7c1ae 424 struct arc_disassemble_info *arc_infop = info->private_data;
4eb6f892 425
37fd5ef3 426 /* First, try the extension instructions. */
bdfe53e3 427 if (*insn_len == 4)
4eb6f892 428 {
bdfe53e3
AB
429 einsn = arcExtMap_insn (OPCODE_32BIT_INSN (insn), insn);
430 for (i = einsn; (i != NULL) && (opcode == NULL); i = i->next)
4eb6f892 431 {
bdfe53e3
AB
432 const char *errmsg = NULL;
433
434 opcode = arcExtMap_genOpcode (i, isa_mask, &errmsg);
435 if (opcode == NULL)
436 {
437 (*info->fprintf_func) (info->stream, "\
37fd5ef3 438An error occured while generating the extension instruction operations");
bdfe53e3
AB
439 *opcode_result = NULL;
440 return FALSE;
441 }
37fd5ef3 442
bdfe53e3
AB
443 opcode = find_format_from_table (info, opcode, insn, *insn_len,
444 isa_mask, &needs_limm, FALSE);
445 }
4eb6f892
AB
446 }
447
37fd5ef3
CZ
448 /* Then, try finding the first match in the opcode table. */
449 if (opcode == NULL)
450 opcode = find_format_from_table (info, arc_opcodes, insn, *insn_len,
451 isa_mask, &needs_limm, TRUE);
452
4eb6f892
AB
453 if (needs_limm && opcode != NULL)
454 {
455 bfd_byte buffer[4];
456 int status;
457
458 status = (*info->read_memory_func) (memaddr + *insn_len, buffer,
459 4, info);
460 if (status != 0)
461 {
462 opcode = NULL;
463 }
464 else
465 {
bdfe53e3 466 limm = ARRANGE_ENDIAN (info, buffer);
4eb6f892
AB
467 *insn_len += 4;
468 }
469 }
470
bdfe53e3 471 if (opcode != NULL)
4eb6f892 472 {
4eb6f892 473 iter->insn = insn;
bdfe53e3
AB
474 iter->limm = limm;
475 iter->opcode = opcode;
476 iter->opidx = opcode->operands;
4eb6f892
AB
477 }
478
479 *opcode_result = opcode;
6ec7c1ae
CZ
480
481 /* Update private data. */
482 arc_infop->opcode = opcode;
483 arc_infop->limm = (needs_limm) ? limm : 0;
484 arc_infop->limm_p = needs_limm;
485
4eb6f892
AB
486 return TRUE;
487}
488
f36e33da
CZ
489static void
490print_flags (const struct arc_opcode *opcode,
bdfe53e3 491 unsigned long long *insn,
f36e33da
CZ
492 struct disassemble_info *info)
493{
494 const unsigned char *flgidx;
495 unsigned int value;
6ec7c1ae 496 struct arc_disassemble_info *arc_infop = info->private_data;
f36e33da
CZ
497
498 /* Now extract and print the flags. */
499 for (flgidx = opcode->flags; *flgidx; flgidx++)
500 {
501 /* Get a valid flag class. */
502 const struct arc_flag_class *cl_flags = &arc_flag_classes[*flgidx];
503 const unsigned *flgopridx;
504
505 /* Check first the extensions. */
c810e0b8 506 if (cl_flags->flag_class & F_CLASS_EXTEND)
f36e33da
CZ
507 {
508 const char *name;
509 value = (insn[0] & 0x1F);
510
511 name = arcExtMap_condCodeName (value);
512 if (name)
513 {
514 (*info->fprintf_func) (info->stream, ".%s", name);
515 continue;
516 }
517 }
518
519 for (flgopridx = cl_flags->flags; *flgopridx; ++flgopridx)
520 {
521 const struct arc_flag_operand *flg_operand =
522 &arc_flag_operands[*flgopridx];
523
6ec7c1ae
CZ
524 /* Implicit flags are only used for the insn decoder. */
525 if (cl_flags->flag_class & F_CLASS_IMPLICIT)
526 {
527 if (cl_flags->flag_class & F_CLASS_COND)
528 arc_infop->condition_code = flg_operand->code;
529 else if (cl_flags->flag_class & F_CLASS_WB)
530 arc_infop->writeback_mode = flg_operand->code;
531 else if (cl_flags->flag_class & F_CLASS_ZZ)
532 info->data_size = flg_operand->code;
533 continue;
534 }
535
f36e33da
CZ
536 if (!flg_operand->favail)
537 continue;
538
539 value = (insn[0] >> flg_operand->shift)
540 & ((1 << flg_operand->bits) - 1);
541 if (value == flg_operand->code)
542 {
543 /* FIXME!: print correctly nt/t flag. */
544 if (!special_flag_p (opcode->name, flg_operand->name))
545 (*info->fprintf_func) (info->stream, ".");
546 else if (info->insn_type == dis_dref)
547 {
548 switch (flg_operand->name[0])
549 {
550 case 'b':
551 info->data_size = 1;
552 break;
553 case 'h':
554 case 'w':
555 info->data_size = 2;
556 break;
557 default:
558 info->data_size = 4;
559 break;
560 }
561 }
d9eca1df
CZ
562 if (flg_operand->name[0] == 'd'
563 && flg_operand->name[1] == 0)
564 info->branch_delay_insns = 1;
565
566 /* Check if it is a conditional flag. */
567 if (cl_flags->flag_class & F_CLASS_COND)
568 {
569 if (info->insn_type == dis_jsr)
570 info->insn_type = dis_condjsr;
571 else if (info->insn_type == dis_branch)
572 info->insn_type = dis_condbranch;
6ec7c1ae 573 arc_infop->condition_code = flg_operand->code;
d9eca1df
CZ
574 }
575
6ec7c1ae
CZ
576 /* Check for the write back modes. */
577 if (cl_flags->flag_class & F_CLASS_WB)
578 arc_infop->writeback_mode = flg_operand->code;
579
f36e33da
CZ
580 (*info->fprintf_func) (info->stream, "%s", flg_operand->name);
581 }
f36e33da
CZ
582 }
583 }
584}
585
586static const char *
587get_auxreg (const struct arc_opcode *opcode,
588 int value,
589 unsigned isa_mask)
590{
591 const char *name;
592 unsigned int i;
593 const struct arc_aux_reg *auxr = &arc_aux_regs[0];
594
c810e0b8 595 if (opcode->insn_class != AUXREG)
f36e33da
CZ
596 return NULL;
597
598 name = arcExtMap_auxRegName (value);
599 if (name)
600 return name;
601
602 for (i = 0; i < arc_num_aux_regs; i++, auxr++)
603 {
604 if (!(auxr->cpu & isa_mask))
605 continue;
606
607 if (auxr->subclass != NONE)
608 return NULL;
609
610 if (auxr->address == value)
611 return auxr->name;
612 }
613 return NULL;
614}
cb040366 615
db18dbab
GM
616/* Convert a value representing an address type to a string used to refer to
617 the address type in assembly code. */
618
619static const char *
620get_addrtype (int value)
621{
622 if (value < 0 || value > addrtypenames_max)
623 return addrtypeunknown;
624
625 return addrtypenames[value];
626}
627
cb040366
AB
628/* Calculate the instruction length for an instruction starting with MSB
629 and LSB, the most and least significant byte. The ISA_MASK is used to
630 filter the instructions considered to only those that are part of the
631 current architecture.
632
633 The instruction lengths are calculated from the ARC_OPCODE table, and
634 cached for later use. */
635
636static unsigned int
4eb6f892 637arc_insn_length (bfd_byte msb, bfd_byte lsb, struct disassemble_info *info)
cb040366
AB
638{
639 bfd_byte major_opcode = msb >> 3;
640
641 switch (info->mach)
642 {
bdd582db
GM
643 case bfd_mach_arc_arc700:
644 /* The nps400 extension set requires this special casing of the
645 instruction length calculation. Right now this is not causing any
646 problems as none of the known extensions overlap in opcode space,
647 but, if they ever do then we might need to start carrying
648 information around in the elf about which extensions are in use. */
4eb6f892
AB
649 if (major_opcode == 0xb)
650 {
651 bfd_byte minor_opcode = lsb & 0x1f;
652
bdfe53e3
AB
653 if (minor_opcode < 4)
654 return 6;
655 else if (minor_opcode == 0x10 || minor_opcode == 0x11)
656 return 8;
4eb6f892 657 }
5a736821
GM
658 if (major_opcode == 0xa)
659 {
660 return 8;
661 }
1a0670f3 662 /* Fall through. */
cb040366
AB
663 case bfd_mach_arc_arc600:
664 return (major_opcode > 0xb) ? 2 : 4;
665 break;
666
667 case bfd_mach_arc_arcv2:
668 return (major_opcode > 0x7) ? 2 : 4;
669 break;
670
671 default:
672 abort ();
673 }
674}
675
4eb6f892
AB
676/* Extract and return the value of OPERAND from the instruction whose value
677 is held in the array INSN. */
678
679static int
bdfe53e3
AB
680extract_operand_value (const struct arc_operand *operand,
681 unsigned long long insn,
682 unsigned limm)
4eb6f892
AB
683{
684 int value;
685
686 /* Read the limm operand, if required. */
687 if (operand->flags & ARC_OPERAND_LIMM)
688 /* The second part of the instruction value will have been loaded as
689 part of the find_format call made earlier. */
bdfe53e3 690 value = limm;
4eb6f892
AB
691 else
692 {
693 if (operand->extract)
bdfe53e3 694 value = (*operand->extract) (insn, (int *) NULL);
4eb6f892
AB
695 else
696 {
697 if (operand->flags & ARC_OPERAND_ALIGNED32)
698 {
bdfe53e3 699 value = (insn >> operand->shift)
4eb6f892
AB
700 & ((1 << (operand->bits - 2)) - 1);
701 value = value << 2;
702 }
703 else
704 {
bdfe53e3 705 value = (insn >> operand->shift) & ((1 << operand->bits) - 1);
4eb6f892
AB
706 }
707 if (operand->flags & ARC_OPERAND_SIGNED)
708 {
709 int signbit = 1 << (operand->bits - 1);
710 value = (value ^ signbit) - signbit;
711 }
712 }
713 }
714
715 return value;
716}
717
718/* Find the next operand, and the operands value from ITER. Return TRUE if
719 there is another operand, otherwise return FALSE. If there is an
720 operand returned then the operand is placed into OPERAND, and the value
721 into VALUE. If there is no operand returned then OPERAND and VALUE are
722 unchanged. */
723
724static bfd_boolean
725operand_iterator_next (struct arc_operand_iterator *iter,
726 const struct arc_operand **operand,
727 int *value)
728{
bdfe53e3 729 if (*iter->opidx == 0)
4eb6f892 730 {
bdfe53e3
AB
731 *operand = NULL;
732 return FALSE;
4eb6f892 733 }
4eb6f892 734
bdfe53e3
AB
735 *operand = &arc_operands[*iter->opidx];
736 *value = extract_operand_value (*operand, iter->insn, iter->limm);
737 iter->opidx++;
4eb6f892 738
4eb6f892
AB
739 return TRUE;
740}
741
37fd5ef3
CZ
742/* Helper for parsing the options. */
743
744static void
f995bbe8 745parse_option (const char *option)
37fd5ef3 746{
e1e94c49 747 if (disassembler_options_cmp (option, "dsp") == 0)
37fd5ef3
CZ
748 add_to_decodelist (DSP, NONE);
749
e1e94c49 750 else if (disassembler_options_cmp (option, "spfp") == 0)
37fd5ef3
CZ
751 add_to_decodelist (FLOAT, SPX);
752
e1e94c49 753 else if (disassembler_options_cmp (option, "dpfp") == 0)
37fd5ef3
CZ
754 add_to_decodelist (FLOAT, DPX);
755
e1e94c49 756 else if (disassembler_options_cmp (option, "quarkse_em") == 0)
ee881e5d
CZ
757 {
758 add_to_decodelist (FLOAT, DPX);
759 add_to_decodelist (FLOAT, SPX);
53a346d8
CZ
760 add_to_decodelist (FLOAT, QUARKSE1);
761 add_to_decodelist (FLOAT, QUARKSE2);
ee881e5d 762 }
37fd5ef3 763
e1e94c49 764 else if (disassembler_options_cmp (option, "fpuda") == 0)
37fd5ef3
CZ
765 add_to_decodelist (FLOAT, DPA);
766
e1e94c49 767 else if (disassembler_options_cmp (option, "fpus") == 0)
37fd5ef3
CZ
768 {
769 add_to_decodelist (FLOAT, SP);
770 add_to_decodelist (FLOAT, CVT);
771 }
772
e1e94c49 773 else if (disassembler_options_cmp (option, "fpud") == 0)
37fd5ef3
CZ
774 {
775 add_to_decodelist (FLOAT, DP);
776 add_to_decodelist (FLOAT, CVT);
777 }
fdddd290 778 else if (CONST_STRNEQ (option, "hex"))
779 print_hex = TRUE;
37fd5ef3 780 else
a6743a54
AM
781 /* xgettext:c-format */
782 opcodes_error_handler (_("unrecognised disassembler option: %s"), option);
37fd5ef3
CZ
783}
784
10045478
AK
785#define ARC_CPU_TYPE_A6xx(NAME,EXTRA) \
786 { #NAME, ARC_OPCODE_ARC600, "ARC600" }
787#define ARC_CPU_TYPE_A7xx(NAME,EXTRA) \
788 { #NAME, ARC_OPCODE_ARC700, "ARC700" }
789#define ARC_CPU_TYPE_AV2EM(NAME,EXTRA) \
790 { #NAME, ARC_OPCODE_ARCv2EM, "ARC EM" }
791#define ARC_CPU_TYPE_AV2HS(NAME,EXTRA) \
792 { #NAME, ARC_OPCODE_ARCv2HS, "ARC HS" }
793#define ARC_CPU_TYPE_NONE \
794 { 0, 0, 0 }
795
796/* A table of CPU names and opcode sets. */
797static const struct cpu_type
798{
799 const char *name;
800 unsigned flags;
801 const char *isa;
802}
803 cpu_types[] =
804{
805 #include "elf/arc-cpu.def"
806};
807
808/* Helper for parsing the CPU options. Accept any of the ARC architectures
809 values. OPTION should be a value passed to cpu=. */
810
811static unsigned
812parse_cpu_option (const char *option)
813{
814 int i;
815
816 for (i = 0; cpu_types[i].name; ++i)
817 {
e1e94c49 818 if (!disassembler_options_cmp (cpu_types[i].name, option))
10045478
AK
819 {
820 return cpu_types[i].flags;
821 }
822 }
823
a6743a54
AM
824 /* xgettext:c-format */
825 opcodes_error_handler (_("unrecognised disassembler CPU option: %s"), option);
10045478
AK
826 return ARC_OPCODE_NONE;
827}
828
37fd5ef3
CZ
829/* Go over the options list and parse it. */
830
831static void
f995bbe8 832parse_disassembler_options (const char *options)
37fd5ef3 833{
2e74f9dd
AK
834 const char *option;
835
37fd5ef3
CZ
836 if (options == NULL)
837 return;
838
10045478
AK
839 /* Disassembler might be reused for difference CPU's, and cpu option set for
840 the first one shouldn't be applied to second (which might not have
841 explicit cpu in its options. Therefore it is required to reset enforced
842 CPU when new options are being parsed. */
843 enforced_isa_mask = ARC_OPCODE_NONE;
844
2e74f9dd 845 FOR_EACH_DISASSEMBLER_OPTION (option, options)
37fd5ef3 846 {
10045478
AK
847 /* A CPU option? Cannot use STRING_COMMA_LEN because strncmp is also a
848 preprocessor macro. */
2e74f9dd 849 if (strncmp (option, "cpu=", 4) == 0)
10045478 850 /* Strip leading `cpu=`. */
2e74f9dd 851 enforced_isa_mask = parse_cpu_option (option + 4);
10045478 852 else
2e74f9dd 853 parse_option (option);
37fd5ef3
CZ
854 }
855}
856
bdfe53e3
AB
857/* Return the instruction type for an instruction described by OPCODE. */
858
859static enum dis_insn_type
860arc_opcode_to_insn_type (const struct arc_opcode *opcode)
861{
862 enum dis_insn_type insn_type;
863
864 switch (opcode->insn_class)
865 {
866 case BRANCH:
6ec7c1ae
CZ
867 case BBIT0:
868 case BBIT1:
869 case BI:
870 case BIH:
871 case BRCC:
872 case EI:
873 case JLI:
bdfe53e3 874 case JUMP:
6ec7c1ae 875 case LOOP:
bdfe53e3
AB
876 if (!strncmp (opcode->name, "bl", 2)
877 || !strncmp (opcode->name, "jl", 2))
878 {
879 if (opcode->subclass == COND)
880 insn_type = dis_condjsr;
881 else
882 insn_type = dis_jsr;
883 }
884 else
885 {
886 if (opcode->subclass == COND)
887 insn_type = dis_condbranch;
888 else
889 insn_type = dis_branch;
890 }
891 break;
abe7c33b
CZ
892 case LOAD:
893 case STORE:
bdfe53e3 894 case MEMORY:
6ec7c1ae
CZ
895 case ENTER:
896 case PUSH:
897 case POP:
abe7c33b 898 insn_type = dis_dref;
bdfe53e3 899 break;
6ec7c1ae
CZ
900 case LEAVE:
901 insn_type = dis_branch;
902 break;
bdfe53e3
AB
903 default:
904 insn_type = dis_nonbranch;
905 break;
906 }
907
908 return insn_type;
909}
910
886a2506 911/* Disassemble ARC instructions. */
0d2bcfaf 912
886a2506
NC
913static int
914print_insn_arc (bfd_vma memaddr,
915 struct disassemble_info *info)
0d2bcfaf 916{
bdfe53e3
AB
917 bfd_byte buffer[8];
918 unsigned int highbyte, lowbyte;
886a2506 919 int status;
4eb6f892 920 unsigned int insn_len;
bdfe53e3 921 unsigned long long insn = 0;
10045478 922 unsigned isa_mask = ARC_OPCODE_NONE;
886a2506 923 const struct arc_opcode *opcode;
886a2506
NC
924 bfd_boolean need_comma;
925 bfd_boolean open_braket;
24b368f8 926 int size;
4eb6f892 927 const struct arc_operand *operand;
50d2740d 928 int value, vpcl;
4eb6f892 929 struct arc_operand_iterator iter;
6ec7c1ae 930 struct arc_disassemble_info *arc_infop;
50d2740d 931 bfd_boolean rpcl = FALSE, rset = FALSE;
37fd5ef3
CZ
932
933 if (info->disassembler_options)
934 {
935 parse_disassembler_options (info->disassembler_options);
936
937 /* Avoid repeated parsing of the options. */
938 info->disassembler_options = NULL;
939 }
0d2bcfaf 940
6ec7c1ae
CZ
941 if (info->private_data == NULL && !init_arc_disasm_info (info))
942 return -1;
943
4eb6f892 944 memset (&iter, 0, sizeof (iter));
90f61cce
GM
945 highbyte = ((info->endian == BFD_ENDIAN_LITTLE) ? 1 : 0);
946 lowbyte = ((info->endian == BFD_ENDIAN_LITTLE) ? 0 : 1);
0d2bcfaf 947
10045478
AK
948 /* Figure out CPU type, unless it was enforced via disassembler options. */
949 if (enforced_isa_mask == ARC_OPCODE_NONE)
886a2506 950 {
10045478 951 Elf_Internal_Ehdr *header = NULL;
0d2bcfaf 952
10045478
AK
953 if (info->section && info->section->owner)
954 header = elf_elfheader (info->section->owner);
0d2bcfaf 955
10045478 956 switch (info->mach)
37fd5ef3 957 {
10045478
AK
958 case bfd_mach_arc_arc700:
959 isa_mask = ARC_OPCODE_ARC700;
960 break;
961
962 case bfd_mach_arc_arc600:
963 isa_mask = ARC_OPCODE_ARC600;
964 break;
965
966 case bfd_mach_arc_arcv2:
967 default:
968 isa_mask = ARC_OPCODE_ARCv2EM;
969 /* TODO: Perhaps remove definition of header since it is only used at
970 this location. */
971 if (header != NULL
972 && (header->e_flags & EF_ARC_MACH_MSK) == EF_ARC_CPU_ARCV2HS)
973 isa_mask = ARC_OPCODE_ARCv2HS;
974 break;
37fd5ef3 975 }
10045478
AK
976 }
977 else
978 isa_mask = enforced_isa_mask;
979
980 if (isa_mask == ARC_OPCODE_ARCv2HS)
981 {
982 /* FPU instructions are not extensions for HS. */
983 add_to_decodelist (FLOAT, SP);
984 add_to_decodelist (FLOAT, DP);
985 add_to_decodelist (FLOAT, CVT);
0d2bcfaf
NC
986 }
987
24b368f8
CZ
988 /* This variable may be set by the instruction decoder. It suggests
989 the number of bytes objdump should display on a single line. If
990 the instruction decoder sets this, it should always set it to
991 the same value in order to get reasonable looking output. */
992
993 info->bytes_per_line = 8;
994
995 /* In the next lines, we set two info variables control the way
996 objdump displays the raw data. For example, if bytes_per_line is
997 8 and bytes_per_chunk is 4, the output will look like this:
998 00: 00000000 00000000
999 with the chunks displayed according to "display_endian". */
1000
1001 if (info->section
1002 && !(info->section->flags & SEC_CODE))
1003 {
1004 /* This is not a CODE section. */
1005 switch (info->section->size)
1006 {
1007 case 1:
1008 case 2:
1009 case 4:
1010 size = info->section->size;
1011 break;
1012 default:
1013 size = (info->section->size & 0x01) ? 1 : 4;
1014 break;
1015 }
1016 info->bytes_per_chunk = 1;
1017 info->display_endian = info->endian;
1018 }
1019 else
1020 {
1021 size = 2;
1022 info->bytes_per_chunk = 2;
1023 info->display_endian = info->endian;
1024 }
1025
886a2506 1026 /* Read the insn into a host word. */
24b368f8 1027 status = (*info->read_memory_func) (memaddr, buffer, size, info);
50d2740d 1028
886a2506 1029 if (status != 0)
0d2bcfaf 1030 {
886a2506
NC
1031 (*info->memory_error_func) (status, memaddr, info);
1032 return -1;
0d2bcfaf
NC
1033 }
1034
886a2506
NC
1035 if (info->section
1036 && !(info->section->flags & SEC_CODE))
0d2bcfaf 1037 {
24b368f8
CZ
1038 /* Data section. */
1039 unsigned long data;
1040
1041 data = bfd_get_bits (buffer, size * 8,
1042 info->display_endian == BFD_ENDIAN_BIG);
1043 switch (size)
0d2bcfaf 1044 {
24b368f8
CZ
1045 case 1:
1046 (*info->fprintf_func) (info->stream, ".byte\t0x%02lx", data);
1047 break;
1048 case 2:
1049 (*info->fprintf_func) (info->stream, ".short\t0x%04lx", data);
1050 break;
1051 case 4:
1052 (*info->fprintf_func) (info->stream, ".word\t0x%08lx", data);
1053 break;
1054 default:
1055 abort ();
0d2bcfaf 1056 }
24b368f8 1057 return size;
886a2506 1058 }
279a96ca 1059
90f61cce 1060 insn_len = arc_insn_length (buffer[highbyte], buffer[lowbyte], info);
4eb6f892 1061 pr_debug ("instruction length = %d bytes\n", insn_len);
6ec7c1ae
CZ
1062 arc_infop = info->private_data;
1063 arc_infop->insn_len = insn_len;
37fd5ef3 1064
4eb6f892 1065 switch (insn_len)
886a2506 1066 {
cb040366 1067 case 2:
bdfe53e3 1068 insn = (buffer[highbyte] << 8) | buffer[lowbyte];
cb040366 1069 break;
886a2506 1070
cb040366 1071 case 4:
bdfe53e3
AB
1072 {
1073 /* This is a long instruction: Read the remaning 2 bytes. */
1074 status = (*info->read_memory_func) (memaddr + 2, &buffer[2], 2, info);
1075 if (status != 0)
1076 {
1077 (*info->memory_error_func) (status, memaddr + 2, info);
1078 return -1;
1079 }
1080 insn = (unsigned long long) ARRANGE_ENDIAN (info, buffer);
1081 }
1082 break;
1083
1084 case 6:
1085 {
1086 status = (*info->read_memory_func) (memaddr + 2, &buffer[2], 4, info);
1087 if (status != 0)
1088 {
1089 (*info->memory_error_func) (status, memaddr + 2, info);
1090 return -1;
1091 }
1092 insn = (unsigned long long) ARRANGE_ENDIAN (info, &buffer[2]);
1093 insn |= ((unsigned long long) buffer[highbyte] << 40)
1094 | ((unsigned long long) buffer[lowbyte] << 32);
1095 }
cb040366 1096 break;
bdfe53e3
AB
1097
1098 case 8:
1099 {
1100 status = (*info->read_memory_func) (memaddr + 2, &buffer[2], 6, info);
1101 if (status != 0)
1102 {
1103 (*info->memory_error_func) (status, memaddr + 2, info);
1104 return -1;
1105 }
1106 insn =
1107 ((((unsigned long long) ARRANGE_ENDIAN (info, buffer)) << 32)
1108 | ((unsigned long long) ARRANGE_ENDIAN (info, &buffer[4])));
1109 }
1110 break;
1111
1112 default:
1113 /* There is no instruction whose length is not 2, 4, 6, or 8. */
1114 abort ();
886a2506
NC
1115 }
1116
bdfe53e3
AB
1117 pr_debug ("instruction value = %llx\n", insn);
1118
886a2506
NC
1119 /* Set some defaults for the insn info. */
1120 info->insn_info_valid = 1;
1121 info->branch_delay_insns = 0;
6ec7c1ae 1122 info->data_size = 4;
886a2506
NC
1123 info->insn_type = dis_nonbranch;
1124 info->target = 0;
1125 info->target2 = 0;
1126
1127 /* FIXME to be moved in dissasemble_init_for_target. */
1128 info->disassembler_needs_relocs = TRUE;
1129
1130 /* Find the first match in the opcode table. */
4eb6f892
AB
1131 if (!find_format (memaddr, insn, &insn_len, isa_mask, info, &opcode, &iter))
1132 return -1;
886a2506 1133
b99747ae
CZ
1134 if (!opcode)
1135 {
bdfe53e3
AB
1136 switch (insn_len)
1137 {
1138 case 2:
50d2740d 1139 (*info->fprintf_func) (info->stream, ".shor\t%#04llx",
bdfe53e3
AB
1140 insn & 0xffff);
1141 break;
1142 case 4:
50d2740d 1143 (*info->fprintf_func) (info->stream, ".word\t%#08llx",
bdfe53e3
AB
1144 insn & 0xffffffff);
1145 break;
1146 case 6:
50d2740d 1147 (*info->fprintf_func) (info->stream, ".long\t%#08llx",
bdfe53e3 1148 insn & 0xffffffff);
50d2740d 1149 (*info->fprintf_func) (info->stream, ".long\t%#04llx",
bdfe53e3
AB
1150 (insn >> 32) & 0xffff);
1151 break;
1152 case 8:
50d2740d 1153 (*info->fprintf_func) (info->stream, ".long\t%#08llx",
bdfe53e3 1154 insn & 0xffffffff);
50d2740d 1155 (*info->fprintf_func) (info->stream, ".long\t%#08llx",
bdfe53e3
AB
1156 insn >> 32);
1157 break;
1158 default:
1159 abort ();
1160 }
886a2506 1161
4eb6f892
AB
1162 info->insn_type = dis_noninsn;
1163 return insn_len;
886a2506 1164 }
279a96ca 1165
886a2506
NC
1166 /* Print the mnemonic. */
1167 (*info->fprintf_func) (info->stream, "%s", opcode->name);
1168
1169 /* Preselect the insn class. */
bdfe53e3 1170 info->insn_type = arc_opcode_to_insn_type (opcode);
279a96ca 1171
bdfe53e3 1172 pr_debug ("%s: 0x%08llx\n", opcode->name, opcode->opcode);
279a96ca 1173
bdfe53e3 1174 print_flags (opcode, &insn, info);
279a96ca 1175
886a2506
NC
1176 if (opcode->operands[0] != 0)
1177 (*info->fprintf_func) (info->stream, "\t");
279a96ca 1178
886a2506
NC
1179 need_comma = FALSE;
1180 open_braket = FALSE;
6ec7c1ae 1181 arc_infop->operands_count = 0;
279a96ca 1182
886a2506 1183 /* Now extract and print the operands. */
4eb6f892 1184 operand = NULL;
50d2740d 1185 vpcl = 0;
4eb6f892 1186 while (operand_iterator_next (&iter, &operand, &value))
886a2506 1187 {
886a2506 1188 if (open_braket && (operand->flags & ARC_OPERAND_BRAKET))
0d2bcfaf 1189 {
886a2506
NC
1190 (*info->fprintf_func) (info->stream, "]");
1191 open_braket = FALSE;
1192 continue;
0d2bcfaf 1193 }
279a96ca 1194
886a2506 1195 /* Only take input from real operands. */
db18dbab 1196 if (ARC_OPERAND_IS_FAKE (operand))
886a2506 1197 continue;
279a96ca 1198
4eb6f892
AB
1199 if ((operand->flags & ARC_OPERAND_IGNORE)
1200 && (operand->flags & ARC_OPERAND_IR)
6ec7c1ae 1201 && value == -1)
886a2506 1202 continue;
279a96ca 1203
db18dbab 1204 if (operand->flags & ARC_OPERAND_COLON)
6ec7c1ae
CZ
1205 {
1206 (*info->fprintf_func) (info->stream, ":");
1207 continue;
1208 }
db18dbab 1209
886a2506
NC
1210 if (need_comma)
1211 (*info->fprintf_func) (info->stream, ",");
279a96ca 1212
886a2506 1213 if (!open_braket && (operand->flags & ARC_OPERAND_BRAKET))
0d2bcfaf 1214 {
886a2506
NC
1215 (*info->fprintf_func) (info->stream, "[");
1216 open_braket = TRUE;
1217 need_comma = FALSE;
1218 continue;
0d2bcfaf 1219 }
886a2506 1220
db18dbab
GM
1221 need_comma = TRUE;
1222
50d2740d 1223 if (operand->flags & ARC_OPERAND_PCREL)
1224 {
1225 rpcl = TRUE;
1226 vpcl = value;
1227 rset = TRUE;
1228
1229 info->target = (bfd_vma) (memaddr & ~3) + value;
1230 }
1231 else if (!(operand->flags & ARC_OPERAND_IR))
1232 {
1233 vpcl = value;
1234 rset = TRUE;
1235 }
1236
886a2506
NC
1237 /* Print the operand as directed by the flags. */
1238 if (operand->flags & ARC_OPERAND_IR)
1239 {
f36e33da
CZ
1240 const char *rname;
1241
886a2506 1242 assert (value >=0 && value < 64);
f36e33da
CZ
1243 rname = arcExtMap_coreRegName (value);
1244 if (!rname)
1245 rname = regnames[value];
1246 (*info->fprintf_func) (info->stream, "%s", rname);
886a2506 1247 if (operand->flags & ARC_OPERAND_TRUNCATE)
f36e33da
CZ
1248 {
1249 rname = arcExtMap_coreRegName (value + 1);
1250 if (!rname)
1251 rname = regnames[value + 1];
1252 (*info->fprintf_func) (info->stream, "%s", rname);
1253 }
50d2740d 1254 if (value == 63)
1255 rpcl = TRUE;
1256 else
1257 rpcl = FALSE;
886a2506
NC
1258 }
1259 else if (operand->flags & ARC_OPERAND_LIMM)
1260 {
4eb6f892 1261 const char *rname = get_auxreg (opcode, value, isa_mask);
db18dbab 1262
f36e33da
CZ
1263 if (rname && open_braket)
1264 (*info->fprintf_func) (info->stream, "%s", rname);
1265 else
1266 {
4eb6f892 1267 (*info->fprintf_func) (info->stream, "%#x", value);
f36e33da
CZ
1268 if (info->insn_type == dis_branch
1269 || info->insn_type == dis_jsr)
4eb6f892 1270 info->target = (bfd_vma) value;
f36e33da 1271 }
886a2506 1272 }
886a2506 1273 else if (operand->flags & ARC_OPERAND_SIGNED)
f36e33da
CZ
1274 {
1275 const char *rname = get_auxreg (opcode, value, isa_mask);
1276 if (rname && open_braket)
1277 (*info->fprintf_func) (info->stream, "%s", rname);
1278 else
fdddd290 1279 {
1280 if (print_hex)
1281 (*info->fprintf_func) (info->stream, "%#x", value);
1282 else
1283 (*info->fprintf_func) (info->stream, "%d", value);
1284 }
f36e33da 1285 }
db18dbab 1286 else if (operand->flags & ARC_OPERAND_ADDRTYPE)
6ec7c1ae
CZ
1287 {
1288 const char *addrtype = get_addrtype (value);
1289 (*info->fprintf_func) (info->stream, "%s", addrtype);
1290 /* A colon follow an address type. */
1291 need_comma = FALSE;
1292 }
886a2506 1293 else
f36e33da
CZ
1294 {
1295 if (operand->flags & ARC_OPERAND_TRUNCATE
1296 && !(operand->flags & ARC_OPERAND_ALIGNED32)
1297 && !(operand->flags & ARC_OPERAND_ALIGNED16)
126124cc
CZ
1298 && value >= 0 && value <= 14)
1299 {
50d2740d 1300 /* Leave/Enter mnemonics. */
126124cc
CZ
1301 switch (value)
1302 {
1303 case 0:
1304 need_comma = FALSE;
1305 break;
1306 case 1:
1307 (*info->fprintf_func) (info->stream, "r13");
1308 break;
1309 default:
1310 (*info->fprintf_func) (info->stream, "r13-%s",
1311 regnames[13 + value - 1]);
1312 break;
1313 }
50d2740d 1314 rpcl = FALSE;
1315 rset = FALSE;
126124cc 1316 }
f36e33da
CZ
1317 else
1318 {
1319 const char *rname = get_auxreg (opcode, value, isa_mask);
1320 if (rname && open_braket)
1321 (*info->fprintf_func) (info->stream, "%s", rname);
1322 else
1323 (*info->fprintf_func) (info->stream, "%#x", value);
1324 }
1325 }
6ec7c1ae
CZ
1326
1327 if (operand->flags & ARC_OPERAND_LIMM)
1328 {
1329 arc_infop->operands[arc_infop->operands_count].kind
1330 = ARC_OPERAND_KIND_LIMM;
1331 /* It is not important to have exactly the LIMM indicator
1332 here. */
1333 arc_infop->operands[arc_infop->operands_count].value = 63;
1334 }
1335 else
1336 {
1337 arc_infop->operands[arc_infop->operands_count].value = value;
1338 arc_infop->operands[arc_infop->operands_count].kind
1339 = (operand->flags & ARC_OPERAND_IR
1340 ? ARC_OPERAND_KIND_REG
1341 : ARC_OPERAND_KIND_SHIMM);
1342 }
1343 arc_infop->operands_count ++;
252b5132 1344 }
279a96ca 1345
50d2740d 1346 /* Pretty print extra info for pc-relative operands. */
1347 if (rpcl && rset)
1348 {
1349 if (info->flags & INSN_HAS_RELOC)
1350 /* If the instruction has a reloc associated with it, then the
1351 offset field in the instruction will actually be the addend
1352 for the reloc. (We are using REL type relocs). In such
1353 cases, we can ignore the pc when computing addresses, since
1354 the addend is not currently pc-relative. */
1355 memaddr = 0;
1356
1357 (*info->fprintf_func) (info->stream, "\t;");
1358 (*info->print_address_func) ((memaddr & ~3) + vpcl, info);
1359 }
1360
4eb6f892 1361 return insn_len;
252b5132
RH
1362}
1363
47b0e7ad 1364
886a2506
NC
1365disassembler_ftype
1366arc_get_disassembler (bfd *abfd)
252b5132 1367{
dce08442
AK
1368 /* BFD my be absent, if opcodes is invoked from the debugger that
1369 has connected to remote target and doesn't have an ELF file. */
1370 if (abfd != NULL)
1371 {
1372 /* Read the extension insns and registers, if any. */
1373 build_ARC_extmap (abfd);
b99747ae 1374#ifdef DEBUG
dce08442 1375 dump_ARC_extmap ();
b99747ae 1376#endif
dce08442 1377 }
252b5132 1378
886a2506 1379 return print_insn_arc;
252b5132
RH
1380}
1381
37fd5ef3
CZ
1382void
1383print_arc_disassembler_options (FILE *stream)
1384{
10045478
AK
1385 int i;
1386
37fd5ef3
CZ
1387 fprintf (stream, _("\n\
1388The following ARC specific disassembler options are supported for use \n\
1389with -M switch (multiple options should be separated by commas):\n"));
1390
10045478
AK
1391 /* cpu=... options. */
1392 for (i = 0; cpu_types[i].name; ++i)
1393 {
1394 /* As of now all value CPU values are less than 16 characters. */
1395 fprintf (stream, " cpu=%-16s\tEnforce %s ISA.\n",
1396 cpu_types[i].name, cpu_types[i].isa);
1397 }
1398
37fd5ef3
CZ
1399 fprintf (stream, _("\
1400 dsp Recognize DSP instructions.\n"));
1401 fprintf (stream, _("\
1402 spfp Recognize FPX SP instructions.\n"));
1403 fprintf (stream, _("\
1404 dpfp Recognize FPX DP instructions.\n"));
1405 fprintf (stream, _("\
1406 quarkse_em Recognize FPU QuarkSE-EM instructions.\n"));
1407 fprintf (stream, _("\
1408 fpuda Recognize double assist FPU instructions.\n"));
1409 fprintf (stream, _("\
1410 fpus Recognize single precision FPU instructions.\n"));
1411 fprintf (stream, _("\
1412 fpud Recognize double precision FPU instructions.\n"));
fdddd290 1413 fprintf (stream, _("\
1414 hex Use only hexadecimal number to print immediates.\n"));
37fd5ef3
CZ
1415}
1416
6ec7c1ae
CZ
1417void arc_insn_decode (bfd_vma addr,
1418 struct disassemble_info *info,
1419 disassembler_ftype disasm_func,
1420 struct arc_instruction *insn)
1421{
1422 const struct arc_opcode *opcode;
1423 struct arc_disassemble_info *arc_infop;
1424
1425 /* Ensure that insn would be in the reset state. */
1426 memset (insn, 0, sizeof (struct arc_instruction));
1427
1428 /* There was an error when disassembling, for example memory read error. */
1429 if (disasm_func (addr, info) < 0)
1430 {
1431 insn->valid = FALSE;
1432 return;
1433 }
1434
1435 assert (info->private_data != NULL);
1436 arc_infop = info->private_data;
1437
1438 insn->length = arc_infop->insn_len;;
1439 insn->address = addr;
1440
1441 /* Quick exit if memory at this address is not an instruction. */
1442 if (info->insn_type == dis_noninsn)
1443 {
1444 insn->valid = FALSE;
1445 return;
1446 }
1447
1448 insn->valid = TRUE;
1449
1450 opcode = (const struct arc_opcode *) arc_infop->opcode;
1451 insn->insn_class = opcode->insn_class;
1452 insn->limm_value = arc_infop->limm;
1453 insn->limm_p = arc_infop->limm_p;
1454
1455 insn->is_control_flow = (info->insn_type == dis_branch
1456 || info->insn_type == dis_condbranch
1457 || info->insn_type == dis_jsr
1458 || info->insn_type == dis_condjsr);
1459
1460 insn->has_delay_slot = info->branch_delay_insns;
1461 insn->writeback_mode
1462 = (enum arc_ldst_writeback_mode) arc_infop->writeback_mode;
1463 insn->data_size_mode = info->data_size;
1464 insn->condition_code = arc_infop->condition_code;
1465 memcpy (insn->operands, arc_infop->operands,
1466 sizeof (struct arc_insn_operand) * MAX_INSN_ARGS);
1467 insn->operands_count = arc_infop->operands_count;
1468}
37fd5ef3 1469
886a2506
NC
1470/* Local variables:
1471 eval: (c-set-style "gnu")
1472 indent-tabs-mode: t
1473 End: */