source: branches/libc-0.6/src/binutils/opcodes/arc-dis.c

Last change on this file was 610, checked in by bird, 22 years ago

This commit was generated by cvs2svn to compensate for changes in r609,
which included commits to RCS files with non-trunk default branches.

  • Property cvs2svn:cvs-rev set to 1.1.1.2
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 28.5 KB
Line 
1/* Instruction printing code for the ARC.
2 Copyright 1994, 1995, 1997, 1998, 2000, 2001, 2002
3 Free Software Foundation, Inc.
4 Contributed by Doug Evans (dje@cygnus.com).
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
19
20#include "ansidecl.h"
21#include "libiberty.h"
22#include "dis-asm.h"
23#include "opcode/arc.h"
24#include "elf-bfd.h"
25#include "elf/arc.h"
26#include <string.h>
27#include "opintl.h"
28
29#include <stdarg.h>
30#include "arc-dis.h"
31#include "arc-ext.h"
32
33#ifndef dbg
34#define dbg (0)
35#endif
36
37#define BIT(word,n) ((word) & (1 << n))
38#define BITS(word,s,e) (((word) << (31 - e)) >> (s + (31 - e)))
39#define OPCODE(word) (BITS ((word), 27, 31))
40#define FIELDA(word) (BITS ((word), 21, 26))
41#define FIELDB(word) (BITS ((word), 15, 20))
42#define FIELDC(word) (BITS ((word), 9, 14))
43
44/* FIELD D is signed in all of its uses, so we make sure argument is
45 treated as signed for bit shifting purposes: */
46#define FIELDD(word) (BITS (((signed int)word), 0, 8))
47
48#define PUT_NEXT_WORD_IN(a) \
49 do \
50 { \
51 if (is_limm == 1 && !NEXT_WORD (1)) \
52 mwerror (state, _("Illegal limm reference in last instruction!\n")); \
53 a = state->words[1]; \
54 } \
55 while (0)
56
57#define CHECK_FLAG_COND_NULLIFY() \
58 do \
59 { \
60 if (is_shimm == 0) \
61 { \
62 flag = BIT (state->words[0], 8); \
63 state->nullifyMode = BITS (state->words[0], 5, 6); \
64 cond = BITS (state->words[0], 0, 4); \
65 } \
66 } \
67 while (0)
68
69#define CHECK_COND() \
70 do \
71 { \
72 if (is_shimm == 0) \
73 cond = BITS (state->words[0], 0, 4); \
74 } \
75 while (0)
76
77#define CHECK_FIELD(field) \
78 do \
79 { \
80 if (field == 62) \
81 { \
82 is_limm++; \
83 field##isReg = 0; \
84 PUT_NEXT_WORD_IN (field); \
85 limm_value = field; \
86 } \
87 else if (field > 60) \
88 { \
89 field##isReg = 0; \
90 is_shimm++; \
91 flag = (field == 61); \
92 field = FIELDD (state->words[0]); \
93 } \
94 } \
95 while (0)
96
97#define CHECK_FIELD_A() \
98 do \
99 { \
100 fieldA = FIELDA (state->words[0]); \
101 if (fieldA > 60) \
102 { \
103 fieldAisReg = 0; \
104 fieldA = 0; \
105 } \
106 } \
107 while (0)
108
109#define CHECK_FIELD_B() \
110 do \
111 { \
112 fieldB = FIELDB (state->words[0]); \
113 CHECK_FIELD (fieldB); \
114 } \
115 while (0)
116
117#define CHECK_FIELD_C() \
118 do \
119 { \
120 fieldC = FIELDC (state->words[0]); \
121 CHECK_FIELD (fieldC); \
122 } \
123 while (0)
124
125#define IS_SMALL(x) (((field##x) < 256) && ((field##x) > -257))
126#define IS_REG(x) (field##x##isReg)
127#define WRITE_FORMAT_LB_Rx_RB(x) WRITE_FORMAT(x,"[","]","","")
128#define WRITE_FORMAT_x_COMMA_LB(x) WRITE_FORMAT(x,"",",[","",",[")
129#define WRITE_FORMAT_COMMA_x_RB(x) WRITE_FORMAT(x,",","]",",","]")
130#define WRITE_FORMAT_x_RB(x) WRITE_FORMAT(x,"","]","","]")
131#define WRITE_FORMAT_COMMA_x(x) WRITE_FORMAT(x,",","",",","")
132#define WRITE_FORMAT_x_COMMA(x) WRITE_FORMAT(x,"",",","",",")
133#define WRITE_FORMAT_x(x) WRITE_FORMAT(x,"","","","")
134#define WRITE_FORMAT(x,cb1,ca1,cb,ca) strcat (formatString, \
135 (IS_REG (x) ? cb1"%r"ca1 : \
136 usesAuxReg ? cb"%a"ca : \
137 IS_SMALL (x) ? cb"%d"ca : cb"%h"ca))
138#define WRITE_FORMAT_RB() strcat (formatString, "]")
139#define WRITE_COMMENT(str) (state->comm[state->commNum++] = (str))
140#define WRITE_NOP_COMMENT() if (!fieldAisReg && !flag) WRITE_COMMENT ("nop");
141
142#define NEXT_WORD(x) (offset += 4, state->words[x])
143
144#define add_target(x) (state->targets[state->tcnt++] = (x))
145
146static char comment_prefix[] = "\t; ";
147
148static const char *core_reg_name PARAMS ((struct arcDisState *, int));
149static const char *aux_reg_name PARAMS ((struct arcDisState *, int));
150static const char *cond_code_name PARAMS ((struct arcDisState *, int));
151static const char *instruction_name
152 PARAMS ((struct arcDisState *, int, int, int *));
153static void mwerror PARAMS ((struct arcDisState *, const char *));
154static const char *post_address PARAMS ((struct arcDisState *, int));
155static void write_comments_
156 PARAMS ((struct arcDisState *, int, int, long int));
157static void write_instr_name_
158 PARAMS ((struct arcDisState *, const char *, int, int, int, int, int, int));
159static int dsmOneArcInst PARAMS ((bfd_vma, struct arcDisState *));
160static const char *_coreRegName PARAMS ((void *, int));
161static int decodeInstr PARAMS ((bfd_vma, disassemble_info *));
162
163static const char *
164core_reg_name (state, val)
165 struct arcDisState * state;
166 int val;
167{
168 if (state->coreRegName)
169 return (*state->coreRegName)(state->_this, val);
170 return 0;
171}
172
173static const char *
174aux_reg_name (state, val)
175 struct arcDisState * state;
176 int val;
177{
178 if (state->auxRegName)
179 return (*state->auxRegName)(state->_this, val);
180 return 0;
181}
182
183static const char *
184cond_code_name (state, val)
185 struct arcDisState * state;
186 int val;
187{
188 if (state->condCodeName)
189 return (*state->condCodeName)(state->_this, val);
190 return 0;
191}
192
193static const char *
194instruction_name (state, op1, op2, flags)
195 struct arcDisState * state;
196 int op1;
197 int op2;
198 int * flags;
199{
200 if (state->instName)
201 return (*state->instName)(state->_this, op1, op2, flags);
202 return 0;
203}
204
205static void
206mwerror (state, msg)
207 struct arcDisState * state;
208 const char * msg;
209{
210 if (state->err != 0)
211 (*state->err)(state->_this, (msg));
212}
213
214static const char *
215post_address (state, addr)
216 struct arcDisState * state;
217 int addr;
218{
219 static char id[3 * ARRAY_SIZE (state->addresses)];
220 int j, i = state->acnt;
221
222 if (i < ((int) ARRAY_SIZE (state->addresses)))
223 {
224 state->addresses[i] = addr;
225 ++state->acnt;
226 j = i*3;
227 id[j+0] = '@';
228 id[j+1] = '0'+i;
229 id[j+2] = 0;
230
231 return id + j;
232 }
233 return "";
234}
235
236static void my_sprintf PARAMS ((struct arcDisState *, char *, const char *,
237 ...));
238
239static void
240my_sprintf VPARAMS ((struct arcDisState *state, char *buf, const char *format,
241 ...))
242{
243 char *bp;
244 const char *p;
245 int size, leading_zero, regMap[2];
246 long auxNum;
247
248 VA_OPEN (ap, format);
249 VA_FIXEDARG (ap, struct arcDisState *, state);
250 VA_FIXEDARG (ap, char *, buf);
251 VA_FIXEDARG (ap, const char *, format);
252
253 bp = buf;
254 *bp = 0;
255 p = format;
256 auxNum = -1;
257 regMap[0] = 0;
258 regMap[1] = 0;
259
260 while (1)
261 switch (*p++)
262 {
263 case 0:
264 goto DOCOMM; /* (return) */
265 default:
266 *bp++ = p[-1];
267 break;
268 case '%':
269 size = 0;
270 leading_zero = 0;
271 RETRY: ;
272 switch (*p++)
273 {
274 case '0':
275 case '1':
276 case '2':
277 case '3':
278 case '4':
279 case '5':
280 case '6':
281 case '7':
282 case '8':
283 case '9':
284 {
285 /* size. */
286 size = p[-1] - '0';
287 if (size == 0)
288 leading_zero = 1; /* e.g. %08x */
289 while (*p >= '0' && *p <= '9')
290 {
291 size = size * 10 + *p - '0';
292 p++;
293 }
294 goto RETRY;
295 }
296#define inc_bp() bp = bp + strlen (bp)
297
298 case 'h':
299 {
300 unsigned u = va_arg (ap, int);
301
302 /* Hex. We can change the format to 0x%08x in
303 one place, here, if we wish.
304 We add underscores for easy reading. */
305 if (u > 65536)
306 sprintf (bp, "0x%x_%04x", u >> 16, u & 0xffff);
307 else
308 sprintf (bp, "0x%x", u);
309 inc_bp ();
310 }
311 break;
312 case 'X': case 'x':
313 {
314 int val = va_arg (ap, int);
315
316 if (size != 0)
317 if (leading_zero)
318 sprintf (bp, "%0*x", size, val);
319 else
320 sprintf (bp, "%*x", size, val);
321 else
322 sprintf (bp, "%x", val);
323 inc_bp ();
324 }
325 break;
326 case 'd':
327 {
328 int val = va_arg (ap, int);
329
330 if (size != 0)
331 sprintf (bp, "%*d", size, val);
332 else
333 sprintf (bp, "%d", val);
334 inc_bp ();
335 }
336 break;
337 case 'r':
338 {
339 /* Register. */
340 int val = va_arg (ap, int);
341
342#define REG2NAME(num, name) case num: sprintf (bp, ""name); \
343 regMap[(num < 32) ? 0 : 1] |= 1 << (num - ((num < 32) ? 0 : 32)); break;
344
345 switch (val)
346 {
347 REG2NAME (26, "gp");
348 REG2NAME (27, "fp");
349 REG2NAME (28, "sp");
350 REG2NAME (29, "ilink1");
351 REG2NAME (30, "ilink2");
352 REG2NAME (31, "blink");
353 REG2NAME (60, "lp_count");
354 default:
355 {
356 const char * ext;
357
358 ext = core_reg_name (state, val);
359 if (ext)
360 sprintf (bp, "%s", ext);
361 else
362 sprintf (bp,"r%d",val);
363 }
364 break;
365 }
366 inc_bp ();
367 } break;
368
369 case 'a':
370 {
371 /* Aux Register. */
372 int val = va_arg (ap, int);
373
374#define AUXREG2NAME(num, name) case num: sprintf (bp,name); break;
375
376 switch (val)
377 {
378 AUXREG2NAME (0x0, "status");
379 AUXREG2NAME (0x1, "semaphore");
380 AUXREG2NAME (0x2, "lp_start");
381 AUXREG2NAME (0x3, "lp_end");
382 AUXREG2NAME (0x4, "identity");
383 AUXREG2NAME (0x5, "debug");
384 default:
385 {
386 const char *ext;
387
388 ext = aux_reg_name (state, val);
389 if (ext)
390 sprintf (bp, "%s", ext);
391 else
392 my_sprintf (state, bp, "%h", val);
393 }
394 break;
395 }
396 inc_bp ();
397 }
398 break;
399
400 case 's':
401 {
402 sprintf (bp, "%s", va_arg (ap, char *));
403 inc_bp ();
404 }
405 break;
406
407 default:
408 fprintf (stderr, "?? format %c\n", p[-1]);
409 break;
410 }
411 }
412
413 DOCOMM: *bp = 0;
414 VA_CLOSE (ap);
415}
416
417static void
418write_comments_(state, shimm, is_limm, limm_value)
419 struct arcDisState * state;
420 int shimm;
421 int is_limm;
422 long limm_value;
423{
424 if (state->commentBuffer != 0)
425 {
426 int i;
427
428 if (is_limm)
429 {
430 const char *name = post_address (state, limm_value + shimm);
431
432 if (*name != 0)
433 WRITE_COMMENT (name);
434 }
435 for (i = 0; i < state->commNum; i++)
436 {
437 if (i == 0)
438 strcpy (state->commentBuffer, comment_prefix);
439 else
440 strcat (state->commentBuffer, ", ");
441 strncat (state->commentBuffer, state->comm[i],
442 sizeof (state->commentBuffer));
443 }
444 }
445}
446
447#define write_comments2(x) write_comments_(state, x, is_limm, limm_value)
448#define write_comments() write_comments2(0)
449
450static const char *condName[] = {
451 /* 0..15. */
452 "" , "z" , "nz" , "p" , "n" , "c" , "nc" , "v" ,
453 "nv" , "gt" , "ge" , "lt" , "le" , "hi" , "ls" , "pnz"
454};
455
456static void
457write_instr_name_(state, instrName, cond, condCodeIsPartOfName, flag, signExtend, addrWriteBack, directMem)
458 struct arcDisState * state;
459 const char * instrName;
460 int cond;
461 int condCodeIsPartOfName;
462 int flag;
463 int signExtend;
464 int addrWriteBack;
465 int directMem;
466{
467 strcpy (state->instrBuffer, instrName);
468
469 if (cond > 0)
470 {
471 const char *cc = 0;
472
473 if (!condCodeIsPartOfName)
474 strcat (state->instrBuffer, ".");
475
476 if (cond < 16)
477 cc = condName[cond];
478 else
479 cc = cond_code_name (state, cond);
480
481 if (!cc)
482 cc = "???";
483
484 strcat (state->instrBuffer, cc);
485 }
486
487 if (flag)
488 strcat (state->instrBuffer, ".f");
489
490 switch (state->nullifyMode)
491 {
492 case BR_exec_always:
493 strcat (state->instrBuffer, ".d");
494 break;
495 case BR_exec_when_jump:
496 strcat (state->instrBuffer, ".jd");
497 break;
498 }
499
500 if (signExtend)
501 strcat (state->instrBuffer, ".x");
502
503 if (addrWriteBack)
504 strcat (state->instrBuffer, ".a");
505
506 if (directMem)
507 strcat (state->instrBuffer, ".di");
508}
509
510#define write_instr_name() \
511 do \
512 { \
513 write_instr_name_(state, instrName,cond, condCodeIsPartOfName, \
514 flag, signExtend, addrWriteBack, directMem); \
515 formatString[0] = '\0'; \
516 } \
517 while (0)
518
519enum {
520 op_LD0 = 0, op_LD1 = 1, op_ST = 2, op_3 = 3,
521 op_BC = 4, op_BLC = 5, op_LPC = 6, op_JC = 7,
522 op_ADD = 8, op_ADC = 9, op_SUB = 10, op_SBC = 11,
523 op_AND = 12, op_OR = 13, op_BIC = 14, op_XOR = 15
524};
525
526extern disassemble_info tm_print_insn_info;
527
528static int
529dsmOneArcInst (addr, state)
530 bfd_vma addr;
531 struct arcDisState * state;
532{
533 int condCodeIsPartOfName = 0;
534 int decodingClass;
535 const char * instrName;
536 int repeatsOp = 0;
537 int fieldAisReg = 1;
538 int fieldBisReg = 1;
539 int fieldCisReg = 1;
540 int fieldA;
541 int fieldB;
542 int fieldC = 0;
543 int flag = 0;
544 int cond = 0;
545 int is_shimm = 0;
546 int is_limm = 0;
547 long limm_value = 0;
548 int signExtend = 0;
549 int addrWriteBack = 0;
550 int directMem = 0;
551 int is_linked = 0;
552 int offset = 0;
553 int usesAuxReg = 0;
554 int flags;
555 int ignoreFirstOpd;
556 char formatString[60];
557
558 state->instructionLen = 4;
559 state->nullifyMode = BR_exec_when_no_jump;
560 state->opWidth = 12;
561 state->isBranch = 0;
562
563 state->_mem_load = 0;
564 state->_ea_present = 0;
565 state->_load_len = 0;
566 state->ea_reg1 = no_reg;
567 state->ea_reg2 = no_reg;
568 state->_offset = 0;
569
570 if (! NEXT_WORD (0))
571 return 0;
572
573 state->_opcode = OPCODE (state->words[0]);
574 instrName = 0;
575 decodingClass = 0; /* default! */
576 repeatsOp = 0;
577 condCodeIsPartOfName=0;
578 state->commNum = 0;
579 state->tcnt = 0;
580 state->acnt = 0;
581 state->flow = noflow;
582 ignoreFirstOpd = 0;
583
584 if (state->commentBuffer)
585 state->commentBuffer[0] = '\0';
586
587 switch (state->_opcode)
588 {
589 case op_LD0:
590 switch (BITS (state->words[0],1,2))
591 {
592 case 0:
593 instrName = "ld";
594 state->_load_len = 4;
595 break;
596 case 1:
597 instrName = "ldb";
598 state->_load_len = 1;
599 break;
600 case 2:
601 instrName = "ldw";
602 state->_load_len = 2;
603 break;
604 default:
605 instrName = "??? (0[3])";
606 state->flow = invalid_instr;
607 break;
608 }
609 decodingClass = 5;
610 break;
611
612 case op_LD1:
613 if (BIT (state->words[0],13))
614 {
615 instrName = "lr";
616 decodingClass = 10;
617 }
618 else
619 {
620 switch (BITS (state->words[0],10,11))
621 {
622 case 0:
623 instrName = "ld";
624 state->_load_len = 4;
625 break;
626 case 1:
627 instrName = "ldb";
628 state->_load_len = 1;
629 break;
630 case 2:
631 instrName = "ldw";
632 state->_load_len = 2;
633 break;
634 default:
635 instrName = "??? (1[3])";
636 state->flow = invalid_instr;
637 break;
638 }
639 decodingClass = 6;
640 }
641 break;
642
643 case op_ST:
644 if (BIT (state->words[0],25))
645 {
646 instrName = "sr";
647 decodingClass = 8;
648 }
649 else
650 {
651 switch (BITS (state->words[0],22,23))
652 {
653 case 0:
654 instrName = "st";
655 break;
656 case 1:
657 instrName = "stb";
658 break;
659 case 2:
660 instrName = "stw";
661 break;
662 default:
663 instrName = "??? (2[3])";
664 state->flow = invalid_instr;
665 break;
666 }
667 decodingClass = 7;
668 }
669 break;
670
671 case op_3:
672 decodingClass = 1; /* default for opcode 3... */
673 switch (FIELDC (state->words[0]))
674 {
675 case 0:
676 instrName = "flag";
677 decodingClass = 2;
678 break;
679 case 1:
680 instrName = "asr";
681 break;
682 case 2:
683 instrName = "lsr";
684 break;
685 case 3:
686 instrName = "ror";
687 break;
688 case 4:
689 instrName = "rrc";
690 break;
691 case 5:
692 instrName = "sexb";
693 break;
694 case 6:
695 instrName = "sexw";
696 break;
697 case 7:
698 instrName = "extb";
699 break;
700 case 8:
701 instrName = "extw";
702 break;
703 case 0x3f:
704 {
705 decodingClass = 9;
706 switch( FIELDD (state->words[0]) )
707 {
708 case 0:
709 instrName = "brk";
710 break;
711 case 1:
712 instrName = "sleep";
713 break;
714 case 2:
715 instrName = "swi";
716 break;
717 default:
718 instrName = "???";
719 state->flow=invalid_instr;
720 break;
721 }
722 }
723 break;
724
725 /* ARC Extension Library Instructions
726 NOTE: We assume that extension codes are these instrs. */
727 default:
728 instrName = instruction_name (state,
729 state->_opcode,
730 FIELDC (state->words[0]),
731 &flags);
732 if (!instrName)
733 {
734 instrName = "???";
735 state->flow = invalid_instr;
736 }
737 if (flags & IGNORE_FIRST_OPD)
738 ignoreFirstOpd = 1;
739 break;
740 }
741 break;
742
743 case op_BC:
744 instrName = "b";
745 case op_BLC:
746 if (!instrName)
747 instrName = "bl";
748 case op_LPC:
749 if (!instrName)
750 instrName = "lp";
751 case op_JC:
752 if (!instrName)
753 {
754 if (BITS (state->words[0],9,9))
755 {
756 instrName = "jl";
757 is_linked = 1;
758 }
759 else
760 {
761 instrName = "j";
762 is_linked = 0;
763 }
764 }
765 condCodeIsPartOfName = 1;
766 decodingClass = ((state->_opcode == op_JC) ? 4 : 3);
767 state->isBranch = 1;
768 break;
769
770 case op_ADD:
771 case op_ADC:
772 case op_AND:
773 repeatsOp = (FIELDC (state->words[0]) == FIELDB (state->words[0]));
774 decodingClass = 0;
775
776 switch (state->_opcode)
777 {
778 case op_ADD:
779 instrName = (repeatsOp ? "asl" : "add");
780 break;
781 case op_ADC:
782 instrName = (repeatsOp ? "rlc" : "adc");
783 break;
784 case op_AND:
785 instrName = (repeatsOp ? "mov" : "and");
786 break;
787 }
788 break;
789
790 case op_SUB: instrName = "sub";
791 break;
792 case op_SBC: instrName = "sbc";
793 break;
794 case op_OR: instrName = "or";
795 break;
796 case op_BIC: instrName = "bic";
797 break;
798
799 case op_XOR:
800 if (state->words[0] == 0x7fffffff)
801 {
802 /* nop encoded as xor -1, -1, -1 */
803 instrName = "nop";
804 decodingClass = 9;
805 }
806 else
807 instrName = "xor";
808 break;
809
810 default:
811 instrName = instruction_name (state,state->_opcode,0,&flags);
812 /* if (instrName) printf("FLAGS=0x%x\n", flags); */
813 if (!instrName)
814 {
815 instrName = "???";
816 state->flow=invalid_instr;
817 }
818 if (flags & IGNORE_FIRST_OPD)
819 ignoreFirstOpd = 1;
820 break;
821 }
822
823 fieldAisReg = fieldBisReg = fieldCisReg = 1; /* Assume regs for now. */
824 flag = cond = is_shimm = is_limm = 0;
825 state->nullifyMode = BR_exec_when_no_jump; /* 0 */
826 signExtend = addrWriteBack = directMem = 0;
827 usesAuxReg = 0;
828
829 switch (decodingClass)
830 {
831 case 0:
832 CHECK_FIELD_A ();
833 CHECK_FIELD_B ();
834 if (!repeatsOp)
835 CHECK_FIELD_C ();
836 CHECK_FLAG_COND_NULLIFY ();
837
838 write_instr_name ();
839 if (!ignoreFirstOpd)
840 {
841 WRITE_FORMAT_x (A);
842 WRITE_FORMAT_COMMA_x (B);
843 if (!repeatsOp)
844 WRITE_FORMAT_COMMA_x (C);
845 WRITE_NOP_COMMENT ();
846 my_sprintf (state, state->operandBuffer, formatString,
847 fieldA, fieldB, fieldC);
848 }
849 else
850 {
851 WRITE_FORMAT_x (B);
852 if (!repeatsOp)
853 WRITE_FORMAT_COMMA_x (C);
854 my_sprintf (state, state->operandBuffer, formatString,
855 fieldB, fieldC);
856 }
857 write_comments ();
858 break;
859
860 case 1:
861 CHECK_FIELD_A ();
862 CHECK_FIELD_B ();
863 CHECK_FLAG_COND_NULLIFY ();
864
865 write_instr_name ();
866 if (!ignoreFirstOpd)
867 {
868 WRITE_FORMAT_x (A);
869 WRITE_FORMAT_COMMA_x (B);
870 WRITE_NOP_COMMENT ();
871 my_sprintf (state, state->operandBuffer, formatString,
872 fieldA, fieldB);
873 }
874 else
875 {
876 WRITE_FORMAT_x (B);
877 my_sprintf (state, state->operandBuffer, formatString, fieldB);
878 }
879 write_comments ();
880 break;
881
882 case 2:
883 CHECK_FIELD_B ();
884 CHECK_FLAG_COND_NULLIFY ();
885 flag = 0; /* this is the FLAG instruction -- it's redundant */
886
887 write_instr_name ();
888 WRITE_FORMAT_x (B);
889 my_sprintf (state, state->operandBuffer, formatString, fieldB);
890 write_comments ();
891 break;
892
893 case 3:
894 fieldA = BITS (state->words[0],7,26) << 2;
895 fieldA = (fieldA << 10) >> 10; /* make it signed */
896 fieldA += addr + 4;
897 CHECK_FLAG_COND_NULLIFY ();
898 flag = 0;
899
900 write_instr_name ();
901 /* This address could be a label we know. Convert it. */
902 if (state->_opcode != op_LPC /* LP */)
903 {
904 add_target (fieldA); /* For debugger. */
905 state->flow = state->_opcode == op_BLC /* BL */
906 ? direct_call
907 : direct_jump;
908 /* indirect calls are achieved by "lr blink,[status];
909 lr dest<- func addr; j [dest]" */
910 }
911
912 strcat (formatString, "%s"); /* address/label name */
913 my_sprintf (state, state->operandBuffer, formatString,
914 post_address (state, fieldA));
915 write_comments ();
916 break;
917
918 case 4:
919 /* For op_JC -- jump to address specified.
920 Also covers jump and link--bit 9 of the instr. word
921 selects whether linked, thus "is_linked" is set above. */
922 fieldA = 0;
923 CHECK_FIELD_B ();
924 CHECK_FLAG_COND_NULLIFY ();
925
926 if (!fieldBisReg)
927 {
928 fieldAisReg = 0;
929 fieldA = (fieldB >> 25) & 0x7F; /* flags */
930 fieldB = (fieldB & 0xFFFFFF) << 2;
931 state->flow = is_linked ? direct_call : direct_jump;
932 add_target (fieldB);
933 /* screwy JLcc requires .jd mode to execute correctly
934 * but we pretend it is .nd (no delay slot). */
935 if (is_linked && state->nullifyMode == BR_exec_when_jump)
936 state->nullifyMode = BR_exec_when_no_jump;
937 }
938 else
939 {
940 state->flow = is_linked ? indirect_call : indirect_jump;
941 /* We should also treat this as indirect call if NOT linked
942 * but the preceding instruction was a "lr blink,[status]"
943 * and we have a delay slot with "add blink,blink,2".
944 * For now we can't detect such. */
945 state->register_for_indirect_jump = fieldB;
946 }
947
948 write_instr_name ();
949 strcat (formatString,
950 IS_REG (B) ? "[%r]" : "%s"); /* address/label name */
951 if (fieldA != 0)
952 {
953 fieldAisReg = 0;
954 WRITE_FORMAT_COMMA_x (A);
955 }
956 if (IS_REG (B))
957 my_sprintf (state, state->operandBuffer, formatString, fieldB, fieldA);
958 else
959 my_sprintf (state, state->operandBuffer, formatString,
960 post_address (state, fieldB), fieldA);
961 write_comments ();
962 break;
963
964 case 5:
965 /* LD instruction.
966 B and C can be regs, or one (both?) can be limm. */
967 CHECK_FIELD_A ();
968 CHECK_FIELD_B ();
969 CHECK_FIELD_C ();
970 if (dbg)
971 printf ("5:b reg %d %d c reg %d %d \n",
972 fieldBisReg,fieldB,fieldCisReg,fieldC);
973 state->_offset = 0;
974 state->_ea_present = 1;
975 if (fieldBisReg)
976 state->ea_reg1 = fieldB;
977 else
978 state->_offset += fieldB;
979 if (fieldCisReg)
980 state->ea_reg2 = fieldC;
981 else
982 state->_offset += fieldC;
983 state->_mem_load = 1;
984
985 directMem = BIT (state->words[0],5);
986 addrWriteBack = BIT (state->words[0],3);
987 signExtend = BIT (state->words[0],0);
988
989 write_instr_name ();
990 WRITE_FORMAT_x_COMMA_LB(A);
991 if (fieldBisReg || fieldB != 0)
992 WRITE_FORMAT_x_COMMA (B);
993 else
994 fieldB = fieldC;
995
996 WRITE_FORMAT_x_RB (C);
997 my_sprintf (state, state->operandBuffer, formatString,
998 fieldA, fieldB, fieldC);
999 write_comments ();
1000 break;
1001
1002 case 6:
1003 /* LD instruction. */
1004 CHECK_FIELD_B ();
1005 CHECK_FIELD_A ();
1006 fieldC = FIELDD (state->words[0]);
1007
1008 if (dbg)
1009 printf ("6:b reg %d %d c 0x%x \n",
1010 fieldBisReg, fieldB, fieldC);
1011 state->_ea_present = 1;
1012 state->_offset = fieldC;
1013 state->_mem_load = 1;
1014 if (fieldBisReg)
1015 state->ea_reg1 = fieldB;
1016 /* field B is either a shimm (same as fieldC) or limm (different!)
1017 Say ea is not present, so only one of us will do the name lookup. */
1018 else
1019 state->_offset += fieldB, state->_ea_present = 0;
1020
1021 directMem = BIT (state->words[0],14);
1022 addrWriteBack = BIT (state->words[0],12);
1023 signExtend = BIT (state->words[0],9);
1024
1025 write_instr_name ();
1026 WRITE_FORMAT_x_COMMA_LB (A);
1027 if (!fieldBisReg)
1028 {
1029 fieldB = state->_offset;
1030 WRITE_FORMAT_x_RB (B);
1031 }
1032 else
1033 {
1034 WRITE_FORMAT_x (B);
1035 if (fieldC != 0 && !BIT (state->words[0],13))
1036 {
1037 fieldCisReg = 0;
1038 WRITE_FORMAT_COMMA_x_RB (C);
1039 }
1040 else
1041 WRITE_FORMAT_RB ();
1042 }
1043 my_sprintf (state, state->operandBuffer, formatString,
1044 fieldA, fieldB, fieldC);
1045 write_comments ();
1046 break;
1047
1048 case 7:
1049 /* ST instruction. */
1050 CHECK_FIELD_B();
1051 CHECK_FIELD_C();
1052 fieldA = FIELDD(state->words[0]); /* shimm */
1053
1054 /* [B,A offset] */
1055 if (dbg) printf("7:b reg %d %x off %x\n",
1056 fieldBisReg,fieldB,fieldA);
1057 state->_ea_present = 1;
1058 state->_offset = fieldA;
1059 if (fieldBisReg)
1060 state->ea_reg1 = fieldB;
1061 /* field B is either a shimm (same as fieldA) or limm (different!)
1062 Say ea is not present, so only one of us will do the name lookup.
1063 (for is_limm we do the name translation here). */
1064 else
1065 state->_offset += fieldB, state->_ea_present = 0;
1066
1067 directMem = BIT(state->words[0],26);
1068 addrWriteBack = BIT(state->words[0],24);
1069
1070 write_instr_name();
1071 WRITE_FORMAT_x_COMMA_LB(C);
1072
1073 if (!fieldBisReg)
1074 {
1075 fieldB = state->_offset;
1076 WRITE_FORMAT_x_RB(B);
1077 }
1078 else
1079 {
1080 WRITE_FORMAT_x(B);
1081 if (fieldBisReg && fieldA != 0)
1082 {
1083 fieldAisReg = 0;
1084 WRITE_FORMAT_COMMA_x_RB(A);
1085 }
1086 else
1087 WRITE_FORMAT_RB();
1088 }
1089 my_sprintf (state, state->operandBuffer, formatString,
1090 fieldC, fieldB, fieldA);
1091 write_comments2(fieldA);
1092 break;
1093 case 8:
1094 /* SR instruction */
1095 CHECK_FIELD_B();
1096 CHECK_FIELD_C();
1097
1098 write_instr_name();
1099 WRITE_FORMAT_x_COMMA_LB(C);
1100 /* Try to print B as an aux reg if it is not a core reg. */
1101 usesAuxReg = 1;
1102 WRITE_FORMAT_x(B);
1103 WRITE_FORMAT_RB();
1104 my_sprintf (state, state->operandBuffer, formatString, fieldC, fieldB);
1105 write_comments();
1106 break;
1107
1108 case 9:
1109 write_instr_name();
1110 state->operandBuffer[0] = '\0';
1111 break;
1112
1113 case 10:
1114 /* LR instruction */
1115 CHECK_FIELD_A();
1116 CHECK_FIELD_B();
1117
1118 write_instr_name();
1119 WRITE_FORMAT_x_COMMA_LB(A);
1120 /* Try to print B as an aux reg if it is not a core reg. */
1121 usesAuxReg = 1;
1122 WRITE_FORMAT_x(B);
1123 WRITE_FORMAT_RB();
1124 my_sprintf (state, state->operandBuffer, formatString, fieldA, fieldB);
1125 write_comments();
1126 break;
1127
1128 case 11:
1129 CHECK_COND();
1130 write_instr_name();
1131 state->operandBuffer[0] = '\0';
1132 break;
1133
1134 default:
1135 mwerror (state, "Bad decoding class in ARC disassembler");
1136 break;
1137 }
1138
1139 state->_cond = cond;
1140 return state->instructionLen = offset;
1141}
1142
1143
1144/* Returns the name the user specified core extension register. */
1145static const char *
1146_coreRegName(arg, regval)
1147 void * arg ATTRIBUTE_UNUSED;
1148 int regval;
1149{
1150 return arcExtMap_coreRegName (regval);
1151}
1152
1153/* Returns the name the user specified AUX extension register. */
1154static const char *
1155_auxRegName(void *_this ATTRIBUTE_UNUSED, int regval)
1156{
1157 return arcExtMap_auxRegName(regval);
1158}
1159
1160
1161/* Returns the name the user specified condition code name. */
1162static const char *
1163_condCodeName(void *_this ATTRIBUTE_UNUSED, int regval)
1164{
1165 return arcExtMap_condCodeName(regval);
1166}
1167
1168/* Returns the name the user specified extension instruction. */
1169static const char *
1170_instName (void *_this ATTRIBUTE_UNUSED, int majop, int minop, int *flags)
1171{
1172 return arcExtMap_instName(majop, minop, flags);
1173}
1174
1175/* Decode an instruction returning the size of the instruction
1176 in bytes or zero if unrecognized. */
1177static int
1178decodeInstr (address, info)
1179 bfd_vma address; /* Address of this instruction. */
1180 disassemble_info * info;
1181{
1182 int status;
1183 bfd_byte buffer[4];
1184 struct arcDisState s; /* ARC Disassembler state */
1185 void *stream = info->stream; /* output stream */
1186 fprintf_ftype func = info->fprintf_func;
1187 int bytes;
1188
1189 memset (&s, 0, sizeof(struct arcDisState));
1190
1191 /* read first instruction */
1192 status = (*info->read_memory_func) (address, buffer, 4, info);
1193 if (status != 0)
1194 {
1195 (*info->memory_error_func) (status, address, info);
1196 return 0;
1197 }
1198 if (info->endian == BFD_ENDIAN_LITTLE)
1199 s.words[0] = bfd_getl32(buffer);
1200 else
1201 s.words[0] = bfd_getb32(buffer);
1202 /* always read second word in case of limm */
1203
1204 /* we ignore the result since last insn may not have a limm */
1205 status = (*info->read_memory_func) (address + 4, buffer, 4, info);
1206 if (info->endian == BFD_ENDIAN_LITTLE)
1207 s.words[1] = bfd_getl32(buffer);
1208 else
1209 s.words[1] = bfd_getb32(buffer);
1210
1211 s._this = &s;
1212 s.coreRegName = _coreRegName;
1213 s.auxRegName = _auxRegName;
1214 s.condCodeName = _condCodeName;
1215 s.instName = _instName;
1216
1217 /* disassemble */
1218 bytes = dsmOneArcInst(address, (void *)&s);
1219
1220 /* display the disassembly instruction */
1221 (*func) (stream, "%08x ", s.words[0]);
1222 (*func) (stream, " ");
1223
1224 (*func) (stream, "%-10s ", s.instrBuffer);
1225
1226 if (__TRANSLATION_REQUIRED(s))
1227 {
1228 bfd_vma addr = s.addresses[s.operandBuffer[1] - '0'];
1229 (*info->print_address_func) ((bfd_vma) addr, info);
1230 (*func) (stream, "\n");
1231 }
1232 else
1233 (*func) (stream, "%s",s.operandBuffer);
1234 return s.instructionLen;
1235}
1236
1237/* Return the print_insn function to use.
1238 Side effect: load (possibly empty) extension section */
1239
1240disassembler_ftype
1241arc_get_disassembler (void *ptr)
1242{
1243 if (ptr)
1244 build_ARC_extmap (ptr);
1245 return decodeInstr;
1246}
Note: See TracBrowser for help on using the repository browser.