Rename bitfields to avoid conflict with macro names in new opcode/sparc.h.
[deliverable/binutils-gdb.git] / gdb / sparc-pinsn.c
1 /* Print SPARC instructions for GDB, the GNU Debugger.
2 Copyright 1989, 1991 Free Software Foundation, Inc.
3
4 This file is part of GDB, the GNU disassembler.
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 <stdio.h>
21
22 #include "defs.h"
23 #include "symtab.h"
24 #include "opcode/sparc.h"
25 #include "gdbcore.h"
26 #include "string.h"
27 #include "target.h"
28
29 extern char *reg_names[];
30 #define freg_names (&reg_names[4 * 8])
31
32 union sparc_insn
33 {
34 unsigned long int code;
35 struct
36 {
37 unsigned int anop:2;
38 #define op ldst.anop
39 unsigned int anrd:5;
40 #define rd ldst.anrd
41 unsigned int op3:6;
42 unsigned int anrs1:5;
43 #define rs1 ldst.anrs1
44 unsigned int i:1;
45 unsigned int anasi:8;
46 #define asi ldst.anasi
47 unsigned int anrs2:5;
48 #define rs2 ldst.anrs2
49 #define shcnt rs2
50 } ldst;
51 struct
52 {
53 unsigned int anop:2, anrd:5, op3:6, anrs1:5, i:1;
54 unsigned int IMM13:13;
55 #define imm13 IMM13.IMM13
56 } IMM13;
57 struct
58 {
59 unsigned int anop:2;
60 unsigned int a:1;
61 unsigned int cond:4;
62 unsigned int op2:3;
63 unsigned int DISP22:22;
64 #define disp22 branch.DISP22
65 } branch;
66 #define imm22 disp22
67 struct
68 {
69 unsigned int anop:2;
70 unsigned int adisp30:30;
71 #define disp30 call.adisp30
72 } call;
73 };
74
75 /* Nonzero if INSN is the opcode for a delayed branch. */
76 static int
77 is_delayed_branch (insn)
78 union sparc_insn insn;
79 {
80 unsigned int i;
81
82 for (i = 0; i < NUMOPCODES; ++i)
83 {
84 const struct sparc_opcode *opcode = &sparc_opcodes[i];
85 if ((opcode->match & insn.code) == opcode->match
86 && (opcode->lose & insn.code) == 0)
87 return (opcode->flags & F_DELAYED);
88 }
89 return 0;
90 }
91
92 /* Print one instruction from MEMADDR on STREAM. */
93 int
94 print_insn (memaddr, stream)
95 CORE_ADDR memaddr;
96 FILE *stream;
97 {
98 union sparc_insn insn;
99
100 register unsigned int i;
101
102 read_memory (memaddr, &insn, sizeof (insn));
103
104 for (i = 0; i < NUMOPCODES; ++i)
105 {
106 const struct sparc_opcode *opcode = &sparc_opcodes[i];
107 if ((opcode->match & insn.code) == opcode->match
108 && (opcode->lose & insn.code) == 0)
109 {
110 /* Nonzero means that we have found an instruction which has
111 the effect of adding or or'ing the imm13 field to rs1. */
112 int imm_added_to_rs1 = 0;
113
114 /* Nonzero means that we have found a plus sign in the args
115 field of the opcode table. */
116 int found_plus = 0;
117
118 /* Do we have an 'or' instruction where rs1 is the same
119 as rsd, and which has the i bit set? */
120 if (opcode->match == 0x80102000
121 && insn.rs1 == insn.rd)
122 imm_added_to_rs1 = 1;
123
124 if (insn.rs1 != insn.rd
125 && strchr (opcode->args, 'r') != 0)
126 /* Can't do simple format if source and dest are different. */
127 continue;
128
129 fputs_filtered (opcode->name, stream);
130
131 {
132 register const char *s;
133
134 if (opcode->args[0] != ',')
135 fputs_filtered (" ", stream);
136 for (s = opcode->args; *s != '\0'; ++s)
137 {
138 if (*s == ',')
139 {
140 fputs_filtered (",", stream);
141 ++s;
142 if (*s == 'a')
143 {
144 fputs_filtered ("a", stream);
145 ++s;
146 }
147 fputs_filtered (" ", stream);
148 }
149
150 switch (*s)
151 {
152 case '+':
153 found_plus = 1;
154
155 /* note fall-through */
156 default:
157 fprintf_filtered (stream, "%c", *s);
158 break;
159
160 case '#':
161 fputs_filtered ("0", stream);
162 break;
163
164 #define reg(n) fprintf_filtered (stream, "%%%s", reg_names[n])
165 case '1':
166 case 'r':
167 reg (insn.rs1);
168 break;
169
170 case '2':
171 reg (insn.rs2);
172 break;
173
174 case 'd':
175 reg (insn.rd);
176 break;
177 #undef reg
178
179 #define freg(n) fprintf_filtered (stream, "%%%s", freg_names[n])
180 case 'e':
181 freg (insn.rs1);
182 break;
183
184 case 'f':
185 freg (insn.rs2);
186 break;
187
188 case 'g':
189 freg (insn.rd);
190 break;
191 #undef freg
192
193 #define creg(n) fprintf_filtered (stream, "%%c%u", (unsigned int) (n))
194 case 'b':
195 creg (insn.rs1);
196 break;
197
198 case 'c':
199 creg (insn.rs2);
200 break;
201
202 case 'D':
203 creg (insn.rd);
204 break;
205 #undef creg
206
207 case 'h':
208 fprintf_filtered (stream, "%%hi(%#x)",
209 (int) insn.imm22 << 10);
210 break;
211
212 case 'i':
213 {
214 /* We cannot trust the compiler to sign-extend
215 when extracting the bitfield, hence the shifts. */
216 int imm = ((int) insn.imm13 << 19) >> 19;
217
218 /* Check to see whether we have a 1+i, and take
219 note of that fact.
220
221 FIXME: No longer true/relavant ???
222 Note: because of the way we sort the table,
223 we will be matching 1+i rather than i+1,
224 so it is OK to assume that i is after +,
225 not before it. */
226 if (found_plus)
227 imm_added_to_rs1 = 1;
228
229 if (imm <= 9)
230 fprintf_filtered (stream, "%d", imm);
231 else
232 fprintf_filtered (stream, "%#x", imm);
233 }
234 break;
235
236 case 'L':
237 print_address ((CORE_ADDR) memaddr + insn.disp30 * 4,
238 stream);
239 break;
240
241 case 'l':
242 if ((insn.code >> 22) == 0)
243 /* Special case for `unimp'. Don't try to turn
244 it's operand into a function offset. */
245 fprintf_filtered (stream, "%#x",
246 (int) (((int) insn.disp22 << 10) >> 10));
247 else
248 /* We cannot trust the compiler to sign-extend
249 when extracting the bitfield, hence the shifts. */
250 print_address ((CORE_ADDR)
251 (memaddr
252 + (((int) insn.disp22 << 10) >> 10) * 4),
253 stream);
254 break;
255
256 case 'A':
257 fprintf_filtered (stream, "(%d)", (int) insn.asi);
258 break;
259
260 case 'C':
261 fputs_filtered ("%csr", stream);
262 break;
263
264 case 'F':
265 fputs_filtered ("%fsr", stream);
266 break;
267
268 case 'p':
269 fputs_filtered ("%psr", stream);
270 break;
271
272 case 'q':
273 fputs_filtered ("%fq", stream);
274 break;
275
276 case 'Q':
277 fputs_filtered ("%cq", stream);
278 break;
279
280 case 't':
281 fputs_filtered ("%tbr", stream);
282 break;
283
284 case 'w':
285 fputs_filtered ("%wim", stream);
286 break;
287
288 case 'y':
289 fputs_filtered ("%y", stream);
290 break;
291 }
292 }
293 }
294
295 /* If we are adding or or'ing something to rs1, then
296 check to see whether the previous instruction was
297 a sethi to the same register as in the sethi.
298 If so, attempt to print the result of the add or
299 or (in this context add and or do the same thing)
300 and its symbolic value. */
301 if (imm_added_to_rs1)
302 {
303 union sparc_insn prev_insn;
304 int errcode;
305
306 errcode = target_read_memory (memaddr - 4,
307 (char *)&prev_insn, sizeof (prev_insn));
308
309 if (errcode == 0)
310 {
311 /* If it is a delayed branch, we need to look at the
312 instruction before the delayed branch. This handles
313 sequences such as
314
315 sethi %o1, %hi(_foo), %o1
316 call _printf
317 or %o1, %lo(_foo), %o1
318 */
319
320 if (is_delayed_branch (prev_insn))
321 errcode = target_read_memory
322 (memaddr - 8, (char *)&prev_insn, sizeof (prev_insn));
323 }
324
325 /* If there was a problem reading memory, then assume
326 the previous instruction was not sethi. */
327 if (errcode == 0)
328 {
329 /* Is it sethi to the same register? */
330 if ((prev_insn.code & 0xc1c00000) == 0x01000000
331 && prev_insn.rd == insn.rs1)
332 {
333 fprintf_filtered (stream, "\t! ");
334 /* We cannot trust the compiler to sign-extend
335 when extracting the bitfield, hence the shifts. */
336 print_address (((int) prev_insn.imm22 << 10)
337 | (insn.imm13 << 19) >> 19, stream);
338 }
339 }
340 }
341
342 return sizeof (insn);
343 }
344 }
345
346 printf_filtered ("%#8x", insn.code);
347 return sizeof (insn);
348 }
This page took 0.037087 seconds and 5 git commands to generate.