1 /* disassemble sparc instructions for objdump
2 Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
5 This file is part of the binutils.
7 The binutils are free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 1, or (at your option)
12 The binutils are distributed in the hope that they will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with the binutils; see the file COPYING. If not, write to
19 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
23 Revision 1.6 1991/05/23 03:49:10 rich
24 new sparc-opcode, new pinsn.
26 * Revision 1.5 1991/05/22 01:40:35 rich
29 * Revision 1.4 1991/05/22 01:17:48 rich
32 * Revision 1.3 1991/05/19 08:00:57 rich
33 * Updated to relect a gdb change in sparc-opcode.h.
35 * Revision 1.2 1991/04/18 21:14:21 steve
36 * Send the right # of args to an fprintf
38 * Revision 1.1.1.1 1991/03/21 21:26:56 gumby
39 * Back from Intel with Steve
41 * Revision 1.1 1991/03/21 21:26:55 gumby
44 * Revision 1.1 1991/03/13 00:34:40 chrisb
47 * Revision 1.3 1991/03/09 04:36:31 rich
49 * sparc-pinsn.c ostrip.c objdump.c m68k-pinsn.c i960-pinsn.c
52 * Pulled sysdep.h out of bfd.h.
54 * Revision 1.2 1991/03/08 21:54:53 rich
56 * Makefile ar.c binutils.h bucomm.c copy.c cplus-dem.c getopt.c
57 * i960-pinsn.c m68k-pinsn.c nm.c objdump.c sparc-opcode.h
58 * sparc-pinsn.c strip.c
60 * Verifying Portland tree with steve's last changes. Also, some partial
63 * Revision 1.1 1991/02/22 16:48:04 sac
71 #include "sparc-opcode.h"
74 extern int print_address();
76 static char *reg_names
[] =
77 { "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7",
78 "o0", "o1", "o2", "o3", "o4", "o5", "sp", "o7",
79 "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7",
80 "i0", "i1", "i2", "i3", "i4", "i5", "fp", "i7",
81 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
82 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
83 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
84 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
85 "y", "psr", "wim", "tbr", "pc", "npc", "fpsr", "cpsr" };
87 #define freg_names (®_names[4 * 8])
91 unsigned long int code
;
100 #define rs1 ldst._RS1
103 #define asi ldst._ASI
105 #define rs2 ldst._RS2
110 unsigned int _OP
:2, _RD
:5, op3
:6, _RS1
:5, i
:1;
111 unsigned int IMM13
:13;
112 #define imm13 IMM13.IMM13
120 unsigned int DISP22
:22;
121 #define disp22 branch.DISP22
126 unsigned int _OP
:2, _RD
:5, op3
:6, _RS1
:5;
127 unsigned int DISP14
:14;
128 #define disp14 DISP14.DISP14
137 unsigned int DISP21
:21;
138 #define disp21 branch2.DISP21
146 unsigned int _DISP30
:30;
147 #define disp30 call._DISP30
151 /* Nonzero if INSN is the opcode for a delayed branch. */
153 is_delayed_branch (insn
)
154 union sparc_insn insn
;
158 for (i
= 0; i
< NUMOPCODES
; ++i
)
160 const struct sparc_opcode
*opcode
= &sparc_opcodes
[i
];
161 if ((opcode
->match
& insn
.code
) == opcode
->match
162 && (opcode
->lose
& insn
.code
) == 0
163 && (opcode
->flags
&F_DELAYED
))
169 static int opcodes_sorted
= 0;
171 /* Print one instruction from MEMADDR on STREAM. */
173 print_insn_sparc (memaddr
, buffer
, stream
)
179 union sparc_insn insn
;
181 register unsigned int i
;
185 static int compare_opcodes ();
186 qsort ((char *) sparc_opcodes
, NUMOPCODES
,
187 sizeof (sparc_opcodes
[0]), compare_opcodes
);
191 memcpy(&insn
,buffer
, sizeof (insn
));
193 for (i
= 0; i
< NUMOPCODES
; ++i
)
195 const struct sparc_opcode
*opcode
= &sparc_opcodes
[i
];
196 if ((opcode
->match
& insn
.code
) == opcode
->match
197 && (opcode
->lose
& insn
.code
) == 0)
199 /* Nonzero means that we have found an instruction which has
200 the effect of adding or or'ing the imm13 field to rs1. */
201 int imm_added_to_rs1
= 0;
203 /* Nonzero means that we have found a plus sign in the args
204 field of the opcode table. */
207 /* Do we have an 'or' instruction where rs1 is the same
208 as rsd, and which has the i bit set? */
209 if (opcode
->match
== 0x80102000
210 && insn
.rs1
== insn
.rd
)
211 imm_added_to_rs1
= 1;
213 if (index (opcode
->args
, 'S') != 0)
214 /* Reject the special case for `set'.
215 The real `sethi' will match. */
217 if (insn
.rs1
!= insn
.rd
218 && index (opcode
->args
, 'r') != 0)
219 /* Can't do simple format if source and dest are different. */
222 fputs (opcode
->name
, stream
);
225 register const char *s
;
227 if (opcode
->args
[0] != ',')
229 for (s
= opcode
->args
; *s
!= '\0'; ++s
) {
253 } /* switch on arg */
254 } /* while there are comma started args */
263 /* note fall-through */
265 fprintf (stream
, "%c", *s
);
272 #define reg(n) fprintf (stream, "%%%s", reg_names[n])
287 #define freg(n) fprintf (stream, "%%%s", freg_names[n])
301 #define creg(n) fprintf (stream, "%%c%u", (unsigned int) (n))
316 fprintf (stream
, "%%hi(%#x)",
317 (unsigned int) insn
.imm22
<< 10);
322 /* We cannot trust the compiler to sign-extend
323 when extracting the bitfield, hence the shifts. */
324 int imm
= ((int) insn
.imm13
<< 19) >> 19;
326 /* Check to see whether we have a 1+i, and take
329 Note: because of the way we sort the table,
330 we will be matching 1+i rather than i+1,
331 so it is OK to assume that i is after +,
334 imm_added_to_rs1
= 1;
337 fprintf (stream
, "%d", imm
);
339 fprintf (stream
, "%#x", (unsigned) imm
);
345 print_address ((bfd_vma
)
347 + (((int) insn
.disp14
<< 18) >> 18) * 4),
352 print_address ((bfd_vma
)
354 + (((int) insn
.disp21
<< 11) >> 11) * 4),
359 fputs ("%amr", stream
);
365 fprintf(stream
, "%%asr%d", insn
.rs1
);
369 fprintf(stream
, "%%asr%d", insn
.rd
);
373 print_address ((bfd_vma
) memaddr
+ insn
.disp30
* 4,
378 if ((insn
.code
>> 22) == 0)
379 /* Special case for `unimp'. Don't try to turn
380 it's operand into a function offset. */
381 fprintf (stream
, "%#x",
382 (unsigned) (((int) insn
.disp22
<< 10) >> 10));
384 /* We cannot trust the compiler to sign-extend
385 when extracting the bitfield, hence the shifts. */
386 print_address ((bfd_vma
)
388 + (((int) insn
.disp22
<< 10) >> 10) * 4),
393 fprintf (stream
, "(%d)", (int) insn
.asi
);
397 fputs ("%csr", stream
);
401 fputs ("%fsr", stream
);
405 fputs ("%psr", stream
);
409 fputs ("%fq", stream
);
413 fputs ("%cq", stream
);
417 fputs ("%tbr", stream
);
421 fputs ("%wim", stream
);
425 fputs ("%y", stream
);
431 /* If we are adding or or'ing something to rs1, then
432 check to see whether the previous instruction was
433 a sethi to the same register as in the sethi.
434 If so, attempt to print the result of the add or
435 or (in this context add and or do the same thing)
436 and its symbolic value. */
437 if (imm_added_to_rs1
)
439 union sparc_insn prev_insn
;
442 memcpy(&prev_insn
, buffer
-4, sizeof (prev_insn
));
446 /* If it is a delayed branch, we need to look at the
447 instruction before the delayed branch. This handles
450 sethi %o1, %hi(_foo), %o1
452 or %o1, %lo(_foo), %o1
455 if (is_delayed_branch (prev_insn
))
456 memcpy(&prev_insn
, buffer
- 8, sizeof(prev_insn
));
460 /* If there was a problem reading memory, then assume
461 the previous instruction was not sethi. */
464 /* Is it sethi to the same register? */
465 if ((prev_insn
.code
& 0xc1c00000) == 0x01000000
466 && prev_insn
.rd
== insn
.rs1
)
468 fprintf (stream
, "\t! ");
469 /* We cannot trust the compiler to sign-extend
470 when extracting the bitfield, hence the shifts. */
471 print_address (((int) prev_insn
.imm22
<< 10)
472 | (insn
.imm13
<< 19) >> 19, stream
);
477 return sizeof (insn
);
481 fprintf (stream
, "%#8x", insn
.code
);
482 return sizeof (insn
);
486 /* Compare opcodes A and B. */
489 compare_opcodes (a
, b
)
492 struct sparc_opcode
*op0
= (struct sparc_opcode
*) a
;
493 struct sparc_opcode
*op1
= (struct sparc_opcode
*) b
;
494 unsigned long int match0
= op0
->match
, match1
= op1
->match
;
495 unsigned long int lose0
= op0
->lose
, lose1
= op1
->lose
;
496 register unsigned int i
;
498 /* If a bit is set in both match and lose, there is something
499 wrong with the opcode table. */
502 fprintf (stderr
, "Internal error: bad sparc-opcode.h: \"%s\", %#.8lx, %#.8lx\n",
503 op0
->name
, match0
, lose0
);
504 op0
->lose
&= ~op0
->match
;
510 fprintf (stderr
, "Internal error: bad sparc-opcode.h: \"%s\", %#.8lx, %#.8lx\n",
511 op1
->name
, match1
, lose1
);
512 op1
->lose
&= ~op1
->match
;
516 /* Because the bits that are variable in one opcode are constant in
517 another, it is important to order the opcodes in the right order. */
518 for (i
= 0; i
< 32; ++i
)
520 unsigned long int x
= 1 << i
;
521 int x0
= (match0
& x
) != 0;
522 int x1
= (match1
& x
) != 0;
528 for (i
= 0; i
< 32; ++i
)
530 unsigned long int x
= 1 << i
;
531 int x0
= (lose0
& x
) != 0;
532 int x1
= (lose1
& x
) != 0;
538 /* They are functionally equal. So as long as the opcode table is
539 valid, we can put whichever one first we want, on aesthetic grounds. */
541 int length_diff
= strlen (op0
->args
) - strlen (op1
->args
);
542 if (length_diff
!= 0)
543 /* Put the one with fewer arguments first. */
547 /* Put 1+i before i+1. */
549 char *p0
= (char *) index(op0
->args
, '+');
550 char *p1
= (char *) index(op1
->args
, '+');
554 /* There is a plus in both operands. Note that a plus
555 sign cannot be the first character in args,
556 so the following [-1]'s are valid. */
557 if (p0
[-1] == 'i' && p1
[1] == 'i')
558 /* op0 is i+1 and op1 is 1+i, so op1 goes first. */
560 if (p0
[1] == 'i' && p1
[-1] == 'i')
561 /* op0 is 1+i and op1 is i+1, so op0 goes first. */
566 /* They are, as far as we can tell, identical.
567 Since qsort may have rearranged the table partially, there is
568 no way to tell which one was first in the opcode table as
569 written, so just say there are equal. */
This page took 0.049449 seconds and 5 git commands to generate.