gdb-3.5
[deliverable/binutils-gdb.git] / gdb / sparc-pinsn.c
CommitLineData
4187119d 1/* Disassembler for the sparc.
2 Copyright (C) 1989 Free Software Foundation, Inc.
3
4This file is part of GDB, the GNU disassembler.
5
6GDB is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 1, or (at your option)
9any later version.
10
11GDB is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GDB; see the file COPYING. If not, write to
18the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
bb7592f0 19
20#include <stdio.h>
21
22#include "defs.h"
23#include "param.h"
24#include "symtab.h"
25#include "sparc-opcode.h"
26
4187119d 27extern char *reg_names[];
28#define freg_names (&reg_names[4 * 8])
bb7592f0 29
4187119d 30union sparc_insn
31 {
32 unsigned long int code;
33 struct
34 {
35 unsigned int OP:2;
36#define op ldst.OP
37 unsigned int RD:5;
38#define rd ldst.RD
39 unsigned int op3:6;
40 unsigned int RS1:5;
41#define rs1 ldst.RS1
42 unsigned int i:1;
43 unsigned int ASI:8;
44#define asi ldst.ASI
45 unsigned int RS2:5;
46#define rs2 ldst.RS2
47#define shcnt rs2
48 } ldst;
49 struct
50 {
51 unsigned int OP:2, RD:5, op3:6, RS1:5, i:1;
52 unsigned int IMM13:13;
53#define imm13 IMM13.IMM13
54 } IMM13;
55 struct
56 {
57 unsigned int OP:2;
58 unsigned int a:1;
59 unsigned int cond:4;
60 unsigned int op2:3;
61 unsigned int DISP22:22;
62#define disp22 branch.DISP22
63 } branch;
64#define imm22 disp22
65 struct
66 {
67 unsigned int OP:2;
68 unsigned int DISP30:30;
69#define disp30 call.DISP30
70 } call;
71 };
72
73/* Nonzero if INSN is the opcode for a delayed branch. */
74static int
75is_delayed_branch (insn)
76 union sparc_insn insn;
77{
78 unsigned int i;
bb7592f0 79
4187119d 80 for (i = 0; i < NUMOPCODES; ++i)
81 {
82 const struct sparc_opcode *opcode = &sparc_opcodes[i];
83 if ((opcode->match & insn.code) == opcode->match
84 && (opcode->lose & insn.code) == 0
85 && (opcode->delayed))
86 return 1;
87 }
88 return 0;
89}
bb7592f0 90
4187119d 91static int opcodes_sorted = 0;
bb7592f0 92
4187119d 93/* Print one instruction from MEMADDR on STREAM. */
bb7592f0 94int
95print_insn (memaddr, stream)
96 CORE_ADDR memaddr;
97 FILE *stream;
98{
4187119d 99 union sparc_insn insn;
100
101 register unsigned int i;
bb7592f0 102
4187119d 103 if (!opcodes_sorted)
104 {
105 static int compare_opcodes ();
106 qsort ((char *) sparc_opcodes, NUMOPCODES,
107 sizeof (sparc_opcodes[0]), compare_opcodes);
108 opcodes_sorted = 1;
109 }
bb7592f0 110
4187119d 111 read_memory (memaddr, &insn, sizeof (insn));
112
113 for (i = 0; i < NUMOPCODES; ++i)
bb7592f0 114 {
4187119d 115 const struct sparc_opcode *opcode = &sparc_opcodes[i];
116 if ((opcode->match & insn.code) == opcode->match
117 && (opcode->lose & insn.code) == 0)
bb7592f0 118 {
4187119d 119 /* Nonzero means that we have found an instruction which has
120 the effect of adding or or'ing the imm13 field to rs1. */
121 int imm_added_to_rs1 = 0;
122
123 /* Nonzero means that we have found a plus sign in the args
124 field of the opcode table. */
125 int found_plus = 0;
126
127 /* Do we have an 'or' instruction where rs1 is the same
128 as rsd, and which has the i bit set? */
129 if (opcode->match == 0x80102000
130 && insn.rs1 == insn.rd)
131 imm_added_to_rs1 = 1;
132
133 if (index (opcode->args, 'S') != 0)
134 /* Reject the special case for `set'.
135 The real `sethi' will match. */
136 continue;
137 if (insn.rs1 != insn.rd
138 && index (opcode->args, 'r') != 0)
139 /* Can't do simple format if source and dest are different. */
140 continue;
141
142 fputs_filtered (opcode->name, stream);
bb7592f0 143
bb7592f0 144 {
4187119d 145 register const char *s;
bb7592f0 146
4187119d 147 if (opcode->args[0] != ',')
148 fputs_filtered (" ", stream);
149 for (s = opcode->args; *s != '\0'; ++s)
bb7592f0 150 {
4187119d 151 if (*s == ',')
bb7592f0 152 {
4187119d 153 fputs_filtered (",", stream);
154 ++s;
155 if (*s == 'a')
156 {
157 fputs_filtered ("a", stream);
158 ++s;
159 }
160 fputs_filtered (" ", stream);
bb7592f0 161 }
bb7592f0 162
4187119d 163 switch (*s)
bb7592f0 164 {
4187119d 165 case '+':
166 found_plus = 1;
167
168 /* note fall-through */
169 default:
170 fprintf_filtered (stream, "%c", *s);
171 break;
172
173 case '#':
174 fputs_filtered ("0", stream);
175 break;
176
177#define reg(n) fprintf_filtered (stream, "%%%s", reg_names[n])
178 case '1':
179 case 'r':
180 reg (insn.rs1);
181 break;
182
183 case '2':
184 reg (insn.rs2);
185 break;
186
187 case 'd':
188 reg (insn.rd);
189 break;
190#undef reg
191
192#define freg(n) fprintf_filtered (stream, "%%%s", freg_names[n])
193 case 'e':
194 freg (insn.rs1);
195 break;
196
197 case 'f':
198 freg (insn.rs2);
199 break;
200
201 case 'g':
202 freg (insn.rd);
203 break;
204#undef freg
205
206#define creg(n) fprintf_filtered (stream, "%%c%u", (unsigned int) (n))
207 case 'b':
208 creg (insn.rs1);
209 break;
210
211 case 'c':
212 creg (insn.rs2);
213 break;
214
215 case 'D':
216 creg (insn.rd);
217 break;
218#undef creg
219
220 case 'h':
221 fprintf_filtered (stream, "%%hi(%#x)",
222 (int) insn.imm22 << 10);
223 break;
224
225 case 'i':
226 {
227 /* We cannot trust the compiler to sign-extend
228 when extracting the bitfield, hence the shifts. */
229 int imm = ((int) insn.imm13 << 19) >> 19;
230
231 /* Check to see whether we have a 1+i, and take
232 note of that fact.
233
234 Note: because of the way we sort the table,
235 we will be matching 1+i rather than i+1,
236 so it is OK to assume that i is after +,
237 not before it. */
238 if (found_plus)
239 imm_added_to_rs1 = 1;
240
241 if (imm <= 9)
242 fprintf_filtered (stream, "%d", imm);
243 else
244 fprintf_filtered (stream, "%#x", imm);
245 }
246 break;
247
248 case 'L':
249 print_address ((CORE_ADDR) memaddr + insn.disp30 * 4,
250 stream);
251 break;
252
253 case 'l':
254 if ((insn.code >> 22) == 0)
255 /* Special case for `unimp'. Don't try to turn
256 it's operand into a function offset. */
257 fprintf_filtered (stream, "%#x",
258 (int) (((int) insn.disp22 << 10) >> 10));
259 else
260 /* We cannot trust the compiler to sign-extend
261 when extracting the bitfield, hence the shifts. */
262 print_address ((CORE_ADDR)
263 (memaddr
264 + (((int) insn.disp22 << 10) >> 10) * 4),
265 stream);
266 break;
267
268 case 'A':
269 fprintf_filtered (stream, "(%d)", (int) insn.asi);
270 break;
271
272 case 'C':
273 fputs_filtered ("%csr", stream);
274 break;
275
276 case 'F':
277 fputs_filtered ("%fsr", stream);
278 break;
279
280 case 'p':
281 fputs_filtered ("%psr", stream);
282 break;
283
284 case 'q':
285 fputs_filtered ("%fq", stream);
286 break;
287
288 case 'Q':
289 fputs_filtered ("%cq", stream);
290 break;
291
292 case 't':
293 fputs_filtered ("%tbr", stream);
294 break;
295
296 case 'w':
297 fputs_filtered ("%wim", stream);
298 break;
299
300 case 'y':
301 fputs_filtered ("%y", stream);
302 break;
bb7592f0 303 }
bb7592f0 304 }
4187119d 305 }
bb7592f0 306
4187119d 307 /* If we are adding or or'ing something to rs1, then
308 check to see whether the previous instruction was
309 a sethi to the same register as in the sethi.
310 If so, attempt to print the result of the add or
311 or (in this context add and or do the same thing)
312 and its symbolic value. */
313 if (imm_added_to_rs1)
314 {
315 union sparc_insn prev_insn;
316 int errcode;
bb7592f0 317
4187119d 318 errcode = read_memory (memaddr - 4,
319 &prev_insn, sizeof (prev_insn));
bb7592f0 320
4187119d 321 if (errcode == 0)
bb7592f0 322 {
4187119d 323 /* If it is a delayed branch, we need to look at the
324 instruction before the delayed branch. This handles
325 sequences such as
326
327 sethi %o1, %hi(_foo), %o1
328 call _printf
329 or %o1, %lo(_foo), %o1
330 */
331
332 if (is_delayed_branch (prev_insn))
333 errcode = read_memory (memaddr - 8,
334 &prev_insn, sizeof (prev_insn));
bb7592f0 335 }
bb7592f0 336
4187119d 337 /* If there was a problem reading memory, then assume
338 the previous instruction was not sethi. */
339 if (errcode == 0)
340 {
341 /* Is it sethi to the same register? */
342 if ((prev_insn.code & 0xc1c00000) == 0x01000000
343 && prev_insn.rd == insn.rs1)
344 {
345 fprintf_filtered (stream, "\t! ");
346 /* We cannot trust the compiler to sign-extend
347 when extracting the bitfield, hence the shifts. */
348 print_address (((int) prev_insn.imm22 << 10)
349 | (insn.imm13 << 19) >> 19, stream);
350 }
351 }
352 }
353
354 return sizeof (insn);
355 }
bb7592f0 356 }
4187119d 357
358 fprintf_filtered ("%#8x", insn.code);
359 return sizeof (insn);
bb7592f0 360}
361
bb7592f0 362
4187119d 363/* Compare opcodes A and B. */
bb7592f0 364
4187119d 365static int
366compare_opcodes (a, b)
367 char *a, *b;
bb7592f0 368{
4187119d 369 struct sparc_opcode *op0 = (struct sparc_opcode *) a;
370 struct sparc_opcode *op1 = (struct sparc_opcode *) b;
371 unsigned long int match0 = op0->match, match1 = op1->match;
372 unsigned long int lose0 = op0->lose, lose1 = op1->lose;
373 register unsigned int i;
374
375 /* If a bit is set in both match and lose, there is something
376 wrong with the opcode table. */
377 if (match0 & lose0)
bb7592f0 378 {
4187119d 379 fprintf (stderr, "Internal error: bad sparc-opcode.h: \"%s\", %#.8x, %#.8x\n",
380 op0->name, match0, lose0);
381 op0->lose &= ~op0->match;
382 lose0 = op0->lose;
bb7592f0 383 }
bb7592f0 384
4187119d 385 if (match1 & lose1)
bb7592f0 386 {
4187119d 387 fprintf (stderr, "Internal error: bad sparc-opcode.h: \"%s\", %#.8x, %#.8x\n",
388 op1->name, match1, lose1);
389 op1->lose &= ~op1->match;
390 lose1 = op1->lose;
bb7592f0 391 }
bb7592f0 392
4187119d 393 /* Because the bits that are variable in one opcode are constant in
394 another, it is important to order the opcodes in the right order. */
395 for (i = 0; i < 32; ++i)
bb7592f0 396 {
4187119d 397 unsigned long int x = 1 << i;
398 int x0 = (match0 & x) != 0;
399 int x1 = (match1 & x) != 0;
bb7592f0 400
4187119d 401 if (x0 != x1)
402 return x1 - x0;
bb7592f0 403 }
bb7592f0 404
4187119d 405 for (i = 0; i < 32; ++i)
bb7592f0 406 {
4187119d 407 unsigned long int x = 1 << i;
408 int x0 = (lose0 & x) != 0;
409 int x1 = (lose1 & x) != 0;
bb7592f0 410
4187119d 411 if (x0 != x1)
412 return x1 - x0;
413 }
bb7592f0 414
4187119d 415 /* They are functionally equal. So as long as the opcode table is
416 valid, we can put whichever one first we want, on aesthetic grounds. */
417 {
418 int length_diff = strlen (op0->args) - strlen (op1->args);
419 if (length_diff != 0)
420 /* Put the one with fewer arguments first. */
421 return length_diff;
422 }
423
424 /* Put 1+i before i+1. */
425 {
426 char *p0 = (char *) index(op0->args, '+');
427 char *p1 = (char *) index(op1->args, '+');
428
429 if (p0 && p1)
430 {
431 /* There is a plus in both operands. Note that a plus
432 sign cannot be the first character in args,
433 so the following [-1]'s are valid. */
434 if (p0[-1] == 'i' && p1[1] == 'i')
435 /* op0 is i+1 and op1 is 1+i, so op1 goes first. */
436 return 1;
437 if (p0[1] == 'i' && p1[-1] == 'i')
438 /* op0 is 1+i and op1 is i+1, so op0 goes first. */
439 return -1;
440 }
441 }
bb7592f0 442
4187119d 443 /* They are, as far as we can tell, identical.
444 Since qsort may have rearranged the table partially, there is
445 no way to tell which one was first in the opcode table as
446 written, so just say there are equal. */
447 return 0;
bb7592f0 448}
This page took 0.041039 seconds and 4 git commands to generate.