source: trunk/src/binutils/opcodes/sparc-dis.c@ 167

Last change on this file since 167 was 10, checked in by bird, 23 years ago

Initial revision

  • Property cvs2svn:cvs-rev set to 1.1
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 26.5 KB
Line 
1/* Print SPARC instructions.
2 Copyright 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
3 2000 Free Software Foundation, Inc.
4
5This program is free software; you can redistribute it and/or modify
6it under the terms of the GNU General Public License as published by
7the Free Software Foundation; either version 2 of the License, or
8(at your option) any later version.
9
10This program is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program; if not, write to the Free Software
17Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
18
19#include <stdio.h>
20
21#include "sysdep.h"
22#include "opcode/sparc.h"
23#include "dis-asm.h"
24#include "libiberty.h"
25#include "opintl.h"
26
27/* Bitmask of v9 architectures. */
28#define MASK_V9 ((1 << SPARC_OPCODE_ARCH_V9) \
29 | (1 << SPARC_OPCODE_ARCH_V9A) \
30 | (1 << SPARC_OPCODE_ARCH_V9B))
31/* 1 if INSN is for v9 only. */
32#define V9_ONLY_P(insn) (! ((insn)->architecture & ~MASK_V9))
33/* 1 if INSN is for v9. */
34#define V9_P(insn) (((insn)->architecture & MASK_V9) != 0)
35
36/* The sorted opcode table. */
37static const struct sparc_opcode **sorted_opcodes;
38
39/* For faster lookup, after insns are sorted they are hashed. */
40/* ??? I think there is room for even more improvement. */
41
42#define HASH_SIZE 256
43/* It is important that we only look at insn code bits as that is how the
44 opcode table is hashed. OPCODE_BITS is a table of valid bits for each
45 of the main types (0,1,2,3). */
46static int opcode_bits[4] = { 0x01c00000, 0x0, 0x01f80000, 0x01f80000 };
47#define HASH_INSN(INSN) \
48 ((((INSN) >> 24) & 0xc0) | (((INSN) & opcode_bits[((INSN) >> 30) & 3]) >> 19))
49struct opcode_hash {
50 struct opcode_hash *next;
51 const struct sparc_opcode *opcode;
52};
53static struct opcode_hash *opcode_hash_table[HASH_SIZE];
54
55static void build_hash_table
56 PARAMS ((const struct sparc_opcode **, struct opcode_hash **, int));
57static int is_delayed_branch PARAMS ((unsigned long));
58static int compare_opcodes PARAMS ((const PTR, const PTR));
59static int compute_arch_mask PARAMS ((unsigned long));
60
61/* Sign-extend a value which is N bits long. */
62#define SEX(value, bits) \
63 ((((int)(value)) << ((8 * sizeof (int)) - bits)) \
64 >> ((8 * sizeof (int)) - bits) )
65
66static char *reg_names[] =
67{ "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7",
68 "o0", "o1", "o2", "o3", "o4", "o5", "sp", "o7",
69 "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7",
70 "i0", "i1", "i2", "i3", "i4", "i5", "fp", "i7",
71 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
72 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
73 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
74 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
75 "f32", "f33", "f34", "f35", "f36", "f37", "f38", "f39",
76 "f40", "f41", "f42", "f43", "f44", "f45", "f46", "f47",
77 "f48", "f49", "f50", "f51", "f52", "f53", "f54", "f55",
78 "f56", "f57", "f58", "f59", "f60", "f61", "f62", "f63",
79/* psr, wim, tbr, fpsr, cpsr are v8 only. */
80 "y", "psr", "wim", "tbr", "pc", "npc", "fpsr", "cpsr"
81};
82
83#define freg_names (&reg_names[4 * 8])
84
85/* These are ordered according to there register number in
86 rdpr and wrpr insns. */
87static char *v9_priv_reg_names[] =
88{
89 "tpc", "tnpc", "tstate", "tt", "tick", "tba", "pstate", "tl",
90 "pil", "cwp", "cansave", "canrestore", "cleanwin", "otherwin",
91 "wstate", "fq"
92 /* "ver" - special cased */
93};
94
95/* These are ordered according to there register number in
96 rd and wr insns (-16). */
97static char *v9a_asr_reg_names[] =
98{
99 "pcr", "pic", "dcr", "gsr", "set_softint", "clear_softint",
100 "softint", "tick_cmpr", "sys_tick", "sys_tick_cmpr"
101};
102
103/* Macros used to extract instruction fields. Not all fields have
104 macros defined here, only those which are actually used. */
105
106#define X_RD(i) (((i) >> 25) & 0x1f)
107#define X_RS1(i) (((i) >> 14) & 0x1f)
108#define X_LDST_I(i) (((i) >> 13) & 1)
109#define X_ASI(i) (((i) >> 5) & 0xff)
110#define X_RS2(i) (((i) >> 0) & 0x1f)
111#define X_IMM(i,n) (((i) >> 0) & ((1 << (n)) - 1))
112#define X_SIMM(i,n) SEX (X_IMM ((i), (n)), (n))
113#define X_DISP22(i) (((i) >> 0) & 0x3fffff)
114#define X_IMM22(i) X_DISP22 (i)
115#define X_DISP30(i) (((i) >> 0) & 0x3fffffff)
116
117/* These are for v9. */
118#define X_DISP16(i) (((((i) >> 20) & 3) << 14) | (((i) >> 0) & 0x3fff))
119#define X_DISP19(i) (((i) >> 0) & 0x7ffff)
120#define X_MEMBAR(i) ((i) & 0x7f)
121
122/* Here is the union which was used to extract instruction fields
123 before the shift and mask macros were written.
124
125 union sparc_insn
126 {
127 unsigned long int code;
128 struct
129 {
130 unsigned int anop:2;
131 #define op ldst.anop
132 unsigned int anrd:5;
133 #define rd ldst.anrd
134 unsigned int op3:6;
135 unsigned int anrs1:5;
136 #define rs1 ldst.anrs1
137 unsigned int i:1;
138 unsigned int anasi:8;
139 #define asi ldst.anasi
140 unsigned int anrs2:5;
141 #define rs2 ldst.anrs2
142 #define shcnt rs2
143 } ldst;
144 struct
145 {
146 unsigned int anop:2, anrd:5, op3:6, anrs1:5, i:1;
147 unsigned int IMM13:13;
148 #define imm13 IMM13.IMM13
149 } IMM13;
150 struct
151 {
152 unsigned int anop:2;
153 unsigned int a:1;
154 unsigned int cond:4;
155 unsigned int op2:3;
156 unsigned int DISP22:22;
157 #define disp22 branch.DISP22
158 #define imm22 disp22
159 } branch;
160 struct
161 {
162 unsigned int anop:2;
163 unsigned int a:1;
164 unsigned int z:1;
165 unsigned int rcond:3;
166 unsigned int op2:3;
167 unsigned int DISP16HI:2;
168 unsigned int p:1;
169 unsigned int _rs1:5;
170 unsigned int DISP16LO:14;
171 } branch16;
172 struct
173 {
174 unsigned int anop:2;
175 unsigned int adisp30:30;
176 #define disp30 call.adisp30
177 } call;
178 };
179
180 */
181
182/* Nonzero if INSN is the opcode for a delayed branch. */
183static int
184is_delayed_branch (insn)
185 unsigned long insn;
186{
187 struct opcode_hash *op;
188
189 for (op = opcode_hash_table[HASH_INSN (insn)]; op; op = op->next)
190 {
191 CONST struct sparc_opcode *opcode = op->opcode;
192 if ((opcode->match & insn) == opcode->match
193 && (opcode->lose & insn) == 0)
194 return (opcode->flags & F_DELAYED);
195 }
196 return 0;
197}
198
199/* extern void qsort (); */
200
201/* Records current mask of SPARC_OPCODE_ARCH_FOO values, used to pass value
202 to compare_opcodes. */
203static unsigned int current_arch_mask;
204
205/* Print one instruction from MEMADDR on INFO->STREAM.
206
207 We suffix the instruction with a comment that gives the absolute
208 address involved, as well as its symbolic form, if the instruction
209 is preceded by a findable `sethi' and it either adds an immediate
210 displacement to that register, or it is an `add' or `or' instruction
211 on that register. */
212
213int
214print_insn_sparc (memaddr, info)
215 bfd_vma memaddr;
216 disassemble_info *info;
217{
218 FILE *stream = info->stream;
219 bfd_byte buffer[4];
220 unsigned long insn;
221 register struct opcode_hash *op;
222 /* Nonzero of opcode table has been initialized. */
223 static int opcodes_initialized = 0;
224 /* bfd mach number of last call. */
225 static unsigned long current_mach = 0;
226 bfd_vma (*getword) PARAMS ((const unsigned char *));
227
228 if (!opcodes_initialized
229 || info->mach != current_mach)
230 {
231 int i;
232
233 current_arch_mask = compute_arch_mask (info->mach);
234
235 if (!opcodes_initialized)
236 sorted_opcodes = (const struct sparc_opcode **)
237 xmalloc (sparc_num_opcodes * sizeof (struct sparc_opcode *));
238 /* Reset the sorted table so we can resort it. */
239 for (i = 0; i < sparc_num_opcodes; ++i)
240 sorted_opcodes[i] = &sparc_opcodes[i];
241 qsort ((char *) sorted_opcodes, sparc_num_opcodes,
242 sizeof (sorted_opcodes[0]), compare_opcodes);
243
244 build_hash_table (sorted_opcodes, opcode_hash_table, sparc_num_opcodes);
245 current_mach = info->mach;
246 opcodes_initialized = 1;
247 }
248
249 {
250 int status =
251 (*info->read_memory_func) (memaddr, buffer, sizeof (buffer), info);
252 if (status != 0)
253 {
254 (*info->memory_error_func) (status, memaddr, info);
255 return -1;
256 }
257 }
258
259 /* On SPARClite variants such as DANlite (sparc86x), instructions
260 are always big-endian even when the machine is in little-endian mode. */
261 if (info->endian == BFD_ENDIAN_BIG || info->mach == bfd_mach_sparc_sparclite)
262 getword = bfd_getb32;
263 else
264 getword = bfd_getl32;
265
266 insn = getword (buffer);
267
268 info->insn_info_valid = 1; /* We do return this info */
269 info->insn_type = dis_nonbranch; /* Assume non branch insn */
270 info->branch_delay_insns = 0; /* Assume no delay */
271 info->target = 0; /* Assume no target known */
272
273 for (op = opcode_hash_table[HASH_INSN (insn)]; op; op = op->next)
274 {
275 CONST struct sparc_opcode *opcode = op->opcode;
276
277 /* If the insn isn't supported by the current architecture, skip it. */
278 if (! (opcode->architecture & current_arch_mask))
279 continue;
280
281 if ((opcode->match & insn) == opcode->match
282 && (opcode->lose & insn) == 0)
283 {
284 /* Nonzero means that we have found an instruction which has
285 the effect of adding or or'ing the imm13 field to rs1. */
286 int imm_added_to_rs1 = 0;
287 int imm_ored_to_rs1 = 0;
288
289 /* Nonzero means that we have found a plus sign in the args
290 field of the opcode table. */
291 int found_plus = 0;
292
293 /* Nonzero means we have an annulled branch. */
294 int is_annulled = 0;
295
296 /* Do we have an `add' or `or' instruction combining an
297 immediate with rs1? */
298 if (opcode->match == 0x80102000) /* or */
299 imm_ored_to_rs1 = 1;
300 if (opcode->match == 0x80002000) /* add */
301 imm_added_to_rs1 = 1;
302
303 if (X_RS1 (insn) != X_RD (insn)
304 && strchr (opcode->args, 'r') != 0)
305 /* Can't do simple format if source and dest are different. */
306 continue;
307 if (X_RS2 (insn) != X_RD (insn)
308 && strchr (opcode->args, 'O') != 0)
309 /* Can't do simple format if source and dest are different. */
310 continue;
311
312 (*info->fprintf_func) (stream, opcode->name);
313
314 {
315 register CONST char *s;
316
317 if (opcode->args[0] != ',')
318 (*info->fprintf_func) (stream, " ");
319 for (s = opcode->args; *s != '\0'; ++s)
320 {
321 while (*s == ',')
322 {
323 (*info->fprintf_func) (stream, ",");
324 ++s;
325 switch (*s) {
326 case 'a':
327 (*info->fprintf_func) (stream, "a");
328 is_annulled = 1;
329 ++s;
330 continue;
331 case 'N':
332 (*info->fprintf_func) (stream, "pn");
333 ++s;
334 continue;
335
336 case 'T':
337 (*info->fprintf_func) (stream, "pt");
338 ++s;
339 continue;
340
341 default:
342 break;
343 } /* switch on arg */
344 } /* while there are comma started args */
345
346 (*info->fprintf_func) (stream, " ");
347
348 switch (*s)
349 {
350 case '+':
351 found_plus = 1;
352
353 /* note fall-through */
354 default:
355 (*info->fprintf_func) (stream, "%c", *s);
356 break;
357
358 case '#':
359 (*info->fprintf_func) (stream, "0");
360 break;
361
362#define reg(n) (*info->fprintf_func) (stream, "%%%s", reg_names[n])
363 case '1':
364 case 'r':
365 reg (X_RS1 (insn));
366 break;
367
368 case '2':
369 case 'O':
370 reg (X_RS2 (insn));
371 break;
372
373 case 'd':
374 reg (X_RD (insn));
375 break;
376#undef reg
377
378#define freg(n) (*info->fprintf_func) (stream, "%%%s", freg_names[n])
379#define fregx(n) (*info->fprintf_func) (stream, "%%%s", freg_names[((n) & ~1) | (((n) & 1) << 5)])
380 case 'e':
381 freg (X_RS1 (insn));
382 break;
383 case 'v': /* double/even */
384 case 'V': /* quad/multiple of 4 */
385 fregx (X_RS1 (insn));
386 break;
387
388 case 'f':
389 freg (X_RS2 (insn));
390 break;
391 case 'B': /* double/even */
392 case 'R': /* quad/multiple of 4 */
393 fregx (X_RS2 (insn));
394 break;
395
396 case 'g':
397 freg (X_RD (insn));
398 break;
399 case 'H': /* double/even */
400 case 'J': /* quad/multiple of 4 */
401 fregx (X_RD (insn));
402 break;
403#undef freg
404#undef fregx
405
406#define creg(n) (*info->fprintf_func) (stream, "%%c%u", (unsigned int) (n))
407 case 'b':
408 creg (X_RS1 (insn));
409 break;
410
411 case 'c':
412 creg (X_RS2 (insn));
413 break;
414
415 case 'D':
416 creg (X_RD (insn));
417 break;
418#undef creg
419
420 case 'h':
421 (*info->fprintf_func) (stream, "%%hi(%#x)",
422 (0xFFFFFFFF
423 & ((int) X_IMM22 (insn) << 10)));
424 break;
425
426 case 'i': /* 13 bit immediate */
427 case 'I': /* 11 bit immediate */
428 case 'j': /* 10 bit immediate */
429 {
430 int imm;
431
432 if (*s == 'i')
433 imm = X_SIMM (insn, 13);
434 else if (*s == 'I')
435 imm = X_SIMM (insn, 11);
436 else
437 imm = X_SIMM (insn, 10);
438
439 /* Check to see whether we have a 1+i, and take
440 note of that fact.
441
442 Note: because of the way we sort the table,
443 we will be matching 1+i rather than i+1,
444 so it is OK to assume that i is after +,
445 not before it. */
446 if (found_plus)
447 imm_added_to_rs1 = 1;
448
449 if (imm <= 9)
450 (*info->fprintf_func) (stream, "%d", imm);
451 else
452 (*info->fprintf_func) (stream, "%#x", imm);
453 }
454 break;
455
456 case 'X': /* 5 bit unsigned immediate */
457 case 'Y': /* 6 bit unsigned immediate */
458 {
459 int imm = X_IMM (insn, *s == 'X' ? 5 : 6);
460
461 if (imm <= 9)
462 (info->fprintf_func) (stream, "%d", imm);
463 else
464 (info->fprintf_func) (stream, "%#x", (unsigned) imm);
465 }
466 break;
467
468 case '3':
469 (info->fprintf_func) (stream, "%d", X_IMM (insn, 3));
470 break;
471
472 case 'K':
473 {
474 int mask = X_MEMBAR (insn);
475 int bit = 0x40, printed_one = 0;
476 const char *name;
477
478 if (mask == 0)
479 (info->fprintf_func) (stream, "0");
480 else
481 while (bit)
482 {
483 if (mask & bit)
484 {
485 if (printed_one)
486 (info->fprintf_func) (stream, "|");
487 name = sparc_decode_membar (bit);
488 (info->fprintf_func) (stream, "%s", name);
489 printed_one = 1;
490 }
491 bit >>= 1;
492 }
493 break;
494 }
495
496 case 'k':
497 info->target = memaddr + SEX (X_DISP16 (insn), 16) * 4;
498 (*info->print_address_func) (info->target, info);
499 break;
500
501 case 'G':
502 info->target = memaddr + SEX (X_DISP19 (insn), 19) * 4;
503 (*info->print_address_func) (info->target, info);
504 break;
505
506 case '6':
507 case '7':
508 case '8':
509 case '9':
510 (*info->fprintf_func) (stream, "%%fcc%c", *s - '6' + '0');
511 break;
512
513 case 'z':
514 (*info->fprintf_func) (stream, "%%icc");
515 break;
516
517 case 'Z':
518 (*info->fprintf_func) (stream, "%%xcc");
519 break;
520
521 case 'E':
522 (*info->fprintf_func) (stream, "%%ccr");
523 break;
524
525 case 's':
526 (*info->fprintf_func) (stream, "%%fprs");
527 break;
528
529 case 'o':
530 (*info->fprintf_func) (stream, "%%asi");
531 break;
532
533 case 'W':
534 (*info->fprintf_func) (stream, "%%tick");
535 break;
536
537 case 'P':
538 (*info->fprintf_func) (stream, "%%pc");
539 break;
540
541 case '?':
542 if (X_RS1 (insn) == 31)
543 (*info->fprintf_func) (stream, "%%ver");
544 else if ((unsigned) X_RS1 (insn) < 16)
545 (*info->fprintf_func) (stream, "%%%s",
546 v9_priv_reg_names[X_RS1 (insn)]);
547 else
548 (*info->fprintf_func) (stream, "%%reserved");
549 break;
550
551 case '!':
552 if ((unsigned) X_RD (insn) < 15)
553 (*info->fprintf_func) (stream, "%%%s",
554 v9_priv_reg_names[X_RD (insn)]);
555 else
556 (*info->fprintf_func) (stream, "%%reserved");
557 break;
558
559 case '/':
560 if (X_RS1 (insn) < 16 || X_RS1 (insn) > 25)
561 (*info->fprintf_func) (stream, "%%reserved");
562 else
563 (*info->fprintf_func) (stream, "%%%s",
564 v9a_asr_reg_names[X_RS1 (insn)-16]);
565 break;
566
567 case '_':
568 if (X_RD (insn) < 16 || X_RD (insn) > 25)
569 (*info->fprintf_func) (stream, "%%reserved");
570 else
571 (*info->fprintf_func) (stream, "%%%s",
572 v9a_asr_reg_names[X_RD (insn)-16]);
573 break;
574
575 case '*':
576 {
577 const char *name = sparc_decode_prefetch (X_RD (insn));
578
579 if (name)
580 (*info->fprintf_func) (stream, "%s", name);
581 else
582 (*info->fprintf_func) (stream, "%d", X_RD (insn));
583 break;
584 }