[ARC] Fix disassembler option.
[deliverable/binutils-gdb.git] / opcodes / arc-dis.c
CommitLineData
252b5132 1/* Instruction printing code for the ARC.
6f2750fe 2 Copyright (C) 1994-2016 Free Software Foundation, Inc.
886a2506
NC
3
4 Contributed by Claudiu Zissulescu (claziss@synopsys.com)
252b5132 5
9b201bb5
NC
6 This file is part of libopcodes.
7
8 This library is free software; you can redistribute it and/or modify
0d2bcfaf 9 it under the terms of the GNU General Public License as published by
9b201bb5
NC
10 the Free Software Foundation; either version 3, or (at your option)
11 any later version.
252b5132 12
9b201bb5
NC
13 It is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
16 License for more details.
252b5132 17
0d2bcfaf
NC
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
47b0e7ad
NC
20 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21 MA 02110-1301, USA. */
252b5132 22
5eb3690e 23#include "sysdep.h"
886a2506
NC
24#include <stdio.h>
25#include <assert.h>
252b5132
RH
26#include "dis-asm.h"
27#include "opcode/arc.h"
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
886a2506 54/* Globals variables. */
82b829a7 55
886a2506 56static const char * const regnames[64] =
47b0e7ad 57{
886a2506
NC
58 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
59 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
60 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
61 "r24", "r25", "gp", "fp", "sp", "ilink", "r30", "blink",
62
63 "r32", "r33", "r34", "r35", "r36", "r37", "r38", "r39",
64 "r40", "r41", "r42", "r43", "r44", "r45", "r46", "r47",
65 "r48", "r49", "r50", "r51", "r52", "r53", "r54", "r55",
66 "r56", "r57", "ACCL", "ACCH", "lp_count", "rezerved", "LIMM", "pcl"
67};
68
db18dbab
GM
69static const char * const addrtypenames[ARC_NUM_ADDRTYPES] =
70{
71 "bd", "jid", "lbd", "mbd", "sd", "sm", "xa", "xd",
72 "cd", "cbd", "cjid", "clbd", "cm", "csd", "cxa", "cxd"
73};
74
75static int addrtypenames_max = ARC_NUM_ADDRTYPES - 1;
76
77static const char * const addrtypeunknown = "unknown";
78
37fd5ef3
CZ
79/* This structure keeps track which instruction class(es)
80 should be ignored durring disassembling. */
81
82typedef struct skipclass
83{
84 insn_class_t insn_class;
85 insn_subclass_t subclass;
86 struct skipclass *nxt;
87} skipclass_t, *linkclass;
88
89/* Intial classes of instructions to be consider first when
90 disassembling. */
91static linkclass decodelist = NULL;
92
886a2506
NC
93/* Macros section. */
94
95#ifdef DEBUG
96# define pr_debug(fmt, args...) fprintf (stderr, fmt, ##args)
97#else
98# define pr_debug(fmt, args...)
99#endif
100
101#define ARRANGE_ENDIAN(info, buf) \
102 (info->endian == BFD_ENDIAN_LITTLE ? bfd_getm32 (bfd_getl32 (buf)) \
103 : bfd_getb32 (buf))
104
105#define BITS(word,s,e) (((word) << (sizeof (word) * 8 - 1 - e)) >> \
106 (s + (sizeof (word) * 8 - 1 - e)))
bdfe53e3 107#define OPCODE_32BIT_INSN(word) (BITS ((word), 27, 31))
252b5132 108
886a2506 109/* Functions implementation. */
252b5132 110
37fd5ef3
CZ
111/* Add a new element to the decode list. */
112
113static void
114add_to_decodelist (insn_class_t insn_class,
115 insn_subclass_t subclass)
116{
117 linkclass t = (linkclass) xmalloc (sizeof (skipclass_t));
118
119 t->insn_class = insn_class;
120 t->subclass = subclass;
121 t->nxt = decodelist;
122 decodelist = t;
123}
124
125/* Return TRUE if we need to skip the opcode from being
126 disassembled. */
127
128static bfd_boolean
ee881e5d 129skip_this_opcode (const struct arc_opcode *opcode)
37fd5ef3
CZ
130{
131 linkclass t = decodelist;
37fd5ef3
CZ
132
133 /* Check opcode for major 0x06, return if it is not in. */
bdfe53e3
AB
134 if (arc_opcode_len (opcode) == 4
135 && OPCODE_32BIT_INSN (opcode->opcode) != 0x06)
37fd5ef3
CZ
136 return FALSE;
137
ee881e5d
CZ
138 /* or not a known truble class. */
139 switch (opcode->insn_class)
140 {
141 case FLOAT:
142 case DSP:
143 break;
144 default:
145 return FALSE;
146 }
147
148 while (t != NULL)
37fd5ef3
CZ
149 {
150 if ((t->insn_class == opcode->insn_class)
151 && (t->subclass == opcode->subclass))
ee881e5d 152 return FALSE;
37fd5ef3
CZ
153 t = t->nxt;
154 }
155
ee881e5d 156 return TRUE;
37fd5ef3
CZ
157}
158
886a2506
NC
159static bfd_vma
160bfd_getm32 (unsigned int data)
0d2bcfaf 161{
886a2506 162 bfd_vma value = 0;
0d2bcfaf 163
886a2506
NC
164 value = ((data & 0xff00) | (data & 0xff)) << 16;
165 value |= ((data & 0xff0000) | (data & 0xff000000)) >> 16;
166 return value;
0d2bcfaf
NC
167}
168
37fd5ef3 169static bfd_boolean
886a2506
NC
170special_flag_p (const char *opname,
171 const char *flgname)
0d2bcfaf 172{
886a2506 173 const struct arc_flag_special *flg_spec;
886a2506 174 unsigned i, j, flgidx;
0d2bcfaf 175
886a2506 176 for (i = 0; i < arc_num_flag_special; i++)
252b5132 177 {
886a2506 178 flg_spec = &arc_flag_special_cases[i];
279a96ca 179
24b368f8 180 if (strcmp (opname, flg_spec->name))
886a2506 181 continue;
279a96ca 182
886a2506
NC
183 /* Found potential special case instruction. */
184 for (j=0;; ++j)
0d2bcfaf 185 {
886a2506
NC
186 flgidx = flg_spec->flags[j];
187 if (flgidx == 0)
188 break; /* End of the array. */
0d2bcfaf 189
886a2506 190 if (strcmp (flgname, arc_flag_operands[flgidx].name) == 0)
37fd5ef3 191 return TRUE;
252b5132 192 }
0d2bcfaf 193 }
37fd5ef3 194 return FALSE;
0d2bcfaf 195}
252b5132 196
4eb6f892
AB
197/* Find opcode from ARC_TABLE given the instruction described by INSN and
198 INSNLEN. The ISA_MASK restricts the possible matches in ARC_TABLE. */
199
b99747ae 200static const struct arc_opcode *
37fd5ef3
CZ
201find_format_from_table (struct disassemble_info *info,
202 const struct arc_opcode *arc_table,
bdfe53e3 203 unsigned long long insn,
37fd5ef3
CZ
204 unsigned int insn_len,
205 unsigned isa_mask,
206 bfd_boolean *has_limm,
207 bfd_boolean overlaps)
b99747ae
CZ
208{
209 unsigned int i = 0;
210 const struct arc_opcode *opcode = NULL;
ee881e5d 211 const struct arc_opcode *t_op = NULL;
b99747ae
CZ
212 const unsigned char *opidx;
213 const unsigned char *flgidx;
ee881e5d 214 bfd_boolean warn_p = FALSE;
b99747ae 215
37fd5ef3
CZ
216 do
217 {
218 bfd_boolean invalid = FALSE;
b99747ae 219
37fd5ef3 220 opcode = &arc_table[i++];
b99747ae 221
bdfe53e3 222 if (!(opcode->cpu & isa_mask))
37fd5ef3 223 continue;
b99747ae 224
bdfe53e3 225 if (arc_opcode_len (opcode) != (int) insn_len)
37fd5ef3 226 continue;
b99747ae 227
bdfe53e3 228 if ((insn & opcode->mask) != opcode->opcode)
37fd5ef3 229 continue;
b99747ae 230
37fd5ef3 231 *has_limm = FALSE;
4eb6f892 232
37fd5ef3
CZ
233 /* Possible candidate, check the operands. */
234 for (opidx = opcode->operands; *opidx; opidx++)
235 {
e5b06ef0 236 int value, limmind;
37fd5ef3 237 const struct arc_operand *operand = &arc_operands[*opidx];
b99747ae 238
37fd5ef3
CZ
239 if (operand->flags & ARC_OPERAND_FAKE)
240 continue;
b99747ae 241
37fd5ef3 242 if (operand->extract)
bdfe53e3 243 value = (*operand->extract) (insn, &invalid);
37fd5ef3 244 else
bdfe53e3 245 value = (insn >> operand->shift) & ((1 << operand->bits) - 1);
37fd5ef3
CZ
246
247 /* Check for LIMM indicator. If it is there, then make sure
248 we pick the right format. */
e5b06ef0 249 limmind = (isa_mask & ARC_OPCODE_ARCV2) ? 0x1E : 0x3E;
37fd5ef3
CZ
250 if (operand->flags & ARC_OPERAND_IR
251 && !(operand->flags & ARC_OPERAND_LIMM))
252 {
253 if ((value == 0x3E && insn_len == 4)
e5b06ef0 254 || (value == limmind && insn_len == 2))
37fd5ef3
CZ
255 {
256 invalid = TRUE;
257 break;
258 }
259 }
260
261 if (operand->flags & ARC_OPERAND_LIMM
262 && !(operand->flags & ARC_OPERAND_DUPLICATE))
263 *has_limm = TRUE;
264 }
265
266 /* Check the flags. */
267 for (flgidx = opcode->flags; *flgidx; flgidx++)
268 {
269 /* Get a valid flag class. */
270 const struct arc_flag_class *cl_flags = &arc_flag_classes[*flgidx];
271 const unsigned *flgopridx;
272 int foundA = 0, foundB = 0;
273 unsigned int value;
274
275 /* Check first the extensions. */
276 if (cl_flags->flag_class & F_CLASS_EXTEND)
277 {
bdfe53e3 278 value = (insn & 0x1F);
37fd5ef3
CZ
279 if (arcExtMap_condCodeName (value))
280 continue;
281 }
282
283 for (flgopridx = cl_flags->flags; *flgopridx; ++flgopridx)
284 {
285 const struct arc_flag_operand *flg_operand =
286 &arc_flag_operands[*flgopridx];
287
bdfe53e3 288 value = (insn >> flg_operand->shift)
37fd5ef3
CZ
289 & ((1 << flg_operand->bits) - 1);
290 if (value == flg_operand->code)
291 foundA = 1;
292 if (value)
293 foundB = 1;
294 }
295
296 if (!foundA && foundB)
297 {
298 invalid = TRUE;
299 break;
300 }
301 }
302
303 if (invalid)
304 continue;
305
306 if (insn_len == 4
ee881e5d
CZ
307 && overlaps)
308 {
309 warn_p = TRUE;
310 t_op = opcode;
311 if (skip_this_opcode (opcode))
312 continue;
313 }
37fd5ef3
CZ
314
315 /* The instruction is valid. */
316 return opcode;
317 }
318 while (opcode->mask);
b99747ae 319
ee881e5d
CZ
320 if (warn_p)
321 {
322 info->fprintf_func (info->stream,
323 _("\nWarning: disassembly may be wrong due to "
324 "guessed opcode class choice.\n"
325 "Use -M<class[,class]> to select the correct "
326 "opcode class(es).\n\t\t\t\t"));
327 return t_op;
328 }
329
b99747ae
CZ
330 return NULL;
331}
332
4eb6f892
AB
333/* Find opcode for INSN, trying various different sources. The instruction
334 length in INSN_LEN will be updated if the instruction requires a LIMM
bdfe53e3 335 extension.
4eb6f892
AB
336
337 A pointer to the opcode is placed into OPCODE_RESULT, and ITER is
bdfe53e3
AB
338 initialised, ready to iterate over the operands of the found opcode. If
339 the found opcode requires a LIMM then the LIMM value will be loaded into a
340 field of ITER.
4eb6f892
AB
341
342 This function returns TRUE in almost all cases, FALSE is reserved to
bdfe53e3
AB
343 indicate an error (failing to find an opcode is not an error) a returned
344 result of FALSE would indicate that the disassembler can't continue.
4eb6f892 345
bdfe53e3
AB
346 If no matching opcode is found then the returned result will be TRUE, the
347 value placed into OPCODE_RESULT will be NULL, ITER will be undefined, and
348 INSN_LEN will be unchanged.
4eb6f892 349
bdfe53e3
AB
350 If a matching opcode is found, then the returned result will be TRUE, the
351 opcode pointer is placed into OPCODE_RESULT, INSN_LEN will be increased by
352 4 if the instruction requires a LIMM, and the LIMM value will have been
353 loaded into a field of ITER. Finally, ITER will have been initialised so
354 that calls to OPERAND_ITERATOR_NEXT will iterate over the opcode's
355 operands. */
4eb6f892
AB
356
357static bfd_boolean
37fd5ef3 358find_format (bfd_vma memaddr,
bdfe53e3 359 unsigned long long insn,
37fd5ef3
CZ
360 unsigned int * insn_len,
361 unsigned isa_mask,
362 struct disassemble_info * info,
363 const struct arc_opcode ** opcode_result,
364 struct arc_operand_iterator * iter)
4eb6f892 365{
37fd5ef3 366 const struct arc_opcode *opcode = NULL;
4eb6f892 367 bfd_boolean needs_limm;
f807f43d 368 const extInstruction_t *einsn, *i;
bdfe53e3 369 unsigned limm = 0;
4eb6f892 370
37fd5ef3 371 /* First, try the extension instructions. */
bdfe53e3 372 if (*insn_len == 4)
4eb6f892 373 {
bdfe53e3
AB
374 einsn = arcExtMap_insn (OPCODE_32BIT_INSN (insn), insn);
375 for (i = einsn; (i != NULL) && (opcode == NULL); i = i->next)
4eb6f892 376 {
bdfe53e3
AB
377 const char *errmsg = NULL;
378
379 opcode = arcExtMap_genOpcode (i, isa_mask, &errmsg);
380 if (opcode == NULL)
381 {
382 (*info->fprintf_func) (info->stream, "\
37fd5ef3 383An error occured while generating the extension instruction operations");
bdfe53e3
AB
384 *opcode_result = NULL;
385 return FALSE;
386 }
37fd5ef3 387
bdfe53e3
AB
388 opcode = find_format_from_table (info, opcode, insn, *insn_len,
389 isa_mask, &needs_limm, FALSE);
390 }
4eb6f892
AB
391 }
392
37fd5ef3
CZ
393 /* Then, try finding the first match in the opcode table. */
394 if (opcode == NULL)
395 opcode = find_format_from_table (info, arc_opcodes, insn, *insn_len,
396 isa_mask, &needs_limm, TRUE);
397
4eb6f892
AB
398 if (needs_limm && opcode != NULL)
399 {
400 bfd_byte buffer[4];
401 int status;
402
403 status = (*info->read_memory_func) (memaddr + *insn_len, buffer,
404 4, info);
405 if (status != 0)
406 {
407 opcode = NULL;
408 }
409 else
410 {
bdfe53e3 411 limm = ARRANGE_ENDIAN (info, buffer);
4eb6f892
AB
412 *insn_len += 4;
413 }
414 }
415
bdfe53e3 416 if (opcode != NULL)
4eb6f892 417 {
4eb6f892 418 iter->insn = insn;
bdfe53e3
AB
419 iter->limm = limm;
420 iter->opcode = opcode;
421 iter->opidx = opcode->operands;
4eb6f892
AB
422 }
423
424 *opcode_result = opcode;
425 return TRUE;
426}
427
f36e33da
CZ
428static void
429print_flags (const struct arc_opcode *opcode,
bdfe53e3 430 unsigned long long *insn,
f36e33da
CZ
431 struct disassemble_info *info)
432{
433 const unsigned char *flgidx;
434 unsigned int value;
435
436 /* Now extract and print the flags. */
437 for (flgidx = opcode->flags; *flgidx; flgidx++)
438 {
439 /* Get a valid flag class. */
440 const struct arc_flag_class *cl_flags = &arc_flag_classes[*flgidx];
441 const unsigned *flgopridx;
442
443 /* Check first the extensions. */
c810e0b8 444 if (cl_flags->flag_class & F_CLASS_EXTEND)
f36e33da
CZ
445 {
446 const char *name;
447 value = (insn[0] & 0x1F);
448
449 name = arcExtMap_condCodeName (value);
450 if (name)
451 {
452 (*info->fprintf_func) (info->stream, ".%s", name);
453 continue;
454 }
455 }
456
457 for (flgopridx = cl_flags->flags; *flgopridx; ++flgopridx)
458 {
459 const struct arc_flag_operand *flg_operand =
460 &arc_flag_operands[*flgopridx];
461
462 if (!flg_operand->favail)
463 continue;
464
465 value = (insn[0] >> flg_operand->shift)
466 & ((1 << flg_operand->bits) - 1);
467 if (value == flg_operand->code)
468 {
469 /* FIXME!: print correctly nt/t flag. */
470 if (!special_flag_p (opcode->name, flg_operand->name))
471 (*info->fprintf_func) (info->stream, ".");
472 else if (info->insn_type == dis_dref)
473 {
474 switch (flg_operand->name[0])
475 {
476 case 'b':
477 info->data_size = 1;
478 break;
479 case 'h':
480 case 'w':
481 info->data_size = 2;
482 break;
483 default:
484 info->data_size = 4;
485 break;
486 }
487 }
d9eca1df
CZ
488 if (flg_operand->name[0] == 'd'
489 && flg_operand->name[1] == 0)
490 info->branch_delay_insns = 1;
491
492 /* Check if it is a conditional flag. */
493 if (cl_flags->flag_class & F_CLASS_COND)
494 {
495 if (info->insn_type == dis_jsr)
496 info->insn_type = dis_condjsr;
497 else if (info->insn_type == dis_branch)
498 info->insn_type = dis_condbranch;
499 }
500
f36e33da
CZ
501 (*info->fprintf_func) (info->stream, "%s", flg_operand->name);
502 }
f36e33da
CZ
503 }
504 }
505}
506
507static const char *
508get_auxreg (const struct arc_opcode *opcode,
509 int value,
510 unsigned isa_mask)
511{
512 const char *name;
513 unsigned int i;
514 const struct arc_aux_reg *auxr = &arc_aux_regs[0];
515
c810e0b8 516 if (opcode->insn_class != AUXREG)
f36e33da
CZ
517 return NULL;
518
519 name = arcExtMap_auxRegName (value);
520 if (name)
521 return name;
522
523 for (i = 0; i < arc_num_aux_regs; i++, auxr++)
524 {
525 if (!(auxr->cpu & isa_mask))
526 continue;
527
528 if (auxr->subclass != NONE)
529 return NULL;
530
531 if (auxr->address == value)
532 return auxr->name;
533 }
534 return NULL;
535}
cb040366 536
db18dbab
GM
537/* Convert a value representing an address type to a string used to refer to
538 the address type in assembly code. */
539
540static const char *
541get_addrtype (int value)
542{
543 if (value < 0 || value > addrtypenames_max)
544 return addrtypeunknown;
545
546 return addrtypenames[value];
547}
548
cb040366
AB
549/* Calculate the instruction length for an instruction starting with MSB
550 and LSB, the most and least significant byte. The ISA_MASK is used to
551 filter the instructions considered to only those that are part of the
552 current architecture.
553
554 The instruction lengths are calculated from the ARC_OPCODE table, and
555 cached for later use. */
556
557static unsigned int
4eb6f892 558arc_insn_length (bfd_byte msb, bfd_byte lsb, struct disassemble_info *info)
cb040366
AB
559{
560 bfd_byte major_opcode = msb >> 3;
561
562 switch (info->mach)
563 {
bdd582db
GM
564 case bfd_mach_arc_arc700:
565 /* The nps400 extension set requires this special casing of the
566 instruction length calculation. Right now this is not causing any
567 problems as none of the known extensions overlap in opcode space,
568 but, if they ever do then we might need to start carrying
569 information around in the elf about which extensions are in use. */
4eb6f892
AB
570 if (major_opcode == 0xb)
571 {
572 bfd_byte minor_opcode = lsb & 0x1f;
573
bdfe53e3
AB
574 if (minor_opcode < 4)
575 return 6;
576 else if (minor_opcode == 0x10 || minor_opcode == 0x11)
577 return 8;
4eb6f892 578 }
5a736821
GM
579 if (major_opcode == 0xa)
580 {
581 return 8;
582 }
1a0670f3 583 /* Fall through. */
cb040366
AB
584 case bfd_mach_arc_arc600:
585 return (major_opcode > 0xb) ? 2 : 4;
586 break;
587
588 case bfd_mach_arc_arcv2:
589 return (major_opcode > 0x7) ? 2 : 4;
590 break;
591
592 default:
593 abort ();
594 }
595}
596
4eb6f892
AB
597/* Extract and return the value of OPERAND from the instruction whose value
598 is held in the array INSN. */
599
600static int
bdfe53e3
AB
601extract_operand_value (const struct arc_operand *operand,
602 unsigned long long insn,
603 unsigned limm)
4eb6f892
AB
604{
605 int value;
606
607 /* Read the limm operand, if required. */
608 if (operand->flags & ARC_OPERAND_LIMM)
609 /* The second part of the instruction value will have been loaded as
610 part of the find_format call made earlier. */
bdfe53e3 611 value = limm;
4eb6f892
AB
612 else
613 {
614 if (operand->extract)
bdfe53e3 615 value = (*operand->extract) (insn, (int *) NULL);
4eb6f892
AB
616 else
617 {
618 if (operand->flags & ARC_OPERAND_ALIGNED32)
619 {
bdfe53e3 620 value = (insn >> operand->shift)
4eb6f892
AB
621 & ((1 << (operand->bits - 2)) - 1);
622 value = value << 2;
623 }
624 else
625 {
bdfe53e3 626 value = (insn >> operand->shift) & ((1 << operand->bits) - 1);
4eb6f892
AB
627 }
628 if (operand->flags & ARC_OPERAND_SIGNED)
629 {
630 int signbit = 1 << (operand->bits - 1);
631 value = (value ^ signbit) - signbit;
632 }
633 }
634 }
635
636 return value;
637}
638
639/* Find the next operand, and the operands value from ITER. Return TRUE if
640 there is another operand, otherwise return FALSE. If there is an
641 operand returned then the operand is placed into OPERAND, and the value
642 into VALUE. If there is no operand returned then OPERAND and VALUE are
643 unchanged. */
644
645static bfd_boolean
646operand_iterator_next (struct arc_operand_iterator *iter,
647 const struct arc_operand **operand,
648 int *value)
649{
bdfe53e3 650 if (*iter->opidx == 0)
4eb6f892 651 {
bdfe53e3
AB
652 *operand = NULL;
653 return FALSE;
4eb6f892 654 }
4eb6f892 655
bdfe53e3
AB
656 *operand = &arc_operands[*iter->opidx];
657 *value = extract_operand_value (*operand, iter->insn, iter->limm);
658 iter->opidx++;
4eb6f892 659
4eb6f892
AB
660 return TRUE;
661}
662
37fd5ef3
CZ
663/* Helper for parsing the options. */
664
665static void
666parse_option (char *option)
667{
668 if (CONST_STRNEQ (option, "dsp"))
669 add_to_decodelist (DSP, NONE);
670
671 else if (CONST_STRNEQ (option, "spfp"))
672 add_to_decodelist (FLOAT, SPX);
673
674 else if (CONST_STRNEQ (option, "dpfp"))
675 add_to_decodelist (FLOAT, DPX);
676
677 else if (CONST_STRNEQ (option, "quarkse_em"))
ee881e5d
CZ
678 {
679 add_to_decodelist (FLOAT, DPX);
680 add_to_decodelist (FLOAT, SPX);
681 add_to_decodelist (FLOAT, QUARKSE);
682 }
37fd5ef3
CZ
683
684 else if (CONST_STRNEQ (option, "fpuda"))
685 add_to_decodelist (FLOAT, DPA);
686
ee881e5d 687 else if (CONST_STRNEQ (option, "fpus"))
37fd5ef3
CZ
688 {
689 add_to_decodelist (FLOAT, SP);
690 add_to_decodelist (FLOAT, CVT);
691 }
692
ee881e5d 693 else if (CONST_STRNEQ (option, "fpud"))
37fd5ef3
CZ
694 {
695 add_to_decodelist (FLOAT, DP);
696 add_to_decodelist (FLOAT, CVT);
697 }
698 else
699 fprintf (stderr, _("Unrecognised disassembler option: %s\n"), option);
700}
701
702/* Go over the options list and parse it. */
703
704static void
705parse_disassembler_options (char *options)
706{
707 if (options == NULL)
708 return;
709
710 while (*options)
711 {
712 /* Skip empty options. */
713 if (*options == ',')
714 {
715 ++ options;
716 continue;
717 }
718
719 parse_option (options);
720
721 while (*options != ',' && *options != '\0')
722 ++ options;
723 }
724}
725
bdfe53e3
AB
726/* Return the instruction type for an instruction described by OPCODE. */
727
728static enum dis_insn_type
729arc_opcode_to_insn_type (const struct arc_opcode *opcode)
730{
731 enum dis_insn_type insn_type;
732
733 switch (opcode->insn_class)
734 {
735 case BRANCH:
736 case JUMP:
737 if (!strncmp (opcode->name, "bl", 2)
738 || !strncmp (opcode->name, "jl", 2))
739 {
740 if (opcode->subclass == COND)
741 insn_type = dis_condjsr;
742 else
743 insn_type = dis_jsr;
744 }
745 else
746 {
747 if (opcode->subclass == COND)
748 insn_type = dis_condbranch;
749 else
750 insn_type = dis_branch;
751 }
752 break;
753 case MEMORY:
754 insn_type = dis_dref; /* FIXME! DB indicates mov as memory! */
755 break;
756 default:
757 insn_type = dis_nonbranch;
758 break;
759 }
760
761 return insn_type;
762}
763
886a2506 764/* Disassemble ARC instructions. */
0d2bcfaf 765
886a2506
NC
766static int
767print_insn_arc (bfd_vma memaddr,
768 struct disassemble_info *info)
0d2bcfaf 769{
bdfe53e3
AB
770 bfd_byte buffer[8];
771 unsigned int highbyte, lowbyte;
886a2506 772 int status;
4eb6f892 773 unsigned int insn_len;
bdfe53e3 774 unsigned long long insn = 0;
3f94e60d 775 unsigned isa_mask;
886a2506 776 const struct arc_opcode *opcode;
886a2506
NC
777 bfd_boolean need_comma;
778 bfd_boolean open_braket;
24b368f8 779 int size;
4eb6f892
AB
780 const struct arc_operand *operand;
781 int value;
782 struct arc_operand_iterator iter;
37fd5ef3
CZ
783 Elf_Internal_Ehdr *header = NULL;
784
785 if (info->disassembler_options)
786 {
787 parse_disassembler_options (info->disassembler_options);
788
789 /* Avoid repeated parsing of the options. */
790 info->disassembler_options = NULL;
791 }
0d2bcfaf 792
4eb6f892 793 memset (&iter, 0, sizeof (iter));
90f61cce
GM
794 highbyte = ((info->endian == BFD_ENDIAN_LITTLE) ? 1 : 0);
795 lowbyte = ((info->endian == BFD_ENDIAN_LITTLE) ? 0 : 1);
0d2bcfaf 796
37fd5ef3
CZ
797 if (info->section && info->section->owner)
798 header = elf_elfheader (info->section->owner);
799
886a2506
NC
800 switch (info->mach)
801 {
802 case bfd_mach_arc_arc700:
803 isa_mask = ARC_OPCODE_ARC700;
804 break;
0d2bcfaf 805
886a2506
NC
806 case bfd_mach_arc_arc600:
807 isa_mask = ARC_OPCODE_ARC600;
808 break;
0d2bcfaf 809
886a2506
NC
810 case bfd_mach_arc_arcv2:
811 default:
37fd5ef3 812 isa_mask = ARC_OPCODE_ARCv2EM;
7763838e
CM
813 /* TODO: Perhaps remove defitinion of header since it is only used at
814 this location. */
815 if (header != NULL
816 && (header->e_flags & EF_ARC_MACH_MSK) == EF_ARC_CPU_ARCV2HS)
37fd5ef3
CZ
817 {
818 isa_mask = ARC_OPCODE_ARCv2HS;
819 /* FPU instructions are not extensions for HS. */
820 add_to_decodelist (FLOAT, SP);
821 add_to_decodelist (FLOAT, DP);
822 add_to_decodelist (FLOAT, CVT);
823 }
886a2506 824 break;
0d2bcfaf
NC
825 }
826
24b368f8
CZ
827 /* This variable may be set by the instruction decoder. It suggests
828 the number of bytes objdump should display on a single line. If
829 the instruction decoder sets this, it should always set it to
830 the same value in order to get reasonable looking output. */
831
832 info->bytes_per_line = 8;
833
834 /* In the next lines, we set two info variables control the way
835 objdump displays the raw data. For example, if bytes_per_line is
836 8 and bytes_per_chunk is 4, the output will look like this:
837 00: 00000000 00000000
838 with the chunks displayed according to "display_endian". */
839
840 if (info->section
841 && !(info->section->flags & SEC_CODE))
842 {
843 /* This is not a CODE section. */
844 switch (info->section->size)
845 {
846 case 1:
847 case 2:
848 case 4:
849 size = info->section->size;
850 break;
851 default:
852 size = (info->section->size & 0x01) ? 1 : 4;
853 break;
854 }
855 info->bytes_per_chunk = 1;
856 info->display_endian = info->endian;
857 }
858 else
859 {
860 size = 2;
861 info->bytes_per_chunk = 2;
862 info->display_endian = info->endian;
863 }
864
886a2506 865 /* Read the insn into a host word. */
24b368f8 866 status = (*info->read_memory_func) (memaddr, buffer, size, info);
886a2506 867 if (status != 0)
0d2bcfaf 868 {
886a2506
NC
869 (*info->memory_error_func) (status, memaddr, info);
870 return -1;
0d2bcfaf
NC
871 }
872
886a2506
NC
873 if (info->section
874 && !(info->section->flags & SEC_CODE))
0d2bcfaf 875 {
24b368f8
CZ
876 /* Data section. */
877 unsigned long data;
878
879 data = bfd_get_bits (buffer, size * 8,
880 info->display_endian == BFD_ENDIAN_BIG);
881 switch (size)
0d2bcfaf 882 {
24b368f8
CZ
883 case 1:
884 (*info->fprintf_func) (info->stream, ".byte\t0x%02lx", data);
885 break;
886 case 2:
887 (*info->fprintf_func) (info->stream, ".short\t0x%04lx", data);
888 break;
889 case 4:
890 (*info->fprintf_func) (info->stream, ".word\t0x%08lx", data);
891 break;
892 default:
893 abort ();
0d2bcfaf 894 }
24b368f8 895 return size;
886a2506 896 }
279a96ca 897
90f61cce 898 insn_len = arc_insn_length (buffer[highbyte], buffer[lowbyte], info);
4eb6f892 899 pr_debug ("instruction length = %d bytes\n", insn_len);
37fd5ef3 900
4eb6f892 901 switch (insn_len)
886a2506 902 {
cb040366 903 case 2:
bdfe53e3 904 insn = (buffer[highbyte] << 8) | buffer[lowbyte];
cb040366 905 break;
886a2506 906
cb040366 907 case 4:
bdfe53e3
AB
908 {
909 /* This is a long instruction: Read the remaning 2 bytes. */
910 status = (*info->read_memory_func) (memaddr + 2, &buffer[2], 2, info);
911 if (status != 0)
912 {
913 (*info->memory_error_func) (status, memaddr + 2, info);
914 return -1;
915 }
916 insn = (unsigned long long) ARRANGE_ENDIAN (info, buffer);
917 }
918 break;
919
920 case 6:
921 {
922 status = (*info->read_memory_func) (memaddr + 2, &buffer[2], 4, info);
923 if (status != 0)
924 {
925 (*info->memory_error_func) (status, memaddr + 2, info);
926 return -1;
927 }
928 insn = (unsigned long long) ARRANGE_ENDIAN (info, &buffer[2]);
929 insn |= ((unsigned long long) buffer[highbyte] << 40)
930 | ((unsigned long long) buffer[lowbyte] << 32);
931 }
cb040366 932 break;
bdfe53e3
AB
933
934 case 8:
935 {
936 status = (*info->read_memory_func) (memaddr + 2, &buffer[2], 6, info);
937 if (status != 0)
938 {
939 (*info->memory_error_func) (status, memaddr + 2, info);
940 return -1;
941 }
942 insn =
943 ((((unsigned long long) ARRANGE_ENDIAN (info, buffer)) << 32)
944 | ((unsigned long long) ARRANGE_ENDIAN (info, &buffer[4])));
945 }
946 break;
947
948 default:
949 /* There is no instruction whose length is not 2, 4, 6, or 8. */
950 abort ();
886a2506
NC
951 }
952
bdfe53e3
AB
953 pr_debug ("instruction value = %llx\n", insn);
954
886a2506
NC
955 /* Set some defaults for the insn info. */
956 info->insn_info_valid = 1;
957 info->branch_delay_insns = 0;
958 info->data_size = 0;
959 info->insn_type = dis_nonbranch;
960 info->target = 0;
961 info->target2 = 0;
962
963 /* FIXME to be moved in dissasemble_init_for_target. */
964 info->disassembler_needs_relocs = TRUE;
965
966 /* Find the first match in the opcode table. */
4eb6f892
AB
967 if (!find_format (memaddr, insn, &insn_len, isa_mask, info, &opcode, &iter))
968 return -1;
886a2506 969
b99747ae
CZ
970 if (!opcode)
971 {
bdfe53e3
AB
972 switch (insn_len)
973 {
974 case 2:
975 (*info->fprintf_func) (info->stream, ".long %#04llx",
976 insn & 0xffff);
977 break;
978 case 4:
979 (*info->fprintf_func) (info->stream, ".long %#08llx",
980 insn & 0xffffffff);
981 break;
982 case 6:
983 (*info->fprintf_func) (info->stream, ".long %#08llx",
984 insn & 0xffffffff);
985 (*info->fprintf_func) (info->stream, ".long %#04llx",
986 (insn >> 32) & 0xffff);
987 break;
988 case 8:
989 (*info->fprintf_func) (info->stream, ".long %#08llx",
990 insn & 0xffffffff);
991 (*info->fprintf_func) (info->stream, ".long %#08llx",
992 insn >> 32);
993 break;
994 default:
995 abort ();
996 }
886a2506 997
4eb6f892
AB
998 info->insn_type = dis_noninsn;
999 return insn_len;
886a2506 1000 }
279a96ca 1001
886a2506
NC
1002 /* Print the mnemonic. */
1003 (*info->fprintf_func) (info->stream, "%s", opcode->name);
1004
1005 /* Preselect the insn class. */
bdfe53e3 1006 info->insn_type = arc_opcode_to_insn_type (opcode);
279a96ca 1007
bdfe53e3 1008 pr_debug ("%s: 0x%08llx\n", opcode->name, opcode->opcode);
279a96ca 1009
bdfe53e3 1010 print_flags (opcode, &insn, info);
279a96ca 1011
886a2506
NC
1012 if (opcode->operands[0] != 0)
1013 (*info->fprintf_func) (info->stream, "\t");
279a96ca 1014
886a2506
NC
1015 need_comma = FALSE;
1016 open_braket = FALSE;
279a96ca 1017
886a2506 1018 /* Now extract and print the operands. */
4eb6f892
AB
1019 operand = NULL;
1020 while (operand_iterator_next (&iter, &operand, &value))
886a2506 1021 {
886a2506 1022 if (open_braket && (operand->flags & ARC_OPERAND_BRAKET))
0d2bcfaf 1023 {
886a2506
NC
1024 (*info->fprintf_func) (info->stream, "]");
1025 open_braket = FALSE;
1026 continue;
0d2bcfaf 1027 }
279a96ca 1028
886a2506 1029 /* Only take input from real operands. */
db18dbab 1030 if (ARC_OPERAND_IS_FAKE (operand))
886a2506 1031 continue;
279a96ca 1032
4eb6f892
AB
1033 if ((operand->flags & ARC_OPERAND_IGNORE)
1034 && (operand->flags & ARC_OPERAND_IR)
1035 && value == -1)
886a2506 1036 continue;
279a96ca 1037
db18dbab
GM
1038 if (operand->flags & ARC_OPERAND_COLON)
1039 {
1040 (*info->fprintf_func) (info->stream, ":");
1041 continue;
1042 }
1043
886a2506
NC
1044 if (need_comma)
1045 (*info->fprintf_func) (info->stream, ",");
279a96ca 1046
886a2506 1047 if (!open_braket && (operand->flags & ARC_OPERAND_BRAKET))
0d2bcfaf 1048 {
886a2506
NC
1049 (*info->fprintf_func) (info->stream, "[");
1050 open_braket = TRUE;
1051 need_comma = FALSE;
1052 continue;
0d2bcfaf 1053 }
886a2506 1054
db18dbab
GM
1055 need_comma = TRUE;
1056
886a2506
NC
1057 /* Print the operand as directed by the flags. */
1058 if (operand->flags & ARC_OPERAND_IR)
1059 {
f36e33da
CZ
1060 const char *rname;
1061
886a2506 1062 assert (value >=0 && value < 64);
f36e33da
CZ
1063 rname = arcExtMap_coreRegName (value);
1064 if (!rname)
1065 rname = regnames[value];
1066 (*info->fprintf_func) (info->stream, "%s", rname);
886a2506 1067 if (operand->flags & ARC_OPERAND_TRUNCATE)
f36e33da
CZ
1068 {
1069 rname = arcExtMap_coreRegName (value + 1);
1070 if (!rname)
1071 rname = regnames[value + 1];
1072 (*info->fprintf_func) (info->stream, "%s", rname);
1073 }
886a2506
NC
1074 }
1075 else if (operand->flags & ARC_OPERAND_LIMM)
1076 {
4eb6f892 1077 const char *rname = get_auxreg (opcode, value, isa_mask);
db18dbab 1078
f36e33da
CZ
1079 if (rname && open_braket)
1080 (*info->fprintf_func) (info->stream, "%s", rname);
1081 else
1082 {
4eb6f892 1083 (*info->fprintf_func) (info->stream, "%#x", value);
f36e33da
CZ
1084 if (info->insn_type == dis_branch
1085 || info->insn_type == dis_jsr)
4eb6f892 1086 info->target = (bfd_vma) value;
f36e33da 1087 }
886a2506
NC
1088 }
1089 else if (operand->flags & ARC_OPERAND_PCREL)
1090 {
1091 /* PCL relative. */
1092 if (info->flags & INSN_HAS_RELOC)
1093 memaddr = 0;
1094 (*info->print_address_func) ((memaddr & ~3) + value, info);
279a96ca 1095
886a2506
NC
1096 info->target = (bfd_vma) (memaddr & ~3) + value;
1097 }
1098 else if (operand->flags & ARC_OPERAND_SIGNED)
f36e33da
CZ
1099 {
1100 const char *rname = get_auxreg (opcode, value, isa_mask);
1101 if (rname && open_braket)
1102 (*info->fprintf_func) (info->stream, "%s", rname);
1103 else
1104 (*info->fprintf_func) (info->stream, "%d", value);
1105 }
db18dbab
GM
1106 else if (operand->flags & ARC_OPERAND_ADDRTYPE)
1107 {
1108 const char *addrtype = get_addrtype (value);
1109 (*info->fprintf_func) (info->stream, "%s", addrtype);
1110 /* A colon follow an address type. */
1111 need_comma = FALSE;
1112 }
886a2506 1113 else
f36e33da
CZ
1114 {
1115 if (operand->flags & ARC_OPERAND_TRUNCATE
1116 && !(operand->flags & ARC_OPERAND_ALIGNED32)
1117 && !(operand->flags & ARC_OPERAND_ALIGNED16)
1118 && value > 0 && value <= 14)
1119 (*info->fprintf_func) (info->stream, "r13-%s",
1120 regnames[13 + value - 1]);
1121 else
1122 {
1123 const char *rname = get_auxreg (opcode, value, isa_mask);
1124 if (rname && open_braket)
1125 (*info->fprintf_func) (info->stream, "%s", rname);
1126 else
1127 (*info->fprintf_func) (info->stream, "%#x", value);
1128 }
1129 }
252b5132 1130 }
279a96ca 1131
4eb6f892 1132 return insn_len;
252b5132
RH
1133}
1134
47b0e7ad 1135
886a2506
NC
1136disassembler_ftype
1137arc_get_disassembler (bfd *abfd)
252b5132 1138{
dce08442
AK
1139 /* BFD my be absent, if opcodes is invoked from the debugger that
1140 has connected to remote target and doesn't have an ELF file. */
1141 if (abfd != NULL)
1142 {
1143 /* Read the extension insns and registers, if any. */
1144 build_ARC_extmap (abfd);
b99747ae 1145#ifdef DEBUG
dce08442 1146 dump_ARC_extmap ();
b99747ae 1147#endif
dce08442 1148 }
252b5132 1149
886a2506 1150 return print_insn_arc;
252b5132
RH
1151}
1152
886a2506 1153/* Disassemble ARC instructions. Used by debugger. */
47b0e7ad 1154
886a2506
NC
1155struct arcDisState
1156arcAnalyzeInstr (bfd_vma memaddr,
1157 struct disassemble_info *info)
0d2bcfaf 1158{
886a2506
NC
1159 struct arcDisState ret;
1160 memset (&ret, 0, sizeof (struct arcDisState));
1161
1162 ret.instructionLen = print_insn_arc (memaddr, info);
1163
1164#if 0
1165 ret.words[0] = insn[0];
1166 ret.words[1] = insn[1];
1167 ret._this = &ret;
1168 ret.coreRegName = _coreRegName;
1169 ret.auxRegName = _auxRegName;
1170 ret.condCodeName = _condCodeName;
1171 ret.instName = _instName;
1172#endif
47b0e7ad 1173
886a2506 1174 return ret;
0d2bcfaf
NC
1175}
1176
37fd5ef3
CZ
1177void
1178print_arc_disassembler_options (FILE *stream)
1179{
1180 fprintf (stream, _("\n\
1181The following ARC specific disassembler options are supported for use \n\
1182with -M switch (multiple options should be separated by commas):\n"));
1183
1184 fprintf (stream, _("\
1185 dsp Recognize DSP instructions.\n"));
1186 fprintf (stream, _("\
1187 spfp Recognize FPX SP instructions.\n"));
1188 fprintf (stream, _("\
1189 dpfp Recognize FPX DP instructions.\n"));
1190 fprintf (stream, _("\
1191 quarkse_em Recognize FPU QuarkSE-EM instructions.\n"));
1192 fprintf (stream, _("\
1193 fpuda Recognize double assist FPU instructions.\n"));
1194 fprintf (stream, _("\
1195 fpus Recognize single precision FPU instructions.\n"));
1196 fprintf (stream, _("\
1197 fpud Recognize double precision FPU instructions.\n"));
1198}
1199
1200
886a2506
NC
1201/* Local variables:
1202 eval: (c-set-style "gnu")
1203 indent-tabs-mode: t
1204 End: */
This page took 1.012934 seconds and 4 git commands to generate.