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