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