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