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