Tue Mar 3 15:11:52 1992 Michael Tiemann (tiemann@cygnus.com)
[deliverable/binutils-gdb.git] / gdb / pyr-pinsn.c
1 /* Print Pyramid Technology 90x instructions for GDB, the GNU Debugger.
2 Copyright 1988, 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 "defs.h"
21 #include "symtab.h"
22 #include "opcode/pyr.h"
23 #include "gdbcore.h"
24
25 \f
26 /* A couple of functions used for debugging frame-handling on
27 Pyramids. (The Pyramid-dependent handling of register values for
28 windowed registers is known to be buggy.)
29
30 When debugging, these functions can supplant the normal definitions of some
31 of the macros in tm-pyramid.h The quantity of information produced
32 when these functions are used makes the gdb unusable as a
33 debugger for user programs. */
34
35 extern unsigned pyr_saved_pc(), pyr_frame_chain();
36
37 CORE_ADDR pyr_frame_chain(frame)
38 CORE_ADDR frame;
39 {
40 int foo=frame - CONTROL_STACK_FRAME_SIZE;
41 /* printf ("...following chain from %x: got %x\n", frame, foo);*/
42 return foo;
43 }
44
45 CORE_ADDR pyr_saved_pc(frame)
46 CORE_ADDR frame;
47 {
48 int foo=0;
49 foo = read_memory_integer (((CORE_ADDR)(frame))+60, 4);
50 printf ("..reading pc from frame 0x%0x+%d regs: got %0x\n",
51 frame, 60/4, foo);
52 return foo;
53 }
54 \f
55
56 /* Pyramid instructions are never longer than this many bytes. */
57 #define MAXLEN 24
58
59 /* Number of elements in the opcode table. */
60 /*const*/ static int nopcodes = (sizeof (pyr_opcodes) / sizeof( pyr_opcodes[0]));
61 #define NOPCODES (nopcodes)
62
63 extern char *reg_names[];
64 \f
65 /* Let's be byte-independent so we can use this as a cross-assembler.
66 (will this ever be useful?
67 */
68
69 #define NEXTLONG(p) \
70 (p += 4, (((((p[-4] << 8) + p[-3]) << 8) + p[-2]) << 8) + p[-1])
71
72 \f
73 /* Print one instruction at address MEMADDR in debugged memory,
74 on STREAM. Returns length of the instruction, in bytes. */
75
76 int
77 print_insn (memaddr, stream)
78 CORE_ADDR memaddr;
79 FILE *stream;
80 {
81 unsigned char buffer[MAXLEN];
82 register int i, nargs, insn_size =4;
83 register unsigned char *p;
84 register char *d;
85 register int insn_opcode, operand_mode;
86 register int index_multiplier, index_reg_regno, op_1_regno, op_2_regno ;
87 long insn; /* first word of the insn, not broken down. */
88 pyr_insn_format insn_decode; /* the same, broken out into op{code,erands} */
89 long extra_1, extra_2;
90
91 read_memory (memaddr, buffer, MAXLEN);
92 insn_decode = *((pyr_insn_format *) buffer);
93 insn = * ((int *) buffer);
94 insn_opcode = insn_decode.operator;
95 operand_mode = insn_decode.mode;
96 index_multiplier = insn_decode.index_scale;
97 index_reg_regno = insn_decode.index_reg;
98 op_1_regno = insn_decode.operand_1;
99 op_2_regno = insn_decode.operand_2;
100
101
102 if (*((int *)buffer) == 0x0) {
103 /* "halt" looks just like an invalid "jump" to the insn decoder,
104 so is dealt with as a special case */
105 fprintf (stream, "halt");
106 return (4);
107 }
108
109 for (i = 0; i < NOPCODES; i++)
110 if (pyr_opcodes[i].datum.code == insn_opcode)
111 break;
112
113 if (i == NOPCODES)
114 /* FIXME: Handle unrecognised instructions better. */
115 fprintf (stream, "???\t#%08x\t(op=%x mode =%x)",
116 insn, insn_decode.operator, insn_decode.mode);
117 else
118 {
119 /* Print the mnemonic for the instruction. Pyramid insn operands
120 are so regular that we can deal with almost all of them
121 separately.
122 Unconditional branches are an exception: they are encoded as
123 conditional branches (branch if false condition, I think)
124 with no condition specified. The average user will not be
125 aware of this. To maintain their illusion that an
126 unconditional branch insn exists, we will have to FIXME to
127 treat the insn mnemnonic of all branch instructions here as a
128 special case: check the operands of branch insn and print an
129 appropriate mnemonic. */
130
131 fprintf (stream, "%s\t", pyr_opcodes[i].name);
132
133 /* Print the operands of the insn (as specified in
134 insn.operand_mode).
135 Branch operands of branches are a special case: they are a word
136 offset, not a byte offset. */
137
138 if (insn_decode.operator == 0x01 || insn_decode.operator == 0x02) {
139 register int bit_codes=(insn >> 16)&0xf;
140 register int i;
141 register int displacement = (insn & 0x0000ffff) << 2;
142
143 static char cc_bit_names[] = "cvzn"; /* z,n,c,v: strange order? */
144
145 /* Is bfc and no bits specified an unconditional branch?*/
146 for (i=0;i<4;i++) {
147 if ((bit_codes) & 0x1)
148 fputc (cc_bit_names[i], stream);
149 bit_codes >>= 1;
150 }
151
152 fprintf (stream, ",%0x",
153 displacement + memaddr);
154 return (insn_size);
155 }
156
157 switch (operand_mode) {
158 case 0:
159 fprintf (stream, "%s,%s",
160 reg_names [op_1_regno],
161 reg_names [op_2_regno]);
162 break;
163
164 case 1:
165 fprintf (stream, " 0x%0x,%s",
166 op_1_regno,
167 reg_names [op_2_regno]);
168 break;
169
170 case 2:
171 read_memory (memaddr+4, buffer, MAXLEN);
172 insn_size += 4;
173 extra_1 = * ((int *) buffer);
174 fprintf (stream, " $0x%0x,%s",
175 extra_1,
176 reg_names [op_2_regno]);
177 break;
178 case 3:
179 fprintf (stream, " (%s),%s",
180 reg_names [op_1_regno],
181 reg_names [op_2_regno]);
182 break;
183
184 case 4:
185 read_memory (memaddr+4, buffer, MAXLEN);
186 insn_size += 4;
187 extra_1 = * ((int *) buffer);
188 fprintf (stream, " 0x%0x(%s),%s",
189 extra_1,
190 reg_names [op_1_regno],
191 reg_names [op_2_regno]);
192 break;
193
194 /* S1 destination mode */
195 case 5:
196 fprintf (stream,
197 ((index_reg_regno) ? "%s,(%s)[%s*%1d]" : "%s,(%s)"),
198 reg_names [op_1_regno],
199 reg_names [op_2_regno],
200 reg_names [index_reg_regno],
201 index_multiplier);
202 break;
203
204 case 6:
205 fprintf (stream,
206 ((index_reg_regno) ? " $%#0x,(%s)[%s*%1d]"
207 : " $%#0x,(%s)"),
208 op_1_regno,
209 reg_names [op_2_regno],
210 reg_names [index_reg_regno],
211 index_multiplier);
212 break;
213
214 case 7:
215 read_memory (memaddr+4, buffer, MAXLEN);
216 insn_size += 4;
217 extra_1 = * ((int *) buffer);
218 fprintf (stream,
219 ((index_reg_regno) ? " $%#0x,(%s)[%s*%1d]"
220 : " $%#0x,(%s)"),
221 extra_1,
222 reg_names [op_2_regno],
223 reg_names [index_reg_regno],
224 index_multiplier);
225 break;
226
227 case 8:
228 fprintf (stream,
229 ((index_reg_regno) ? " (%s),(%s)[%s*%1d]" : " (%s),(%s)"),
230 reg_names [op_1_regno],
231 reg_names [op_2_regno],
232 reg_names [index_reg_regno],
233 index_multiplier);
234 break;
235
236 case 9:
237 read_memory (memaddr+4, buffer, MAXLEN);
238 insn_size += 4;
239 extra_1 = * ((int *) buffer);
240 fprintf (stream,
241 ((index_reg_regno)
242 ? "%#0x(%s),(%s)[%s*%1d]"
243 : "%#0x(%s),(%s)"),
244 extra_1,
245 reg_names [op_1_regno],
246 reg_names [op_2_regno],
247 reg_names [index_reg_regno],
248 index_multiplier);
249 break;
250
251 /* S2 destination mode */
252 case 10:
253 read_memory (memaddr+4, buffer, MAXLEN);
254 insn_size += 4;
255 extra_1 = * ((int *) buffer);
256 fprintf (stream,
257 ((index_reg_regno) ? "%s,%#0x(%s)[%s*%1d]" : "%s,%#0x(%s)"),
258 reg_names [op_1_regno],
259 extra_1,
260 reg_names [op_2_regno],
261 reg_names [index_reg_regno],
262 index_multiplier);
263 break;
264 case 11:
265 read_memory (memaddr+4, buffer, MAXLEN);
266 insn_size += 4;
267 extra_1 = * ((int *) buffer);
268 fprintf (stream,
269 ((index_reg_regno) ?
270 " $%#0x,%#0x(%s)[%s*%1d]" : " $%#0x,%#0x(%s)"),
271 op_1_regno,
272 extra_1,
273 reg_names [op_2_regno],
274 reg_names [index_reg_regno],
275 index_multiplier);
276 break;
277 case 12:
278 read_memory (memaddr+4, buffer, MAXLEN);
279 insn_size += 4;
280 extra_1 = * ((int *) buffer);
281 read_memory (memaddr+8, buffer, MAXLEN);
282 insn_size += 4;
283 extra_2 = * ((int *) buffer);
284 fprintf (stream,
285 ((index_reg_regno) ?
286 " $%#0x,%#0x(%s)[%s*%1d]" : " $%#0x,%#0x(%s)"),
287 extra_1,
288 extra_2,
289 reg_names [op_2_regno],
290 reg_names [index_reg_regno],
291 index_multiplier);
292 break;
293
294 case 13:
295 read_memory (memaddr+4, buffer, MAXLEN);
296 insn_size += 4;
297 extra_1 = * ((int *) buffer);
298 fprintf (stream,
299 ((index_reg_regno)
300 ? " (%s),%#0x(%s)[%s*%1d]"
301 : " (%s),%#0x(%s)"),
302 reg_names [op_1_regno],
303 extra_1,
304 reg_names [op_2_regno],
305 reg_names [index_reg_regno],
306 index_multiplier);
307 break;
308 case 14:
309 read_memory (memaddr+4, buffer, MAXLEN);
310 insn_size += 4;
311 extra_1 = * ((int *) buffer);
312 read_memory (memaddr+8, buffer, MAXLEN);
313 insn_size += 4;
314 extra_2 = * ((int *) buffer);
315 fprintf (stream,
316 ((index_reg_regno) ? "%#0x(%s),%#0x(%s)[%s*%1d]"
317 : "%#0x(%s),%#0x(%s) "),
318 extra_1,
319 reg_names [op_1_regno],
320 extra_2,
321 reg_names [op_2_regno],
322 reg_names [index_reg_regno],
323 index_multiplier);
324 break;
325
326 default:
327 fprintf (stream,
328 ((index_reg_regno) ? "%s,%s [%s*%1d]" : "%s,%s"),
329 reg_names [op_1_regno],
330 reg_names [op_2_regno],
331 reg_names [index_reg_regno],
332 index_multiplier);
333 fprintf (stream,
334 "\t\t# unknown mode in %08x",
335 insn);
336 break;
337 } /* switch */
338 }
339
340 {
341 return insn_size;
342 }
343 abort ();
344 }
This page took 0.035775 seconds and 4 git commands to generate.