* solib.c (elf_locate_base): New function to locate the address
[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 342 case 'k':
3245e377
JK
343 (*info->print_address_func)
344 ((bfd_vma) (memaddr
345 + (((int) insn.disp14 << 18) >> 18) * 4),
346 info);
839df5c3
RP
347 break;
348
5f4d1571 349 case 'G':
3245e377
JK
350 (*info->print_address_func)
351 ((bfd_vma) (memaddr
352 /* We use only 19 of the 21 bits. */
353 + (((int) insn.disp21 << 13) >> 13) * 4),
354 info);
839df5c3
RP
355 break;
356
5f4d1571
MT
357 case '6':
358 case '7':
359 case '8':
360 case '9':
3245e377 361 (*info->fprintf_func) (stream, "fcc%c", *s - '6' + '0');
5f4d1571
MT
362 break;
363
364 case 'z':
3245e377 365 (*info->fprintf_func) (stream, "icc");
5f4d1571
MT
366 break;
367
368 case 'Z':
3245e377 369 (*info->fprintf_func) (stream, "xcc");
5f4d1571 370 break;
93fd00fb
JW
371
372 case 'E':
3245e377 373 (*info->fprintf_func) (stream, "%%ccr");
93fd00fb
JW
374 break;
375
376 case 's':
3245e377 377 (*info->fprintf_func) (stream, "%%fprs");
93fd00fb 378 break;
76d89cb1 379#endif /* NO_V9 */
839df5c3 380
76d89cb1 381 case 'M':
3245e377 382 (*info->fprintf_func) (stream, "%%asr%d", insn.rs1);
839df5c3
RP
383 break;
384
76d89cb1 385 case 'm':
3245e377 386 (*info->fprintf_func) (stream, "%%asr%d", insn.rd);
839df5c3
RP
387 break;
388
76d89cb1 389 case 'L':
3245e377
JK
390 (*info->print_address_func)
391 ((bfd_vma) memaddr + insn.disp30 * 4,
392 info);
2fa0b342
DHW
393 break;
394
395 case 'l':
396 if ((insn.code >> 22) == 0)
397 /* Special case for `unimp'. Don't try to turn
398 it's operand into a function offset. */
3ac166b1
JK
399 (*info->fprintf_func)
400 (stream, "%#x",
401 (int) (((int) insn.disp22 << 10) >> 10));
2fa0b342
DHW
402 else
403 /* We cannot trust the compiler to sign-extend
404 when extracting the bitfield, hence the shifts. */
3245e377
JK
405 (*info->print_address_func)
406 ((bfd_vma) (memaddr
407 + (((int) insn.disp22 << 10) >> 10) * 4),
408 info);
2fa0b342
DHW
409 break;
410
411 case 'A':
3ac166b1 412 (*info->fprintf_func) (stream, "(%d)", (int) insn.asi);
2fa0b342
DHW
413 break;
414
415 case 'C':
3245e377 416 (*info->fprintf_func) (stream, "%%csr");
2fa0b342
DHW
417 break;
418
419 case 'F':
3245e377 420 (*info->fprintf_func) (stream, "%%fsr");
2fa0b342
DHW
421 break;
422
423 case 'p':
3245e377 424 (*info->fprintf_func) (stream, "%%psr");
2fa0b342
DHW
425 break;
426
427 case 'q':
3245e377 428 (*info->fprintf_func) (stream, "%%fq");
2fa0b342
DHW
429 break;
430
431 case 'Q':
3245e377 432 (*info->fprintf_func) (stream, "%%cq");
2fa0b342
DHW
433 break;
434
435 case 't':
3245e377 436 (*info->fprintf_func) (stream, "%%tbr");
2fa0b342
DHW
437 break;
438
439 case 'w':
3245e377 440 (*info->fprintf_func) (stream, "%%wim");
2fa0b342
DHW
441 break;
442
443 case 'y':
3245e377 444 (*info->fprintf_func) (stream, "%%y");
2fa0b342
DHW
445 break;
446 }
447 }
448 }
449
450 /* If we are adding or or'ing something to rs1, then
451 check to see whether the previous instruction was
452 a sethi to the same register as in the sethi.
453 If so, attempt to print the result of the add or
454 or (in this context add and or do the same thing)
455 and its symbolic value. */
456 if (imm_added_to_rs1)
457 {
458 union sparc_insn prev_insn;
3ac166b1 459 int errcode;
2fa0b342 460
3ac166b1
JK
461 errcode =
462 (*info->read_memory_func)
463 (memaddr - 4,
a6cead71 464 (char *)&prev_insn, sizeof (prev_insn), info);
2fa0b342
DHW
465
466 if (errcode == 0)
467 {
468 /* If it is a delayed branch, we need to look at the
469 instruction before the delayed branch. This handles
470 sequences such as
471
472 sethi %o1, %hi(_foo), %o1
473 call _printf
474 or %o1, %lo(_foo), %o1
475 */
476
477 if (is_delayed_branch (prev_insn))
3ac166b1 478 errcode = (*info->read_memory_func)
a6cead71
JK
479 (memaddr - 8, (char *)&prev_insn, sizeof (prev_insn),
480 info);
2fa0b342
DHW
481 }
482
483 /* If there was a problem reading memory, then assume
484 the previous instruction was not sethi. */
485 if (errcode == 0)
486 {
487 /* Is it sethi to the same register? */
488 if ((prev_insn.code & 0xc1c00000) == 0x01000000
489 && prev_insn.rd == insn.rs1)
490 {
3ac166b1 491 (*info->fprintf_func) (stream, "\t! ");
2fa0b342
DHW
492 /* We cannot trust the compiler to sign-extend
493 when extracting the bitfield, hence the shifts. */
3245e377
JK
494 (*info->print_address_func)
495 (((int) prev_insn.imm22 << 10)
496 | (insn.imm13 << 19) >> 19,
497 info);
2fa0b342
DHW
498 }
499 }
500 }
501
502 return sizeof (insn);
503 }
504 }
505
3ac166b1 506 (*info->fprintf_func) (stream, "%#8x", insn.code);
2fa0b342
DHW
507 return sizeof (insn);
508}
509
2fa0b342
DHW
510/* Compare opcodes A and B. */
511
512static int
513compare_opcodes (a, b)
514 char *a, *b;
515{
516 struct sparc_opcode *op0 = (struct sparc_opcode *) a;
517 struct sparc_opcode *op1 = (struct sparc_opcode *) b;
518 unsigned long int match0 = op0->match, match1 = op1->match;
519 unsigned long int lose0 = op0->lose, lose1 = op1->lose;
520 register unsigned int i;
521
522 /* If a bit is set in both match and lose, there is something
523 wrong with the opcode table. */
524 if (match0 & lose0)
525 {
526 fprintf (stderr, "Internal error: bad sparc-opcode.h: \"%s\", %#.8lx, %#.8lx\n",
527 op0->name, match0, lose0);
528 op0->lose &= ~op0->match;
529 lose0 = op0->lose;
530 }
531
532 if (match1 & lose1)
533 {
534 fprintf (stderr, "Internal error: bad sparc-opcode.h: \"%s\", %#.8lx, %#.8lx\n",
535 op1->name, match1, lose1);
536 op1->lose &= ~op1->match;
537 lose1 = op1->lose;
538 }
539
540 /* Because the bits that are variable in one opcode are constant in
541 another, it is important to order the opcodes in the right order. */
542 for (i = 0; i < 32; ++i)
543 {
544 unsigned long int x = 1 << i;
545 int x0 = (match0 & x) != 0;
546 int x1 = (match1 & x) != 0;
547
548 if (x0 != x1)
549 return x1 - x0;
550 }
551
552 for (i = 0; i < 32; ++i)
553 {
554 unsigned long int x = 1 << i;
555 int x0 = (lose0 & x) != 0;
556 int x1 = (lose1 & x) != 0;
557
558 if (x0 != x1)
559 return x1 - x0;
560 }
561
562 /* They are functionally equal. So as long as the opcode table is
563 valid, we can put whichever one first we want, on aesthetic grounds. */
3ac166b1
JK
564
565 /* Our first aesthetic ground is that aliases defer to real insns. */
566 {
567 int alias_diff = (op0->flags & F_ALIAS) - (op1->flags & F_ALIAS);
568 if (alias_diff != 0)
569 /* Put the one that isn't an alias first. */
570 return alias_diff;
571 }
572
573 /* Except for aliases, two "identical" instructions had
574 better have the same opcode. This is a sanity check on the table. */
575 i = strcmp (op0->name, op1->name);
576 if (i)
577 if (op0->flags & F_ALIAS) /* If they're both aliases, be arbitrary. */
578 return i;
579 else
580 fprintf (stderr,
581 "Internal error: bad sparc-opcode.h: \"%s\" == \"%s\"\n",
582 op0->name, op1->name);
583
584 /* Fewer arguments are preferred. */
2fa0b342
DHW
585 {
586 int length_diff = strlen (op0->args) - strlen (op1->args);
587 if (length_diff != 0)
588 /* Put the one with fewer arguments first. */
589 return length_diff;
590 }
591
592 /* Put 1+i before i+1. */
593 {
c005c66c
JG
594 char *p0 = (char *) strchr(op0->args, '+');
595 char *p1 = (char *) strchr(op1->args, '+');
2fa0b342
DHW
596
597 if (p0 && p1)
598 {
599 /* There is a plus in both operands. Note that a plus
600 sign cannot be the first character in args,
601 so the following [-1]'s are valid. */
602 if (p0[-1] == 'i' && p1[1] == 'i')
603 /* op0 is i+1 and op1 is 1+i, so op1 goes first. */
604 return 1;
605 if (p0[1] == 'i' && p1[-1] == 'i')
606 /* op0 is 1+i and op1 is i+1, so op0 goes first. */
607 return -1;
608 }
609 }
610
611 /* They are, as far as we can tell, identical.
612 Since qsort may have rearranged the table partially, there is
613 no way to tell which one was first in the opcode table as
614 written, so just say there are equal. */
615 return 0;
616}
This page took 0.128404 seconds and 4 git commands to generate.