[BZ 21005] Add support for Intel 64 rdrand and rdseed record/replay
[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
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;
abe7c33b
CZ
753 case LOAD:
754 case STORE:
bdfe53e3 755 case MEMORY:
abe7c33b 756 insn_type = dis_dref;
bdfe53e3
AB
757 break;
758 default:
759 insn_type = dis_nonbranch;
760 break;
761 }
762
763 return insn_type;
764}
765
886a2506 766/* Disassemble ARC instructions. */
0d2bcfaf 767
886a2506
NC
768static int
769print_insn_arc (bfd_vma memaddr,
770 struct disassemble_info *info)
0d2bcfaf 771{
bdfe53e3
AB
772 bfd_byte buffer[8];
773 unsigned int highbyte, lowbyte;
886a2506 774 int status;
4eb6f892 775 unsigned int insn_len;
bdfe53e3 776 unsigned long long insn = 0;
3f94e60d 777 unsigned isa_mask;
886a2506 778 const struct arc_opcode *opcode;
886a2506
NC
779 bfd_boolean need_comma;
780 bfd_boolean open_braket;
24b368f8 781 int size;
4eb6f892
AB
782 const struct arc_operand *operand;
783 int value;
784 struct arc_operand_iterator iter;
37fd5ef3
CZ
785 Elf_Internal_Ehdr *header = NULL;
786
787 if (info->disassembler_options)
788 {
789 parse_disassembler_options (info->disassembler_options);
790
791 /* Avoid repeated parsing of the options. */
792 info->disassembler_options = NULL;
793 }
0d2bcfaf 794
4eb6f892 795 memset (&iter, 0, sizeof (iter));
90f61cce
GM
796 highbyte = ((info->endian == BFD_ENDIAN_LITTLE) ? 1 : 0);
797 lowbyte = ((info->endian == BFD_ENDIAN_LITTLE) ? 0 : 1);
0d2bcfaf 798
37fd5ef3
CZ
799 if (info->section && info->section->owner)
800 header = elf_elfheader (info->section->owner);
801
886a2506
NC
802 switch (info->mach)
803 {
804 case bfd_mach_arc_arc700:
805 isa_mask = ARC_OPCODE_ARC700;
806 break;
0d2bcfaf 807
886a2506
NC
808 case bfd_mach_arc_arc600:
809 isa_mask = ARC_OPCODE_ARC600;
810 break;
0d2bcfaf 811
886a2506
NC
812 case bfd_mach_arc_arcv2:
813 default:
37fd5ef3 814 isa_mask = ARC_OPCODE_ARCv2EM;
7763838e
CM
815 /* TODO: Perhaps remove defitinion of header since it is only used at
816 this location. */
817 if (header != NULL
818 && (header->e_flags & EF_ARC_MACH_MSK) == EF_ARC_CPU_ARCV2HS)
37fd5ef3
CZ
819 {
820 isa_mask = ARC_OPCODE_ARCv2HS;
821 /* FPU instructions are not extensions for HS. */
822 add_to_decodelist (FLOAT, SP);
823 add_to_decodelist (FLOAT, DP);
824 add_to_decodelist (FLOAT, CVT);
825 }
886a2506 826 break;
0d2bcfaf
NC
827 }
828
24b368f8
CZ
829 /* This variable may be set by the instruction decoder. It suggests
830 the number of bytes objdump should display on a single line. If
831 the instruction decoder sets this, it should always set it to
832 the same value in order to get reasonable looking output. */
833
834 info->bytes_per_line = 8;
835
836 /* In the next lines, we set two info variables control the way
837 objdump displays the raw data. For example, if bytes_per_line is
838 8 and bytes_per_chunk is 4, the output will look like this:
839 00: 00000000 00000000
840 with the chunks displayed according to "display_endian". */
841
842 if (info->section
843 && !(info->section->flags & SEC_CODE))
844 {
845 /* This is not a CODE section. */
846 switch (info->section->size)
847 {
848 case 1:
849 case 2:
850 case 4:
851 size = info->section->size;
852 break;
853 default:
854 size = (info->section->size & 0x01) ? 1 : 4;
855 break;
856 }
857 info->bytes_per_chunk = 1;
858 info->display_endian = info->endian;
859 }
860 else
861 {
862 size = 2;
863 info->bytes_per_chunk = 2;
864 info->display_endian = info->endian;
865 }
866
886a2506 867 /* Read the insn into a host word. */
24b368f8 868 status = (*info->read_memory_func) (memaddr, buffer, size, info);
886a2506 869 if (status != 0)
0d2bcfaf 870 {
886a2506
NC
871 (*info->memory_error_func) (status, memaddr, info);
872 return -1;
0d2bcfaf
NC
873 }
874
886a2506
NC
875 if (info->section
876 && !(info->section->flags & SEC_CODE))
0d2bcfaf 877 {
24b368f8
CZ
878 /* Data section. */
879 unsigned long data;
880
881 data = bfd_get_bits (buffer, size * 8,
882 info->display_endian == BFD_ENDIAN_BIG);
883 switch (size)
0d2bcfaf 884 {
24b368f8
CZ
885 case 1:
886 (*info->fprintf_func) (info->stream, ".byte\t0x%02lx", data);
887 break;
888 case 2:
889 (*info->fprintf_func) (info->stream, ".short\t0x%04lx", data);
890 break;
891 case 4:
892 (*info->fprintf_func) (info->stream, ".word\t0x%08lx", data);
893 break;
894 default:
895 abort ();
0d2bcfaf 896 }
24b368f8 897 return size;
886a2506 898 }
279a96ca 899
90f61cce 900 insn_len = arc_insn_length (buffer[highbyte], buffer[lowbyte], info);
4eb6f892 901 pr_debug ("instruction length = %d bytes\n", insn_len);
37fd5ef3 902
4eb6f892 903 switch (insn_len)
886a2506 904 {
cb040366 905 case 2:
bdfe53e3 906 insn = (buffer[highbyte] << 8) | buffer[lowbyte];
cb040366 907 break;
886a2506 908
cb040366 909 case 4:
bdfe53e3
AB
910 {
911 /* This is a long instruction: Read the remaning 2 bytes. */
912 status = (*info->read_memory_func) (memaddr + 2, &buffer[2], 2, info);
913 if (status != 0)
914 {
915 (*info->memory_error_func) (status, memaddr + 2, info);
916 return -1;
917 }
918 insn = (unsigned long long) ARRANGE_ENDIAN (info, buffer);
919 }
920 break;
921
922 case 6:
923 {
924 status = (*info->read_memory_func) (memaddr + 2, &buffer[2], 4, info);
925 if (status != 0)
926 {
927 (*info->memory_error_func) (status, memaddr + 2, info);
928 return -1;
929 }
930 insn = (unsigned long long) ARRANGE_ENDIAN (info, &buffer[2]);
931 insn |= ((unsigned long long) buffer[highbyte] << 40)
932 | ((unsigned long long) buffer[lowbyte] << 32);
933 }
cb040366 934 break;
bdfe53e3
AB
935
936 case 8:
937 {
938 status = (*info->read_memory_func) (memaddr + 2, &buffer[2], 6, info);
939 if (status != 0)
940 {
941 (*info->memory_error_func) (status, memaddr + 2, info);
942 return -1;
943 }
944 insn =
945 ((((unsigned long long) ARRANGE_ENDIAN (info, buffer)) << 32)
946 | ((unsigned long long) ARRANGE_ENDIAN (info, &buffer[4])));
947 }
948 break;
949
950 default:
951 /* There is no instruction whose length is not 2, 4, 6, or 8. */
952 abort ();
886a2506
NC
953 }
954
bdfe53e3
AB
955 pr_debug ("instruction value = %llx\n", insn);
956
886a2506
NC
957 /* Set some defaults for the insn info. */
958 info->insn_info_valid = 1;
959 info->branch_delay_insns = 0;
960 info->data_size = 0;
961 info->insn_type = dis_nonbranch;
962 info->target = 0;
963 info->target2 = 0;
964
965 /* FIXME to be moved in dissasemble_init_for_target. */
966 info->disassembler_needs_relocs = TRUE;
967
968 /* Find the first match in the opcode table. */
4eb6f892
AB
969 if (!find_format (memaddr, insn, &insn_len, isa_mask, info, &opcode, &iter))
970 return -1;
886a2506 971
b99747ae
CZ
972 if (!opcode)
973 {
bdfe53e3
AB
974 switch (insn_len)
975 {
976 case 2:
977 (*info->fprintf_func) (info->stream, ".long %#04llx",
978 insn & 0xffff);
979 break;
980 case 4:
981 (*info->fprintf_func) (info->stream, ".long %#08llx",
982 insn & 0xffffffff);
983 break;
984 case 6:
985 (*info->fprintf_func) (info->stream, ".long %#08llx",
986 insn & 0xffffffff);
987 (*info->fprintf_func) (info->stream, ".long %#04llx",
988 (insn >> 32) & 0xffff);
989 break;
990 case 8:
991 (*info->fprintf_func) (info->stream, ".long %#08llx",
992 insn & 0xffffffff);
993 (*info->fprintf_func) (info->stream, ".long %#08llx",
994 insn >> 32);
995 break;
996 default:
997 abort ();
998 }
886a2506 999
4eb6f892
AB
1000 info->insn_type = dis_noninsn;
1001 return insn_len;
886a2506 1002 }
279a96ca 1003
886a2506
NC
1004 /* Print the mnemonic. */
1005 (*info->fprintf_func) (info->stream, "%s", opcode->name);
1006
1007 /* Preselect the insn class. */
bdfe53e3 1008 info->insn_type = arc_opcode_to_insn_type (opcode);
279a96ca 1009
bdfe53e3 1010 pr_debug ("%s: 0x%08llx\n", opcode->name, opcode->opcode);
279a96ca 1011
bdfe53e3 1012 print_flags (opcode, &insn, info);
279a96ca 1013
886a2506
NC
1014 if (opcode->operands[0] != 0)
1015 (*info->fprintf_func) (info->stream, "\t");
279a96ca 1016
886a2506
NC
1017 need_comma = FALSE;
1018 open_braket = FALSE;
279a96ca 1019
886a2506 1020 /* Now extract and print the operands. */
4eb6f892
AB
1021 operand = NULL;
1022 while (operand_iterator_next (&iter, &operand, &value))
886a2506 1023 {
886a2506 1024 if (open_braket && (operand->flags & ARC_OPERAND_BRAKET))
0d2bcfaf 1025 {
886a2506
NC
1026 (*info->fprintf_func) (info->stream, "]");
1027 open_braket = FALSE;
1028 continue;
0d2bcfaf 1029 }
279a96ca 1030
886a2506 1031 /* Only take input from real operands. */
db18dbab 1032 if (ARC_OPERAND_IS_FAKE (operand))
886a2506 1033 continue;
279a96ca 1034
4eb6f892
AB
1035 if ((operand->flags & ARC_OPERAND_IGNORE)
1036 && (operand->flags & ARC_OPERAND_IR)
1037 && value == -1)
886a2506 1038 continue;
279a96ca 1039
db18dbab
GM
1040 if (operand->flags & ARC_OPERAND_COLON)
1041 {
1042 (*info->fprintf_func) (info->stream, ":");
1043 continue;
1044 }
1045
886a2506
NC
1046 if (need_comma)
1047 (*info->fprintf_func) (info->stream, ",");
279a96ca 1048
886a2506 1049 if (!open_braket && (operand->flags & ARC_OPERAND_BRAKET))
0d2bcfaf 1050 {
886a2506
NC
1051 (*info->fprintf_func) (info->stream, "[");
1052 open_braket = TRUE;
1053 need_comma = FALSE;
1054 continue;
0d2bcfaf 1055 }
886a2506 1056
db18dbab
GM
1057 need_comma = TRUE;
1058
886a2506
NC
1059 /* Print the operand as directed by the flags. */
1060 if (operand->flags & ARC_OPERAND_IR)
1061 {
f36e33da
CZ
1062 const char *rname;
1063
886a2506 1064 assert (value >=0 && value < 64);
f36e33da
CZ
1065 rname = arcExtMap_coreRegName (value);
1066 if (!rname)
1067 rname = regnames[value];
1068 (*info->fprintf_func) (info->stream, "%s", rname);
886a2506 1069 if (operand->flags & ARC_OPERAND_TRUNCATE)
f36e33da
CZ
1070 {
1071 rname = arcExtMap_coreRegName (value + 1);
1072 if (!rname)
1073 rname = regnames[value + 1];
1074 (*info->fprintf_func) (info->stream, "%s", rname);
1075 }
886a2506
NC
1076 }
1077 else if (operand->flags & ARC_OPERAND_LIMM)
1078 {
4eb6f892 1079 const char *rname = get_auxreg (opcode, value, isa_mask);
db18dbab 1080
f36e33da
CZ
1081 if (rname && open_braket)
1082 (*info->fprintf_func) (info->stream, "%s", rname);
1083 else
1084 {
4eb6f892 1085 (*info->fprintf_func) (info->stream, "%#x", value);
f36e33da
CZ
1086 if (info->insn_type == dis_branch
1087 || info->insn_type == dis_jsr)
4eb6f892 1088 info->target = (bfd_vma) value;
f36e33da 1089 }
886a2506
NC
1090 }
1091 else if (operand->flags & ARC_OPERAND_PCREL)
1092 {
1093 /* PCL relative. */
1094 if (info->flags & INSN_HAS_RELOC)
1095 memaddr = 0;
1096 (*info->print_address_func) ((memaddr & ~3) + value, info);
279a96ca 1097
886a2506
NC
1098 info->target = (bfd_vma) (memaddr & ~3) + value;
1099 }
1100 else if (operand->flags & ARC_OPERAND_SIGNED)
f36e33da
CZ
1101 {
1102 const char *rname = get_auxreg (opcode, value, isa_mask);
1103 if (rname && open_braket)
1104 (*info->fprintf_func) (info->stream, "%s", rname);
1105 else
1106 (*info->fprintf_func) (info->stream, "%d", value);
1107 }
db18dbab
GM
1108 else if (operand->flags & ARC_OPERAND_ADDRTYPE)
1109 {
1110 const char *addrtype = get_addrtype (value);
1111 (*info->fprintf_func) (info->stream, "%s", addrtype);
1112 /* A colon follow an address type. */
1113 need_comma = FALSE;
1114 }
886a2506 1115 else
f36e33da
CZ
1116 {
1117 if (operand->flags & ARC_OPERAND_TRUNCATE
1118 && !(operand->flags & ARC_OPERAND_ALIGNED32)
1119 && !(operand->flags & ARC_OPERAND_ALIGNED16)
1120 && value > 0 && value <= 14)
1121 (*info->fprintf_func) (info->stream, "r13-%s",
1122 regnames[13 + value - 1]);
1123 else
1124 {
1125 const char *rname = get_auxreg (opcode, value, isa_mask);
1126 if (rname && open_braket)
1127 (*info->fprintf_func) (info->stream, "%s", rname);
1128 else
1129 (*info->fprintf_func) (info->stream, "%#x", value);
1130 }
1131 }
252b5132 1132 }
279a96ca 1133
4eb6f892 1134 return insn_len;
252b5132
RH
1135}
1136
47b0e7ad 1137
886a2506
NC
1138disassembler_ftype
1139arc_get_disassembler (bfd *abfd)
252b5132 1140{
dce08442
AK
1141 /* BFD my be absent, if opcodes is invoked from the debugger that
1142 has connected to remote target and doesn't have an ELF file. */
1143 if (abfd != NULL)
1144 {
1145 /* Read the extension insns and registers, if any. */
1146 build_ARC_extmap (abfd);
b99747ae 1147#ifdef DEBUG
dce08442 1148 dump_ARC_extmap ();
b99747ae 1149#endif
dce08442 1150 }
252b5132 1151
886a2506 1152 return print_insn_arc;
252b5132
RH
1153}
1154
886a2506 1155/* Disassemble ARC instructions. Used by debugger. */
47b0e7ad 1156
886a2506
NC
1157struct arcDisState
1158arcAnalyzeInstr (bfd_vma memaddr,
1159 struct disassemble_info *info)
0d2bcfaf 1160{
886a2506
NC
1161 struct arcDisState ret;
1162 memset (&ret, 0, sizeof (struct arcDisState));
1163
1164 ret.instructionLen = print_insn_arc (memaddr, info);
1165
1166#if 0
1167 ret.words[0] = insn[0];
1168 ret.words[1] = insn[1];
1169 ret._this = &ret;
1170 ret.coreRegName = _coreRegName;
1171 ret.auxRegName = _auxRegName;
1172 ret.condCodeName = _condCodeName;
1173 ret.instName = _instName;
1174#endif
47b0e7ad 1175
886a2506 1176 return ret;
0d2bcfaf
NC
1177}
1178
37fd5ef3
CZ
1179void
1180print_arc_disassembler_options (FILE *stream)
1181{
1182 fprintf (stream, _("\n\
1183The following ARC specific disassembler options are supported for use \n\
1184with -M switch (multiple options should be separated by commas):\n"));
1185
1186 fprintf (stream, _("\
1187 dsp Recognize DSP instructions.\n"));
1188 fprintf (stream, _("\
1189 spfp Recognize FPX SP instructions.\n"));
1190 fprintf (stream, _("\
1191 dpfp Recognize FPX DP instructions.\n"));
1192 fprintf (stream, _("\
1193 quarkse_em Recognize FPU QuarkSE-EM instructions.\n"));
1194 fprintf (stream, _("\
1195 fpuda Recognize double assist FPU instructions.\n"));
1196 fprintf (stream, _("\
1197 fpus Recognize single precision FPU instructions.\n"));
1198 fprintf (stream, _("\
1199 fpud Recognize double precision FPU instructions.\n"));
1200}
1201
1202
886a2506
NC
1203/* Local variables:
1204 eval: (c-set-style "gnu")
1205 indent-tabs-mode: t
1206 End: */
This page took 1.476545 seconds and 4 git commands to generate.