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