*** empty log message ***
[deliverable/binutils-gdb.git] / binutils / sparc-pinsn.c
CommitLineData
2fa0b342 1/* disassemble sparc instructions for objdump
d8474a9b 2 Copyright (C) 1986, 1987, 1989, 1991 Free Software Foundation, Inc.
2fa0b342
DHW
3
4
5This file is part of the binutils.
6
7The binutils are free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
d8474a9b 9the Free Software Foundation; either version 2, or (at your option)
2fa0b342
DHW
10any later version.
11
12The binutils are distributed in the hope that they will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with the binutils; see the file COPYING. If not, write to
19the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
20
2a5f387b 21/* $Id$ */
2fa0b342 22
2a5f387b 23#include "bfd.h"
2fa0b342 24#include "sysdep.h"
17e6f61f 25#include <stdio.h>
4aa58a0a 26#include "opcode/sparc.h"
5a77e916 27#include "objdump.h"
2fa0b342
DHW
28extern int print_address();
29
30static char *reg_names[] =
31 { "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7",
32 "o0", "o1", "o2", "o3", "o4", "o5", "sp", "o7",
33 "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7",
34 "i0", "i1", "i2", "i3", "i4", "i5", "fp", "i7",
35 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
36 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
37 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
38 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
39 "y", "psr", "wim", "tbr", "pc", "npc", "fpsr", "cpsr" };
40
41#define freg_names (&reg_names[4 * 8])
42
43union sparc_insn
44 {
45 unsigned long int code;
46 struct
47 {
839df5c3
RP
48 unsigned int _OP:2;
49#define op ldst._OP
50 unsigned int _RD:5;
51#define rd ldst._RD
2fa0b342 52 unsigned int op3:6;
839df5c3
RP
53 unsigned int _RS1:5;
54#define rs1 ldst._RS1
2fa0b342 55 unsigned int i:1;
839df5c3
RP
56 unsigned int _ASI:8;
57#define asi ldst._ASI
58 unsigned int _RS2:5;
59#define rs2 ldst._RS2
2fa0b342
DHW
60#define shcnt rs2
61 } ldst;
62 struct
63 {
839df5c3 64 unsigned int _OP:2, _RD:5, op3:6, _RS1:5, i:1;
2fa0b342
DHW
65 unsigned int IMM13:13;
66#define imm13 IMM13.IMM13
67 } IMM13;
68 struct
69 {
839df5c3 70 unsigned int _OP:2;
2fa0b342
DHW
71 unsigned int a:1;
72 unsigned int cond:4;
73 unsigned int op2:3;
74 unsigned int DISP22:22;
75#define disp22 branch.DISP22
76 } branch;
839df5c3
RP
77#ifndef NO_V9
78 struct
79 {
80 unsigned int _OP:2, _RD:5, op3:6, _RS1:5;
81 unsigned int DISP14:14;
82#define disp14 DISP14.DISP14
83 } DISP14;
84 struct
85 {
86 unsigned int _OP:2;
87 unsigned int a:1;
88 unsigned int cond:4;
89 unsigned int op2:3;
90 unsigned int p:1;
91 unsigned int DISP21:21;
c64cf848 92#define disp21 branch2.DISP21
839df5c3
RP
93 } branch2;
94#endif /* NO_V9 */
95
2fa0b342
DHW
96#define imm22 disp22
97 struct
98 {
839df5c3 99 unsigned int _OP:2;
320484bf
RP
100 unsigned int _DISP30:30;
101#define disp30 call._DISP30
2fa0b342
DHW
102 } call;
103 };
104
105/* Nonzero if INSN is the opcode for a delayed branch. */
106static int
107is_delayed_branch (insn)
108 union sparc_insn insn;
109{
110 unsigned int i;
111
112 for (i = 0; i < NUMOPCODES; ++i)
113 {
114 const struct sparc_opcode *opcode = &sparc_opcodes[i];
115 if ((opcode->match & insn.code) == opcode->match
116 && (opcode->lose & insn.code) == 0
bb50293f 117 && (opcode->flags&F_DELAYED))
2fa0b342
DHW
118 return 1;
119 }
120 return 0;
121}
122
123static int opcodes_sorted = 0;
124
125/* Print one instruction from MEMADDR on STREAM. */
126int
127print_insn_sparc (memaddr, buffer, stream)
128 bfd_vma memaddr;
129 bfd_byte *buffer;
130 FILE *stream;
131
132{
133 union sparc_insn insn;
134
135 register unsigned int i;
136
137 if (!opcodes_sorted)
138 {
139 static int compare_opcodes ();
140 qsort ((char *) sparc_opcodes, NUMOPCODES,
141 sizeof (sparc_opcodes[0]), compare_opcodes);
142 opcodes_sorted = 1;
143 }
144
145memcpy(&insn,buffer, sizeof (insn));
146
147 for (i = 0; i < NUMOPCODES; ++i)
148 {
149 const struct sparc_opcode *opcode = &sparc_opcodes[i];
150 if ((opcode->match & insn.code) == opcode->match
151 && (opcode->lose & insn.code) == 0)
152 {
153 /* Nonzero means that we have found an instruction which has
154 the effect of adding or or'ing the imm13 field to rs1. */
155 int imm_added_to_rs1 = 0;
156
157 /* Nonzero means that we have found a plus sign in the args
158 field of the opcode table. */
159 int found_plus = 0;
160
161 /* Do we have an 'or' instruction where rs1 is the same
162 as rsd, and which has the i bit set? */
163 if (opcode->match == 0x80102000
164 && insn.rs1 == insn.rd)
165 imm_added_to_rs1 = 1;
166
167 if (index (opcode->args, 'S') != 0)
168 /* Reject the special case for `set'.
169 The real `sethi' will match. */
170 continue;
171 if (insn.rs1 != insn.rd
172 && index (opcode->args, 'r') != 0)
173 /* Can't do simple format if source and dest are different. */
174 continue;
175
176 fputs (opcode->name, stream);
177
178 {
179 register const char *s;
180
181 if (opcode->args[0] != ',')
182 fputs (" ", stream);
76d89cb1
MT
183 for (s = opcode->args; *s != '\0'; ++s)
184 {
185 while (*s == ',')
186 {
187 fputs (",", stream);
188 ++s;
189
190 switch (*s) {
191 case 'a':
192 fputs ("a", stream);
193 ++s;
194 continue;
839df5c3 195#ifndef NO_V9
76d89cb1
MT
196 case 'N':
197 fputs("pn", stream);
198 ++s;
199 continue;
200
201 case 'T':
202 fputs("pt", stream);
203 ++s;
204 continue;
205#endif /* NO_V9 */
206
207 default:
208 break;
209 } /* switch on arg */
210 } /* while there are comma started args */
839df5c3
RP
211
212 fputs (" ", stream);
213
2fa0b342
DHW
214 switch (*s)
215 {
216 case '+':
217 found_plus = 1;
218
219 /* note fall-through */
220 default:
221 fprintf (stream, "%c", *s);
222 break;
223
224 case '#':
225 fputs ("0", stream);
226 break;
227
228#define reg(n) fprintf (stream, "%%%s", reg_names[n])
229 case '1':
230 case 'r':
231 reg (insn.rs1);
232 break;
233
234 case '2':
235 reg (insn.rs2);
236 break;
237
238 case 'd':
239 reg (insn.rd);
240 break;
241#undef reg
242
243#define freg(n) fprintf (stream, "%%%s", freg_names[n])
244 case 'e':
245 freg (insn.rs1);
246 break;
247
248 case 'f':
249 freg (insn.rs2);
250 break;
251
252 case 'g':
253 freg (insn.rd);
254 break;
255#undef freg
256
257#define creg(n) fprintf (stream, "%%c%u", (unsigned int) (n))
258 case 'b':
259 creg (insn.rs1);
260 break;
261
262 case 'c':
263 creg (insn.rs2);
264 break;
265
266 case 'D':
267 creg (insn.rd);
268 break;
269#undef creg
270
271 case 'h':
272 fprintf (stream, "%%hi(%#x)",
76d89cb1 273 (unsigned int) insn.imm22 << 10);
2fa0b342
DHW
274 break;
275
276 case 'i':
277 {
278 /* We cannot trust the compiler to sign-extend
279 when extracting the bitfield, hence the shifts. */
280 int imm = ((int) insn.imm13 << 19) >> 19;
281
282 /* Check to see whether we have a 1+i, and take
283 note of that fact.
76d89cb1 284
2fa0b342
DHW
285 Note: because of the way we sort the table,
286 we will be matching 1+i rather than i+1,
287 so it is OK to assume that i is after +,
288 not before it. */
289 if (found_plus)
290 imm_added_to_rs1 = 1;
291
292 if (imm <= 9)
293 fprintf (stream, "%d", imm);
294 else
295 fprintf (stream, "%#x", (unsigned) imm);
296 }
297 break;
298
839df5c3
RP
299#ifndef NO_V9
300 case 'k':
301 print_address ((bfd_vma)
302 (memaddr
303 + (((int) insn.disp14 << 18) >> 18) * 4),
304 stream);
305 break;
306
5f4d1571 307 case 'G':
839df5c3
RP
308 print_address ((bfd_vma)
309 (memaddr
5f4d1571
MT
310 /* We use only 19 of the 21 bits. */
311 + (((int) insn.disp21 << 13) >> 13) * 4),
839df5c3
RP
312 stream);
313 break;
314
76d89cb1 315 case 'Y':
839df5c3
RP
316 fputs ("%amr", stream);
317 break;
318
5f4d1571
MT
319 case '6':
320 case '7':
321 case '8':
322 case '9':
323 fprintf (stream, "fcc%c", *s - '6' + '0');
324 break;
325
326 case 'z':
327 fputs ("icc", stream);
328 break;
329
330 case 'Z':
331 fputs ("xcc", stream);
332 break;
76d89cb1 333#endif /* NO_V9 */
839df5c3 334
76d89cb1 335 case 'M':
839df5c3
RP
336 fprintf(stream, "%%asr%d", insn.rs1);
337 break;
338
76d89cb1 339 case 'm':
839df5c3
RP
340 fprintf(stream, "%%asr%d", insn.rd);
341 break;
342
76d89cb1 343 case 'L':
2fa0b342
DHW
344 print_address ((bfd_vma) memaddr + insn.disp30 * 4,
345 stream);
346 break;
347
348 case 'l':
349 if ((insn.code >> 22) == 0)
350 /* Special case for `unimp'. Don't try to turn
351 it's operand into a function offset. */
352 fprintf (stream, "%#x",
76d89cb1 353 (unsigned) (((int) insn.disp22 << 10) >> 10));
2fa0b342
DHW
354 else
355 /* We cannot trust the compiler to sign-extend
356 when extracting the bitfield, hence the shifts. */
357 print_address ((bfd_vma)
358 (memaddr
359 + (((int) insn.disp22 << 10) >> 10) * 4),
360 stream);
361 break;
362
363 case 'A':
364 fprintf (stream, "(%d)", (int) insn.asi);
365 break;
366
367 case 'C':
368 fputs ("%csr", stream);
369 break;
370
371 case 'F':
372 fputs ("%fsr", stream);
373 break;
374
375 case 'p':
376 fputs ("%psr", stream);
377 break;
378
379 case 'q':
380 fputs ("%fq", stream);
381 break;
382
383 case 'Q':
384 fputs ("%cq", stream);
385 break;
386
387 case 't':
388 fputs ("%tbr", stream);
389 break;
390
391 case 'w':
392 fputs ("%wim", stream);
393 break;
394
395 case 'y':
396 fputs ("%y", stream);
397 break;
398 }
399 }
400 }
401
402 /* If we are adding or or'ing something to rs1, then
403 check to see whether the previous instruction was
404 a sethi to the same register as in the sethi.
405 If so, attempt to print the result of the add or
406 or (in this context add and or do the same thing)
407 and its symbolic value. */
408 if (imm_added_to_rs1)
409 {
410 union sparc_insn prev_insn;
5a77e916 411 int errcode = 0;
2fa0b342
DHW
412
413 memcpy(&prev_insn, buffer -4, sizeof (prev_insn));
414
415 if (errcode == 0)
416 {
417 /* If it is a delayed branch, we need to look at the
418 instruction before the delayed branch. This handles
419 sequences such as
420
421 sethi %o1, %hi(_foo), %o1
422 call _printf
423 or %o1, %lo(_foo), %o1
424 */
425
426 if (is_delayed_branch (prev_insn))
427 memcpy(&prev_insn, buffer - 8, sizeof(prev_insn));
428
429 }
430
431 /* If there was a problem reading memory, then assume
432 the previous instruction was not sethi. */
433 if (errcode == 0)
434 {
435 /* Is it sethi to the same register? */
436 if ((prev_insn.code & 0xc1c00000) == 0x01000000
437 && prev_insn.rd == insn.rs1)
438 {
439 fprintf (stream, "\t! ");
440 /* We cannot trust the compiler to sign-extend
441 when extracting the bitfield, hence the shifts. */
442 print_address (((int) prev_insn.imm22 << 10)
443 | (insn.imm13 << 19) >> 19, stream);
444 }
445 }
446 }
447
448 return sizeof (insn);
449 }
450 }
451
75a082e2 452 fprintf (stream, "%#8x", insn.code);
2fa0b342
DHW
453 return sizeof (insn);
454}
455
456
457/* Compare opcodes A and B. */
458
459static int
460compare_opcodes (a, b)
461 char *a, *b;
462{
463 struct sparc_opcode *op0 = (struct sparc_opcode *) a;
464 struct sparc_opcode *op1 = (struct sparc_opcode *) b;
465 unsigned long int match0 = op0->match, match1 = op1->match;
466 unsigned long int lose0 = op0->lose, lose1 = op1->lose;
467 register unsigned int i;
468
469 /* If a bit is set in both match and lose, there is something
470 wrong with the opcode table. */
471 if (match0 & lose0)
472 {
473 fprintf (stderr, "Internal error: bad sparc-opcode.h: \"%s\", %#.8lx, %#.8lx\n",
474 op0->name, match0, lose0);
475 op0->lose &= ~op0->match;
476 lose0 = op0->lose;
477 }
478
479 if (match1 & lose1)
480 {
481 fprintf (stderr, "Internal error: bad sparc-opcode.h: \"%s\", %#.8lx, %#.8lx\n",
482 op1->name, match1, lose1);
483 op1->lose &= ~op1->match;
484 lose1 = op1->lose;
485 }
486
487 /* Because the bits that are variable in one opcode are constant in
488 another, it is important to order the opcodes in the right order. */
489 for (i = 0; i < 32; ++i)
490 {
491 unsigned long int x = 1 << i;
492 int x0 = (match0 & x) != 0;
493 int x1 = (match1 & x) != 0;
494
495 if (x0 != x1)
496 return x1 - x0;
497 }
498
499 for (i = 0; i < 32; ++i)
500 {
501 unsigned long int x = 1 << i;
502 int x0 = (lose0 & x) != 0;
503 int x1 = (lose1 & x) != 0;
504
505 if (x0 != x1)
506 return x1 - x0;
507 }
508
509 /* They are functionally equal. So as long as the opcode table is
510 valid, we can put whichever one first we want, on aesthetic grounds. */
511 {
512 int length_diff = strlen (op0->args) - strlen (op1->args);
513 if (length_diff != 0)
514 /* Put the one with fewer arguments first. */
515 return length_diff;
516 }
517
518 /* Put 1+i before i+1. */
519 {
520 char *p0 = (char *) index(op0->args, '+');
521 char *p1 = (char *) index(op1->args, '+');
522
523 if (p0 && p1)
524 {
525 /* There is a plus in both operands. Note that a plus
526 sign cannot be the first character in args,
527 so the following [-1]'s are valid. */
528 if (p0[-1] == 'i' && p1[1] == 'i')
529 /* op0 is i+1 and op1 is 1+i, so op1 goes first. */
530 return 1;
531 if (p0[1] == 'i' && p1[-1] == 'i')
532 /* op0 is 1+i and op1 is i+1, so op0 goes first. */
533 return -1;
534 }
535 }
536
537 /* They are, as far as we can tell, identical.
538 Since qsort may have rearranged the table partially, there is
539 no way to tell which one was first in the opcode table as
540 written, so just say there are equal. */
541 return 0;
542}
This page took 0.059445 seconds and 4 git commands to generate.