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