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