Arc assembler: Convert nps400 from a machine type to an extension.
[deliverable/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 "arc-dis.h"
29 #include "arc-ext.h"
30
31 /* Structure used to iterate over, and extract the values for, operands of
32 an opcode. */
33
34 struct arc_operand_iterator
35 {
36 enum
37 {
38 OPERAND_ITERATOR_STANDARD,
39 OPERAND_ITERATOR_LONG
40 } mode;
41
42 /* The array of 32-bit values that make up this instruction. All
43 required values have been pre-loaded into this array during the
44 find_format call. */
45 unsigned *insn;
46
47 union
48 {
49 struct
50 {
51 /* The opcode this iterator is operating on. */
52 const struct arc_opcode *opcode;
53
54 /* The index into the opcodes operand index list. */
55 const unsigned char *opidx;
56 } standard;
57
58 struct
59 {
60 /* The long instruction opcode this iterator is operating on. */
61 const struct arc_long_opcode *long_opcode;
62
63 /* Two indexes into the opcodes operand index lists. */
64 const unsigned char *opidx_base, *opidx_limm;
65 } long_insn;
66 } state;
67 };
68
69 /* Globals variables. */
70
71 static const char * const regnames[64] =
72 {
73 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
74 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
75 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
76 "r24", "r25", "gp", "fp", "sp", "ilink", "r30", "blink",
77
78 "r32", "r33", "r34", "r35", "r36", "r37", "r38", "r39",
79 "r40", "r41", "r42", "r43", "r44", "r45", "r46", "r47",
80 "r48", "r49", "r50", "r51", "r52", "r53", "r54", "r55",
81 "r56", "r57", "ACCL", "ACCH", "lp_count", "rezerved", "LIMM", "pcl"
82 };
83
84 /* Macros section. */
85
86 #ifdef DEBUG
87 # define pr_debug(fmt, args...) fprintf (stderr, fmt, ##args)
88 #else
89 # define pr_debug(fmt, args...)
90 #endif
91
92 #define ARRANGE_ENDIAN(info, buf) \
93 (info->endian == BFD_ENDIAN_LITTLE ? bfd_getm32 (bfd_getl32 (buf)) \
94 : bfd_getb32 (buf))
95
96 #define BITS(word,s,e) (((word) << (sizeof (word) * 8 - 1 - e)) >> \
97 (s + (sizeof (word) * 8 - 1 - e)))
98 #define OPCODE(word) (BITS ((word), 27, 31))
99
100 #define OPCODE_AC(word) (BITS ((word), 11, 15))
101
102 /* Functions implementation. */
103
104 static bfd_vma
105 bfd_getm32 (unsigned int data)
106 {
107 bfd_vma value = 0;
108
109 value = ((data & 0xff00) | (data & 0xff)) << 16;
110 value |= ((data & 0xff0000) | (data & 0xff000000)) >> 16;
111 return value;
112 }
113
114 static int
115 special_flag_p (const char *opname,
116 const char *flgname)
117 {
118 const struct arc_flag_special *flg_spec;
119 unsigned i, j, flgidx;
120
121 for (i = 0; i < arc_num_flag_special; i++)
122 {
123 flg_spec = &arc_flag_special_cases[i];
124
125 if (strcmp (opname, flg_spec->name))
126 continue;
127
128 /* Found potential special case instruction. */
129 for (j=0;; ++j)
130 {
131 flgidx = flg_spec->flags[j];
132 if (flgidx == 0)
133 break; /* End of the array. */
134
135 if (strcmp (flgname, arc_flag_operands[flgidx].name) == 0)
136 return 1;
137 }
138 }
139 return 0;
140 }
141
142 /* Find opcode from ARC_TABLE given the instruction described by INSN and
143 INSNLEN. The ISA_MASK restricts the possible matches in ARC_TABLE. */
144
145 static const struct arc_opcode *
146 find_format_from_table (const struct arc_opcode *arc_table,
147 unsigned *insn, unsigned int insn_len,
148 unsigned isa_mask, bfd_boolean *has_limm)
149 {
150 unsigned int i = 0;
151 const struct arc_opcode *opcode = NULL;
152 const unsigned char *opidx;
153 const unsigned char *flgidx;
154
155 do {
156 bfd_boolean invalid = FALSE;
157
158 opcode = &arc_table[i++];
159
160 if (ARC_SHORT (opcode->mask) && (insn_len == 2))
161 {
162 if (OPCODE_AC (opcode->opcode) != OPCODE_AC (insn[0]))
163 continue;
164 }
165 else if (!ARC_SHORT (opcode->mask) && (insn_len == 4))
166 {
167 if (OPCODE (opcode->opcode) != OPCODE (insn[0]))
168 continue;
169 }
170 else
171 continue;
172
173 if ((insn[0] ^ opcode->opcode) & opcode->mask)
174 continue;
175
176 if (!(opcode->cpu & isa_mask))
177 continue;
178
179 *has_limm = FALSE;
180
181 /* Possible candidate, check the operands. */
182 for (opidx = opcode->operands; *opidx; opidx++)
183 {
184 int value;
185 const struct arc_operand *operand = &arc_operands[*opidx];
186
187 if (operand->flags & ARC_OPERAND_FAKE)
188 continue;
189
190 if (operand->extract)
191 value = (*operand->extract) (insn[0], &invalid);
192 else
193 value = (insn[0] >> operand->shift) & ((1 << operand->bits) - 1);
194
195 /* Check for LIMM indicator. If it is there, then make sure
196 we pick the right format. */
197 if (operand->flags & ARC_OPERAND_IR
198 && !(operand->flags & ARC_OPERAND_LIMM))
199 {
200 if ((value == 0x3E && insn_len == 4)
201 || (value == 0x1E && insn_len == 2))
202 {
203 invalid = TRUE;
204 break;
205 }
206 }
207
208 if (operand->flags & ARC_OPERAND_LIMM
209 && !(operand->flags & ARC_OPERAND_DUPLICATE))
210 *has_limm = TRUE;
211 }
212
213 /* Check the flags. */
214 for (flgidx = opcode->flags; *flgidx; flgidx++)
215 {
216 /* Get a valid flag class. */
217 const struct arc_flag_class *cl_flags = &arc_flag_classes[*flgidx];
218 const unsigned *flgopridx;
219 int foundA = 0, foundB = 0;
220 unsigned int value;
221
222 /* Check first the extensions. */
223 if (cl_flags->flag_class & F_CLASS_EXTEND)
224 {
225 value = (insn[0] & 0x1F);
226 if (arcExtMap_condCodeName (value))
227 continue;
228 }
229 for (flgopridx = cl_flags->flags; *flgopridx; ++flgopridx)
230 {
231 const struct arc_flag_operand *flg_operand =
232 &arc_flag_operands[*flgopridx];
233
234 value = (insn[0] >> flg_operand->shift)
235 & ((1 << flg_operand->bits) - 1);
236 if (value == flg_operand->code)
237 foundA = 1;
238 if (value)
239 foundB = 1;
240 }
241 if (!foundA && foundB)
242 {
243 invalid = TRUE;
244 break;
245 }
246 }
247
248 if (invalid)
249 continue;
250
251 /* The instruction is valid. */
252 return opcode;
253 } while (opcode->mask);
254
255 return NULL;
256 }
257
258 /* Find long instructions matching values in INSN array. */
259
260 static const struct arc_long_opcode *
261 find_format_long_instructions (unsigned *insn,
262 unsigned int *insn_len,
263 unsigned isa_mask,
264 bfd_vma memaddr,
265 struct disassemble_info *info)
266 {
267 unsigned int i;
268 unsigned limm = 0;
269 bfd_boolean limm_loaded = FALSE;
270
271 for (i = 0; i < arc_num_long_opcodes; ++i)
272 {
273 bfd_byte buffer[4];
274 int status;
275 const struct arc_opcode *opcode;
276
277 opcode = &arc_long_opcodes[i].base_opcode;
278
279 if (ARC_SHORT (opcode->mask) && (*insn_len == 2))
280 {
281 if (OPCODE_AC (opcode->opcode) != OPCODE_AC (insn[0]))
282 continue;
283 }
284 else if (!ARC_SHORT (opcode->mask) && (*insn_len == 4))
285 {
286 if (OPCODE (opcode->opcode) != OPCODE (insn[0]))
287 continue;
288 }
289 else
290 continue;
291
292 if ((insn[0] ^ opcode->opcode) & opcode->mask)
293 continue;
294
295 if (!(opcode->cpu & isa_mask))
296 continue;
297
298 if (!limm_loaded)
299 {
300 status = (*info->read_memory_func) (memaddr + *insn_len, buffer,
301 4, info);
302 if (status != 0)
303 return NULL;
304
305 limm = ARRANGE_ENDIAN (info, buffer);
306 limm_loaded = TRUE;
307 }
308
309 /* Check the second word using the mask and template. */
310 if ((limm & arc_long_opcodes[i].limm_mask)
311 != arc_long_opcodes[i].limm_template)
312 continue;
313
314 (*insn_len) += 4;
315 insn[1] = limm;
316 return &arc_long_opcodes[i];
317 }
318
319 return NULL;
320 }
321
322 /* Find opcode for INSN, trying various different sources. The instruction
323 length in INSN_LEN will be updated if the instruction requires a LIMM
324 extension, and the additional values loaded into the INSN array (which
325 must be big enough).
326
327 A pointer to the opcode is placed into OPCODE_RESULT, and ITER is
328 initialised, ready to iterate over the operands of the found opcode.
329
330 This function returns TRUE in almost all cases, FALSE is reserved to
331 indicate an error (failing to find an opcode is not an error) a
332 returned result of FALSE would indicate that the disassembler can't
333 continue.
334
335 If no matching opcode is found then the returned result will be TRUE,
336 the value placed into OPCODE_RESULT will be NULL, ITER will be
337 undefined, and INSN_LEN will be unchanged.
338
339 If a matching opcode is found, then the returned result will be TRUE,
340 the opcode pointer is placed into OPCODE_RESULT, INSN_LEN will be
341 increased by 4 if the instruction requires a LIMM, and the LIMM value
342 will have been loaded into the INSN[1]. Finally, ITER will have been
343 initialised so that calls to OPERAND_ITERATOR_NEXT will iterate over
344 the opcode's operands. */
345
346 static bfd_boolean
347 find_format (bfd_vma memaddr, unsigned *insn, unsigned int *insn_len,
348 unsigned isa_mask, struct disassemble_info *info,
349 const struct arc_opcode **opcode_result,
350 struct arc_operand_iterator *iter)
351 {
352 const struct arc_opcode *opcode;
353 bfd_boolean needs_limm;
354
355 /* Find the first match in the opcode table. */
356 opcode = find_format_from_table (arc_opcodes, insn, *insn_len,
357 isa_mask, &needs_limm);
358
359 if (opcode == NULL)
360 {
361 const extInstruction_t *einsn;
362
363 /* No instruction found. Try the extensions. */
364 einsn = arcExtMap_insn (OPCODE (insn[0]), insn[0]);
365 if (einsn != NULL)
366 {
367 const char *errmsg = NULL;
368 opcode = arcExtMap_genOpcode (einsn, isa_mask, &errmsg);
369 if (opcode == NULL)
370 {
371 (*info->fprintf_func) (info->stream,
372 "An error occured while "
373 "generating the extension instruction "
374 "operations");
375 *opcode_result = NULL;
376 return FALSE;
377 }
378
379 opcode = find_format_from_table (opcode, insn, *insn_len,
380 isa_mask, &needs_limm);
381 assert (opcode != NULL);
382 }
383 }
384
385 if (needs_limm && opcode != NULL)
386 {
387 bfd_byte buffer[4];
388 int status;
389
390 status = (*info->read_memory_func) (memaddr + *insn_len, buffer,
391 4, info);
392 if (status != 0)
393 {
394 opcode = NULL;
395 }
396 else
397 {
398 insn[1] = ARRANGE_ENDIAN (info, buffer);
399 *insn_len += 4;
400 }
401 }
402
403 if (opcode == NULL)
404 {
405 const struct arc_long_opcode *long_opcode;
406
407 /* No instruction found yet, try the long instructions. */
408 long_opcode =
409 find_format_long_instructions (insn, insn_len, isa_mask,
410 memaddr, info);
411
412 if (long_opcode != NULL)
413 {
414 iter->mode = OPERAND_ITERATOR_LONG;
415 iter->insn = insn;
416 iter->state.long_insn.long_opcode = long_opcode;
417 iter->state.long_insn.opidx_base =
418 long_opcode->base_opcode.operands;
419 iter->state.long_insn.opidx_limm =
420 long_opcode->operands;
421 opcode = &long_opcode->base_opcode;
422 }
423 }
424 else
425 {
426 iter->mode = OPERAND_ITERATOR_STANDARD;
427 iter->insn = insn;
428 iter->state.standard.opcode = opcode;
429 iter->state.standard.opidx = opcode->operands;
430 }
431
432 *opcode_result = opcode;
433 return TRUE;
434 }
435
436 static void
437 print_flags (const struct arc_opcode *opcode,
438 unsigned *insn,
439 struct disassemble_info *info)
440 {
441 const unsigned char *flgidx;
442 unsigned int value;
443
444 /* Now extract and print the flags. */
445 for (flgidx = opcode->flags; *flgidx; flgidx++)
446 {
447 /* Get a valid flag class. */
448 const struct arc_flag_class *cl_flags = &arc_flag_classes[*flgidx];
449 const unsigned *flgopridx;
450
451 /* Check first the extensions. */
452 if (cl_flags->flag_class & F_CLASS_EXTEND)
453 {
454 const char *name;
455 value = (insn[0] & 0x1F);
456
457 name = arcExtMap_condCodeName (value);
458 if (name)
459 {
460 (*info->fprintf_func) (info->stream, ".%s", name);
461 continue;
462 }
463 }
464
465 for (flgopridx = cl_flags->flags; *flgopridx; ++flgopridx)
466 {
467 const struct arc_flag_operand *flg_operand =
468 &arc_flag_operands[*flgopridx];
469
470 if (!flg_operand->favail)
471 continue;
472
473 value = (insn[0] >> flg_operand->shift)
474 & ((1 << flg_operand->bits) - 1);
475 if (value == flg_operand->code)
476 {
477 /* FIXME!: print correctly nt/t flag. */
478 if (!special_flag_p (opcode->name, flg_operand->name))
479 (*info->fprintf_func) (info->stream, ".");
480 else if (info->insn_type == dis_dref)
481 {
482 switch (flg_operand->name[0])
483 {
484 case 'b':
485 info->data_size = 1;
486 break;
487 case 'h':
488 case 'w':
489 info->data_size = 2;
490 break;
491 default:
492 info->data_size = 4;
493 break;
494 }
495 }
496 if (flg_operand->name[0] == 'd'
497 && flg_operand->name[1] == 0)
498 info->branch_delay_insns = 1;
499
500 /* Check if it is a conditional flag. */
501 if (cl_flags->flag_class & F_CLASS_COND)
502 {
503 if (info->insn_type == dis_jsr)
504 info->insn_type = dis_condjsr;
505 else if (info->insn_type == dis_branch)
506 info->insn_type = dis_condbranch;
507 }
508
509 (*info->fprintf_func) (info->stream, "%s", flg_operand->name);
510 }
511 }
512 }
513 }
514
515 static const char *
516 get_auxreg (const struct arc_opcode *opcode,
517 int value,
518 unsigned isa_mask)
519 {
520 const char *name;
521 unsigned int i;
522 const struct arc_aux_reg *auxr = &arc_aux_regs[0];
523
524 if (opcode->insn_class != AUXREG)
525 return NULL;
526
527 name = arcExtMap_auxRegName (value);
528 if (name)
529 return name;
530
531 for (i = 0; i < arc_num_aux_regs; i++, auxr++)
532 {
533 if (!(auxr->cpu & isa_mask))
534 continue;
535
536 if (auxr->subclass != NONE)
537 return NULL;
538
539 if (auxr->address == value)
540 return auxr->name;
541 }
542 return NULL;
543 }
544
545 /* Calculate the instruction length for an instruction starting with MSB
546 and LSB, the most and least significant byte. The ISA_MASK is used to
547 filter the instructions considered to only those that are part of the
548 current architecture.
549
550 The instruction lengths are calculated from the ARC_OPCODE table, and
551 cached for later use. */
552
553 static unsigned int
554 arc_insn_length (bfd_byte msb, bfd_byte lsb, struct disassemble_info *info)
555 {
556 bfd_byte major_opcode = msb >> 3;
557
558 switch (info->mach)
559 {
560 case bfd_mach_arc_arc700:
561 /* The nps400 extension set requires this special casing of the
562 instruction length calculation. Right now this is not causing any
563 problems as none of the known extensions overlap in opcode space,
564 but, if they ever do then we might need to start carrying
565 information around in the elf about which extensions are in use. */
566 if (major_opcode == 0xb)
567 {
568 bfd_byte minor_opcode = lsb & 0x1f;
569
570 if (minor_opcode < 4)
571 return 2;
572 }
573 case bfd_mach_arc_arc600:
574 return (major_opcode > 0xb) ? 2 : 4;
575 break;
576
577 case bfd_mach_arc_arcv2:
578 return (major_opcode > 0x7) ? 2 : 4;
579 break;
580
581 default:
582 abort ();
583 }
584 }
585
586 /* Extract and return the value of OPERAND from the instruction whose value
587 is held in the array INSN. */
588
589 static int
590 extract_operand_value (const struct arc_operand *operand, unsigned *insn)
591 {
592 int value;
593
594 /* Read the limm operand, if required. */
595 if (operand->flags & ARC_OPERAND_LIMM)
596 /* The second part of the instruction value will have been loaded as
597 part of the find_format call made earlier. */
598 value = insn[1];
599 else
600 {
601 if (operand->extract)
602 value = (*operand->extract) (insn[0], (int *) NULL);
603 else
604 {
605 if (operand->flags & ARC_OPERAND_ALIGNED32)
606 {
607 value = (insn[0] >> operand->shift)
608 & ((1 << (operand->bits - 2)) - 1);
609 value = value << 2;
610 }
611 else
612 {
613 value = (insn[0] >> operand->shift) & ((1 << operand->bits) - 1);
614 }
615 if (operand->flags & ARC_OPERAND_SIGNED)
616 {
617 int signbit = 1 << (operand->bits - 1);
618 value = (value ^ signbit) - signbit;
619 }
620 }
621 }
622
623 return value;
624 }
625
626 /* Find the next operand, and the operands value from ITER. Return TRUE if
627 there is another operand, otherwise return FALSE. If there is an
628 operand returned then the operand is placed into OPERAND, and the value
629 into VALUE. If there is no operand returned then OPERAND and VALUE are
630 unchanged. */
631
632 static bfd_boolean
633 operand_iterator_next (struct arc_operand_iterator *iter,
634 const struct arc_operand **operand,
635 int *value)
636 {
637 if (iter->mode == OPERAND_ITERATOR_STANDARD)
638 {
639 if (*iter->state.standard.opidx == 0)
640 {
641 *operand = NULL;
642 return FALSE;
643 }
644
645 *operand = &arc_operands[*iter->state.standard.opidx];
646 *value = extract_operand_value (*operand, iter->insn);
647 iter->state.standard.opidx++;
648 }
649 else
650 {
651 const struct arc_operand *operand_base, *operand_limm;
652 int value_base, value_limm;
653
654 if (*iter->state.long_insn.opidx_limm == 0)
655 {
656 *operand = NULL;
657 return FALSE;
658 }
659
660 operand_base = &arc_operands[*iter->state.long_insn.opidx_base];
661 operand_limm = &arc_operands[*iter->state.long_insn.opidx_limm];
662
663 if (operand_base->flags & ARC_OPERAND_LIMM)
664 {
665 /* We've reached the end of the operand list. */
666 *operand = NULL;
667 return FALSE;
668 }
669
670 value_base = value_limm = 0;
671 if (!(operand_limm->flags & ARC_OPERAND_IGNORE))
672 {
673 /* This should never happen. If it does then the use of
674 extract_operand_value below will access memory beyond
675 the insn array. */
676 assert ((operand_limm->flags & ARC_OPERAND_LIMM) == 0);
677
678 *operand = operand_limm;
679 value_limm = extract_operand_value (*operand, &iter->insn[1]);
680 }
681
682 if (!(operand_base->flags & ARC_OPERAND_IGNORE))
683 {
684 *operand = operand_base;
685 value_base = extract_operand_value (*operand, iter->insn);
686 }
687
688 /* This is a bit of a fudge. There's no reason why simply ORing
689 together the two values is the right thing to do, however, for all
690 the cases we currently have, it is the right thing, so, for now,
691 I've put off solving the more complex problem. */
692 *value = value_base | value_limm;
693
694 iter->state.long_insn.opidx_base++;
695 iter->state.long_insn.opidx_limm++;
696 }
697 return TRUE;
698 }
699
700 /* Disassemble ARC instructions. */
701
702 static int
703 print_insn_arc (bfd_vma memaddr,
704 struct disassemble_info *info)
705 {
706 bfd_byte buffer[4];
707 unsigned int lowbyte, highbyte;
708 int status;
709 unsigned int insn_len;
710 unsigned insn[2] = { 0, 0 };
711 unsigned isa_mask;
712 const struct arc_opcode *opcode;
713 bfd_boolean need_comma;
714 bfd_boolean open_braket;
715 int size;
716 const struct arc_operand *operand;
717 int value;
718 struct arc_operand_iterator iter;
719
720 memset (&iter, 0, sizeof (iter));
721 lowbyte = ((info->endian == BFD_ENDIAN_LITTLE) ? 1 : 0);
722 highbyte = ((info->endian == BFD_ENDIAN_LITTLE) ? 0 : 1);
723
724 switch (info->mach)
725 {
726 case bfd_mach_arc_arc700:
727 isa_mask = ARC_OPCODE_ARC700;
728 break;
729
730 case bfd_mach_arc_arc600:
731 isa_mask = ARC_OPCODE_ARC600;
732 break;
733
734 case bfd_mach_arc_arcv2:
735 default:
736 isa_mask = ARC_OPCODE_ARCv2HS | ARC_OPCODE_ARCv2EM;
737 break;
738 }
739
740 /* This variable may be set by the instruction decoder. It suggests
741 the number of bytes objdump should display on a single line. If
742 the instruction decoder sets this, it should always set it to
743 the same value in order to get reasonable looking output. */
744
745 info->bytes_per_line = 8;
746
747 /* In the next lines, we set two info variables control the way
748 objdump displays the raw data. For example, if bytes_per_line is
749 8 and bytes_per_chunk is 4, the output will look like this:
750 00: 00000000 00000000
751 with the chunks displayed according to "display_endian". */
752
753 if (info->section
754 && !(info->section->flags & SEC_CODE))
755 {
756 /* This is not a CODE section. */
757 switch (info->section->size)
758 {
759 case 1:
760 case 2:
761 case 4:
762 size = info->section->size;
763 break;
764 default:
765 size = (info->section->size & 0x01) ? 1 : 4;
766 break;
767 }
768 info->bytes_per_chunk = 1;
769 info->display_endian = info->endian;
770 }
771 else
772 {
773 size = 2;
774 info->bytes_per_chunk = 2;
775 info->display_endian = info->endian;
776 }
777
778 /* Read the insn into a host word. */
779 status = (*info->read_memory_func) (memaddr, buffer, size, info);
780 if (status != 0)
781 {
782 (*info->memory_error_func) (status, memaddr, info);
783 return -1;
784 }
785
786 if (info->section
787 && !(info->section->flags & SEC_CODE))
788 {
789 /* Data section. */
790 unsigned long data;
791
792 data = bfd_get_bits (buffer, size * 8,
793 info->display_endian == BFD_ENDIAN_BIG);
794 switch (size)
795 {
796 case 1:
797 (*info->fprintf_func) (info->stream, ".byte\t0x%02lx", data);
798 break;
799 case 2:
800 (*info->fprintf_func) (info->stream, ".short\t0x%04lx", data);
801 break;
802 case 4:
803 (*info->fprintf_func) (info->stream, ".word\t0x%08lx", data);
804 break;
805 default:
806 abort ();
807 }
808 return size;
809 }
810
811 insn_len = arc_insn_length (buffer[lowbyte], buffer[highbyte], info);
812 pr_debug ("instruction length = %d bytes\n", insn_len);
813 switch (insn_len)
814 {
815 case 2:
816 insn[0] = (buffer[lowbyte] << 8) | buffer[highbyte];
817 break;
818
819 default:
820 /* An unknown instruction is treated as being length 4. This is
821 possibly not the best solution, but matches the behaviour that was
822 in place before the table based instruction length look-up was
823 introduced. */
824 case 4:
825 /* This is a long instruction: Read the remaning 2 bytes. */
826 status = (*info->read_memory_func) (memaddr + 2, &buffer[2], 2, info);
827 if (status != 0)
828 {
829 (*info->memory_error_func) (status, memaddr + 2, info);
830 return -1;
831 }
832 insn[0] = ARRANGE_ENDIAN (info, buffer);
833 break;
834 }
835
836 /* Set some defaults for the insn info. */
837 info->insn_info_valid = 1;
838 info->branch_delay_insns = 0;
839 info->data_size = 0;
840 info->insn_type = dis_nonbranch;
841 info->target = 0;
842 info->target2 = 0;
843
844 /* FIXME to be moved in dissasemble_init_for_target. */
845 info->disassembler_needs_relocs = TRUE;
846
847 /* Find the first match in the opcode table. */
848 if (!find_format (memaddr, insn, &insn_len, isa_mask, info, &opcode, &iter))
849 return -1;
850
851 if (!opcode)
852 {
853 if (insn_len == 2)
854 (*info->fprintf_func) (info->stream, ".long %#04x", insn[0]);
855 else
856 (*info->fprintf_func) (info->stream, ".long %#08x", insn[0]);
857
858 info->insn_type = dis_noninsn;
859 return insn_len;
860 }
861
862 /* Print the mnemonic. */
863 (*info->fprintf_func) (info->stream, "%s", opcode->name);
864
865 /* Preselect the insn class. */
866 switch (opcode->insn_class)
867 {
868 case BRANCH:
869 case JUMP:
870 if (!strncmp (opcode->name, "bl", 2)
871 || !strncmp (opcode->name, "jl", 2))
872 {
873 if (opcode->subclass == COND)
874 info->insn_type = dis_condjsr;
875 else
876 info->insn_type = dis_jsr;
877 }
878 else
879 {
880 if (opcode->subclass == COND)
881 info->insn_type = dis_condbranch;
882 else
883 info->insn_type = dis_branch;
884 }
885 break;
886 case MEMORY:
887 info->insn_type = dis_dref; /* FIXME! DB indicates mov as memory! */
888 break;
889 default:
890 info->insn_type = dis_nonbranch;
891 break;
892 }
893
894 pr_debug ("%s: 0x%08x\n", opcode->name, opcode->opcode);
895
896 print_flags (opcode, insn, info);
897
898 if (opcode->operands[0] != 0)
899 (*info->fprintf_func) (info->stream, "\t");
900
901 need_comma = FALSE;
902 open_braket = FALSE;
903
904 /* Now extract and print the operands. */
905 operand = NULL;
906 while (operand_iterator_next (&iter, &operand, &value))
907 {
908 if (open_braket && (operand->flags & ARC_OPERAND_BRAKET))
909 {
910 (*info->fprintf_func) (info->stream, "]");
911 open_braket = FALSE;
912 continue;
913 }
914
915 /* Only take input from real operands. */
916 if ((operand->flags & ARC_OPERAND_FAKE)
917 && !(operand->flags & ARC_OPERAND_BRAKET))
918 continue;
919
920 if ((operand->flags & ARC_OPERAND_IGNORE)
921 && (operand->flags & ARC_OPERAND_IR)
922 && value == -1)
923 continue;
924
925 if (need_comma)
926 (*info->fprintf_func) (info->stream, ",");
927
928 if (!open_braket && (operand->flags & ARC_OPERAND_BRAKET))
929 {
930 (*info->fprintf_func) (info->stream, "[");
931 open_braket = TRUE;
932 need_comma = FALSE;
933 continue;
934 }
935
936 /* Print the operand as directed by the flags. */
937 if (operand->flags & ARC_OPERAND_IR)
938 {
939 const char *rname;
940
941 assert (value >=0 && value < 64);
942 rname = arcExtMap_coreRegName (value);
943 if (!rname)
944 rname = regnames[value];
945 (*info->fprintf_func) (info->stream, "%s", rname);
946 if (operand->flags & ARC_OPERAND_TRUNCATE)
947 {
948 rname = arcExtMap_coreRegName (value + 1);
949 if (!rname)
950 rname = regnames[value + 1];
951 (*info->fprintf_func) (info->stream, "%s", rname);
952 }
953 }
954 else if (operand->flags & ARC_OPERAND_LIMM)
955 {
956 const char *rname = get_auxreg (opcode, value, isa_mask);
957 if (rname && open_braket)
958 (*info->fprintf_func) (info->stream, "%s", rname);
959 else
960 {
961 (*info->fprintf_func) (info->stream, "%#x", value);
962 if (info->insn_type == dis_branch
963 || info->insn_type == dis_jsr)
964 info->target = (bfd_vma) value;
965 }
966 }
967 else if (operand->flags & ARC_OPERAND_PCREL)
968 {
969 /* PCL relative. */
970 if (info->flags & INSN_HAS_RELOC)
971 memaddr = 0;
972 (*info->print_address_func) ((memaddr & ~3) + value, info);
973
974 info->target = (bfd_vma) (memaddr & ~3) + value;
975 }
976 else if (operand->flags & ARC_OPERAND_SIGNED)
977 {
978 const char *rname = get_auxreg (opcode, value, isa_mask);
979 if (rname && open_braket)
980 (*info->fprintf_func) (info->stream, "%s", rname);
981 else
982 (*info->fprintf_func) (info->stream, "%d", value);
983 }
984 else
985 {
986 if (operand->flags & ARC_OPERAND_TRUNCATE
987 && !(operand->flags & ARC_OPERAND_ALIGNED32)
988 && !(operand->flags & ARC_OPERAND_ALIGNED16)
989 && value > 0 && value <= 14)
990 (*info->fprintf_func) (info->stream, "r13-%s",
991 regnames[13 + value - 1]);
992 else
993 {
994 const char *rname = get_auxreg (opcode, value, isa_mask);
995 if (rname && open_braket)
996 (*info->fprintf_func) (info->stream, "%s", rname);
997 else
998 (*info->fprintf_func) (info->stream, "%#x", value);
999 }
1000 }
1001
1002 need_comma = TRUE;
1003 }
1004
1005 return insn_len;
1006 }
1007
1008
1009 disassembler_ftype
1010 arc_get_disassembler (bfd *abfd)
1011 {
1012 /* Read the extenssion insns and registers, if any. */
1013 build_ARC_extmap (abfd);
1014 #ifdef DEBUG
1015 dump_ARC_extmap ();
1016 #endif
1017
1018 return print_insn_arc;
1019 }
1020
1021 /* Disassemble ARC instructions. Used by debugger. */
1022
1023 struct arcDisState
1024 arcAnalyzeInstr (bfd_vma memaddr,
1025 struct disassemble_info *info)
1026 {
1027 struct arcDisState ret;
1028 memset (&ret, 0, sizeof (struct arcDisState));
1029
1030 ret.instructionLen = print_insn_arc (memaddr, info);
1031
1032 #if 0
1033 ret.words[0] = insn[0];
1034 ret.words[1] = insn[1];
1035 ret._this = &ret;
1036 ret.coreRegName = _coreRegName;
1037 ret.auxRegName = _auxRegName;
1038 ret.condCodeName = _condCodeName;
1039 ret.instName = _instName;
1040 #endif
1041
1042 return ret;
1043 }
1044
1045 /* Local variables:
1046 eval: (c-set-style "gnu")
1047 indent-tabs-mode: t
1048 End: */
This page took 0.140019 seconds and 5 git commands to generate.