This commit was generated by cvs2svn to track changes on a CVS vendor
[binutils-gdb.git] / binutils / sparc-pinsn.c
1 /* disassemble sparc instructions for objdump
2 Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
3
4
5 This file is part of the binutils.
6
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)
10 any later version.
11
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.
16
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. */
20
21 /* $Id$
22 $Log$
23 Revision 1.1.1.1 1991/03/21 21:26:56 gumby
24 Back from Intel with Steve
25
26 * Revision 1.1 1991/03/21 21:26:55 gumby
27 * Initial revision
28 *
29 * Revision 1.1 1991/03/13 00:34:40 chrisb
30 * Initial revision
31 *
32 * Revision 1.3 1991/03/09 04:36:31 rich
33 * Modified Files:
34 * sparc-pinsn.c ostrip.c objdump.c m68k-pinsn.c i960-pinsn.c
35 * binutils.h
36 *
37 * Pulled sysdep.h out of bfd.h.
38 *
39 * Revision 1.2 1991/03/08 21:54:53 rich
40 * Modified Files:
41 * Makefile ar.c binutils.h bucomm.c copy.c cplus-dem.c getopt.c
42 * i960-pinsn.c m68k-pinsn.c nm.c objdump.c sparc-opcode.h
43 * sparc-pinsn.c strip.c
44 *
45 * Verifying Portland tree with steve's last changes. Also, some partial
46 * porting.
47 *
48 * Revision 1.1 1991/02/22 16:48:04 sac
49 * Initial revision
50 *
51 */
52
53 #include <stdio.h>
54 #include "sysdep.h"
55 #include "bfd.h"
56 #include "sparc-opcode.h"
57
58 extern int fputs();
59 extern int print_address();
60
61 static char *reg_names[] =
62 { "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7",
63 "o0", "o1", "o2", "o3", "o4", "o5", "sp", "o7",
64 "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7",
65 "i0", "i1", "i2", "i3", "i4", "i5", "fp", "i7",
66 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
67 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
68 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
69 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
70 "y", "psr", "wim", "tbr", "pc", "npc", "fpsr", "cpsr" };
71
72 #define freg_names (&reg_names[4 * 8])
73
74 union sparc_insn
75 {
76 unsigned long int code;
77 struct
78 {
79 unsigned int OP:2;
80 #define op ldst.OP
81 unsigned int RD:5;
82 #define rd ldst.RD
83 unsigned int op3:6;
84 unsigned int RS1:5;
85 #define rs1 ldst.RS1
86 unsigned int i:1;
87 unsigned int ASI:8;
88 #define asi ldst.ASI
89 unsigned int RS2:5;
90 #define rs2 ldst.RS2
91 #define shcnt rs2
92 } ldst;
93 struct
94 {
95 unsigned int OP:2, RD:5, op3:6, RS1:5, i:1;
96 unsigned int IMM13:13;
97 #define imm13 IMM13.IMM13
98 } IMM13;
99 struct
100 {
101 unsigned int OP:2;
102 unsigned int a:1;
103 unsigned int cond:4;
104 unsigned int op2:3;
105 unsigned int DISP22:22;
106 #define disp22 branch.DISP22
107 } branch;
108 #define imm22 disp22
109 struct
110 {
111 unsigned int OP:2;
112 unsigned int DISP30:30;
113 #define disp30 call.DISP30
114 } call;
115 };
116
117 /* Nonzero if INSN is the opcode for a delayed branch. */
118 static int
119 is_delayed_branch (insn)
120 union sparc_insn insn;
121 {
122 unsigned int i;
123
124 for (i = 0; i < NUMOPCODES; ++i)
125 {
126 const struct sparc_opcode *opcode = &sparc_opcodes[i];
127 if ((opcode->match & insn.code) == opcode->match
128 && (opcode->lose & insn.code) == 0
129 && (opcode->delayed))
130 return 1;
131 }
132 return 0;
133 }
134
135 static int opcodes_sorted = 0;
136
137 /* Print one instruction from MEMADDR on STREAM. */
138 int
139 print_insn_sparc (memaddr, buffer, stream)
140 bfd_vma memaddr;
141 bfd_byte *buffer;
142 FILE *stream;
143
144 {
145 union sparc_insn insn;
146
147 register unsigned int i;
148
149 if (!opcodes_sorted)
150 {
151 static int compare_opcodes ();
152 qsort ((char *) sparc_opcodes, NUMOPCODES,
153 sizeof (sparc_opcodes[0]), compare_opcodes);
154 opcodes_sorted = 1;
155 }
156
157 memcpy(&insn,buffer, sizeof (insn));
158
159 for (i = 0; i < NUMOPCODES; ++i)
160 {
161 const struct sparc_opcode *opcode = &sparc_opcodes[i];
162 if ((opcode->match & insn.code) == opcode->match
163 && (opcode->lose & insn.code) == 0)
164 {
165 /* Nonzero means that we have found an instruction which has
166 the effect of adding or or'ing the imm13 field to rs1. */
167 int imm_added_to_rs1 = 0;
168
169 /* Nonzero means that we have found a plus sign in the args
170 field of the opcode table. */
171 int found_plus = 0;
172
173 /* Do we have an 'or' instruction where rs1 is the same
174 as rsd, and which has the i bit set? */
175 if (opcode->match == 0x80102000
176 && insn.rs1 == insn.rd)
177 imm_added_to_rs1 = 1;
178
179 if (index (opcode->args, 'S') != 0)
180 /* Reject the special case for `set'.
181 The real `sethi' will match. */
182 continue;
183 if (insn.rs1 != insn.rd
184 && index (opcode->args, 'r') != 0)
185 /* Can't do simple format if source and dest are different. */
186 continue;
187
188 fputs (opcode->name, stream);
189
190 {
191 register const char *s;
192
193 if (opcode->args[0] != ',')
194 fputs (" ", stream);
195 for (s = opcode->args; *s != '\0'; ++s)
196 {
197 if (*s == ',')
198 {
199 fputs (",", stream);
200 ++s;
201 if (*s == 'a')
202 {
203 fputs ("a", stream);
204 ++s;
205 }
206 fputs (" ", stream);
207 }
208
209 switch (*s)
210 {
211 case '+':
212 found_plus = 1;
213
214 /* note fall-through */
215 default:
216 fprintf (stream, "%c", *s);
217 break;
218
219 case '#':
220 fputs ("0", stream);
221 break;
222
223 #define reg(n) fprintf (stream, "%%%s", reg_names[n])
224 case '1':
225 case 'r':
226 reg (insn.rs1);
227 break;
228
229 case '2':
230 reg (insn.rs2);
231 break;
232
233 case 'd':
234 reg (insn.rd);
235 break;
236 #undef reg
237
238 #define freg(n) fprintf (stream, "%%%s", freg_names[n])
239 case 'e':
240 freg (insn.rs1);
241 break;
242
243 case 'f':
244 freg (insn.rs2);
245 break;
246
247 case 'g':
248 freg (insn.rd);
249 break;
250 #undef freg
251
252 #define creg(n) fprintf (stream, "%%c%u", (unsigned int) (n))
253 case 'b':
254 creg (insn.rs1);
255 break;
256
257 case 'c':
258 creg (insn.rs2);
259 break;
260
261 case 'D':
262 creg (insn.rd);
263 break;
264 #undef creg
265
266 case 'h':
267 fprintf (stream, "%%hi(%#x)",
268 (unsigned int) insn.imm22 << 10);
269 break;
270
271 case 'i':
272 {
273 /* We cannot trust the compiler to sign-extend
274 when extracting the bitfield, hence the shifts. */
275 int imm = ((int) insn.imm13 << 19) >> 19;
276
277 /* Check to see whether we have a 1+i, and take
278 note of that fact.
279
280 Note: because of the way we sort the table,
281 we will be matching 1+i rather than i+1,
282 so it is OK to assume that i is after +,
283 not before it. */
284 if (found_plus)
285 imm_added_to_rs1 = 1;
286
287 if (imm <= 9)
288 fprintf (stream, "%d", imm);
289 else
290 fprintf (stream, "%#x", (unsigned) imm);
291 }
292 break;
293
294 case 'L':
295 print_address ((bfd_vma) memaddr + insn.disp30 * 4,
296 stream);
297 break;
298
299 case 'l':
300 if ((insn.code >> 22) == 0)
301 /* Special case for `unimp'. Don't try to turn
302 it's operand into a function offset. */
303 fprintf (stream, "%#x",
304 (unsigned) (((int) insn.disp22 << 10) >> 10));
305 else
306 /* We cannot trust the compiler to sign-extend
307 when extracting the bitfield, hence the shifts. */
308 print_address ((bfd_vma)
309 (memaddr
310 + (((int) insn.disp22 << 10) >> 10) * 4),
311 stream);
312 break;
313
314 case 'A':
315 fprintf (stream, "(%d)", (int) insn.asi);
316 break;
317
318 case 'C':
319 fputs ("%csr", stream);
320 break;
321
322 case 'F':
323 fputs ("%fsr", stream);
324 break;
325
326 case 'p':
327 fputs ("%psr", stream);
328 break;
329
330 case 'q':
331 fputs ("%fq", stream);
332 break;
333
334 case 'Q':
335 fputs ("%cq", stream);
336 break;
337
338 case 't':
339 fputs ("%tbr", stream);
340 break;
341
342 case 'w':
343 fputs ("%wim", stream);
344 break;
345
346 case 'y':
347 fputs ("%y", stream);
348 break;
349 }
350 }
351 }
352
353 /* If we are adding or or'ing something to rs1, then
354 check to see whether the previous instruction was
355 a sethi to the same register as in the sethi.
356 If so, attempt to print the result of the add or
357 or (in this context add and or do the same thing)
358 and its symbolic value. */
359 if (imm_added_to_rs1)
360 {
361 union sparc_insn prev_insn;
362 int errcode;
363
364 memcpy(&prev_insn, buffer -4, sizeof (prev_insn));
365
366 if (errcode == 0)
367 {
368 /* If it is a delayed branch, we need to look at the
369 instruction before the delayed branch. This handles
370 sequences such as
371
372 sethi %o1, %hi(_foo), %o1
373 call _printf
374 or %o1, %lo(_foo), %o1
375 */
376
377 if (is_delayed_branch (prev_insn))
378 memcpy(&prev_insn, buffer - 8, sizeof(prev_insn));
379
380 }
381
382 /* If there was a problem reading memory, then assume
383 the previous instruction was not sethi. */
384 if (errcode == 0)
385 {
386 /* Is it sethi to the same register? */
387 if ((prev_insn.code & 0xc1c00000) == 0x01000000
388 && prev_insn.rd == insn.rs1)
389 {
390 fprintf (stream, "\t! ");
391 /* We cannot trust the compiler to sign-extend
392 when extracting the bitfield, hence the shifts. */
393 print_address (((int) prev_insn.imm22 << 10)
394 | (insn.imm13 << 19) >> 19, stream);
395 }
396 }
397 }
398
399 return sizeof (insn);
400 }
401 }
402
403 fprintf ("%#8x", insn.code);
404 return sizeof (insn);
405 }
406
407
408 /* Compare opcodes A and B. */
409
410 static int
411 compare_opcodes (a, b)
412 char *a, *b;
413 {
414 struct sparc_opcode *op0 = (struct sparc_opcode *) a;
415 struct sparc_opcode *op1 = (struct sparc_opcode *) b;
416 unsigned long int match0 = op0->match, match1 = op1->match;
417 unsigned long int lose0 = op0->lose, lose1 = op1->lose;
418 register unsigned int i;
419
420 /* If a bit is set in both match and lose, there is something
421 wrong with the opcode table. */
422 if (match0 & lose0)
423 {
424 fprintf (stderr, "Internal error: bad sparc-opcode.h: \"%s\", %#.8lx, %#.8lx\n",
425 op0->name, match0, lose0);
426 op0->lose &= ~op0->match;
427 lose0 = op0->lose;
428 }
429
430 if (match1 & lose1)
431 {
432 fprintf (stderr, "Internal error: bad sparc-opcode.h: \"%s\", %#.8lx, %#.8lx\n",
433 op1->name, match1, lose1);
434 op1->lose &= ~op1->match;
435 lose1 = op1->lose;
436 }
437
438 /* Because the bits that are variable in one opcode are constant in
439 another, it is important to order the opcodes in the right order. */
440 for (i = 0; i < 32; ++i)
441 {
442 unsigned long int x = 1 << i;
443 int x0 = (match0 & x) != 0;
444 int x1 = (match1 & x) != 0;
445
446 if (x0 != x1)
447 return x1 - x0;
448 }
449
450 for (i = 0; i < 32; ++i)
451 {
452 unsigned long int x = 1 << i;
453 int x0 = (lose0 & x) != 0;
454 int x1 = (lose1 & x) != 0;
455
456 if (x0 != x1)
457 return x1 - x0;
458 }
459
460 /* They are functionally equal. So as long as the opcode table is
461 valid, we can put whichever one first we want, on aesthetic grounds. */
462 {
463 int length_diff = strlen (op0->args) - strlen (op1->args);
464 if (length_diff != 0)
465 /* Put the one with fewer arguments first. */
466 return length_diff;
467 }
468
469 /* Put 1+i before i+1. */
470 {
471 char *p0 = (char *) index(op0->args, '+');
472 char *p1 = (char *) index(op1->args, '+');
473
474 if (p0 && p1)
475 {
476 /* There is a plus in both operands. Note that a plus
477 sign cannot be the first character in args,
478 so the following [-1]'s are valid. */
479 if (p0[-1] == 'i' && p1[1] == 'i')
480 /* op0 is i+1 and op1 is 1+i, so op1 goes first. */
481 return 1;
482 if (p0[1] == 'i' && p1[-1] == 'i')
483 /* op0 is 1+i and op1 is i+1, so op0 goes first. */
484 return -1;
485 }
486 }
487
488 /* They are, as far as we can tell, identical.
489 Since qsort may have rearranged the table partially, there is
490 no way to tell which one was first in the opcode table as
491 written, so just say there are equal. */
492 return 0;
493 }