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