1 /* Print SPARC instructions for GDB, the GNU Debugger.
2 Copyright 1989, 1991 Free Software Foundation, Inc.
4 This file is part of GDB, the GNU disassembler.
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.
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.
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. */
24 #include "opcode/sparc.h"
29 extern char *reg_names[];
30 #define freg_names (®_names[4 * 8])
34 unsigned long int code;
43 #define rs1 ldst.anrs1
46 #define asi ldst.anasi
48 #define rs2 ldst.anrs2
53 unsigned int anop:2, anrd:5, op3:6, anrs1:5, i:1;
54 unsigned int IMM13:13;
55 #define imm13 IMM13.IMM13
63 unsigned int DISP22:22;
64 #define disp22 branch.DISP22
70 unsigned int adisp30:30;
71 #define disp30 call.adisp30
75 /* Nonzero if INSN is the opcode for a delayed branch. */
77 is_delayed_branch (insn)
78 union sparc_insn insn;
82 for (i = 0; i < NUMOPCODES; ++i)
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);
92 /* Print one instruction from MEMADDR on STREAM. */
94 print_insn (memaddr, stream)
98 union sparc_insn insn;
100 register unsigned int i;
102 read_memory (memaddr, &insn, sizeof (insn));
104 for (i = 0; i < NUMOPCODES; ++i)
106 const struct sparc_opcode *opcode = &sparc_opcodes[i];
107 if ((opcode->match & insn.code) == opcode->match
108 && (opcode->lose & insn.code) == 0)
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;
114 /* Nonzero means that we have found a plus sign in the args
115 field of the opcode table. */
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;
124 if (insn.rs1 != insn.rd
125 && strchr (opcode->args, 'r') != 0)
126 /* Can't do simple format if source and dest are different. */
129 fputs_filtered (opcode->name, stream);
132 register const char *s;
134 if (opcode->args[0] != ',')
135 fputs_filtered (" ", stream);
136 for (s = opcode->args; *s != '\0'; ++s)
140 fputs_filtered (",", stream);
144 fputs_filtered ("a", stream);
147 fputs_filtered (" ", stream);
155 /* note fall-through */
157 fprintf_filtered (stream, "%c", *s);
161 fputs_filtered ("0", stream);
164 #define reg(n) fprintf_filtered (stream, "%%%s", reg_names[n])
179 #define freg(n) fprintf_filtered (stream, "%%%s", freg_names[n])
193 #define creg(n) fprintf_filtered (stream, "%%c%u", (unsigned int) (n))
208 fprintf_filtered (stream, "%%hi(%#x)",
209 (int) insn.imm22 << 10);
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;
218 /* Check to see whether we have a 1+i, and take
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 +,
227 imm_added_to_rs1 = 1;
230 fprintf_filtered (stream, "%d", imm);
232 fprintf_filtered (stream, "%#x", imm);
237 print_address ((CORE_ADDR) memaddr + insn.disp30 * 4,
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));
248 /* We cannot trust the compiler to sign-extend
249 when extracting the bitfield, hence the shifts. */
250 print_address ((CORE_ADDR)
252 + (((int) insn.disp22 << 10) >> 10) * 4),
257 fprintf_filtered (stream, "(%d)", (int) insn.asi);
261 fputs_filtered ("%csr", stream);
265 fputs_filtered ("%fsr", stream);
269 fputs_filtered ("%psr", stream);
273 fputs_filtered ("%fq", stream);
277 fputs_filtered ("%cq", stream);
281 fputs_filtered ("%tbr", stream);
285 fputs_filtered ("%wim", stream);
289 fputs_filtered ("%y", stream);
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)
303 union sparc_insn prev_insn;
306 errcode = target_read_memory (memaddr - 4,
307 (char *)&prev_insn, sizeof (prev_insn));
311 /* If it is a delayed branch, we need to look at the
312 instruction before the delayed branch. This handles
315 sethi %o1, %hi(_foo), %o1
317 or %o1, %lo(_foo), %o1
320 if (is_delayed_branch (prev_insn))
321 errcode = target_read_memory
322 (memaddr - 8, (char *)&prev_insn, sizeof (prev_insn));
325 /* If there was a problem reading memory, then assume
326 the previous instruction was not sethi. */
329 /* Is it sethi to the same register? */
330 if ((prev_insn.code & 0xc1c00000) == 0x01000000
331 && prev_insn.rd == insn.rs1)
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);
342 return sizeof (insn);
346 printf_filtered ("%#8x", insn.code);
347 return sizeof (insn);