1 /* Disassembler for the Pyramid Technology 90x
2 Copyright (C) 1988,1989 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. */
25 #include "pyr-opcode.h"
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.)
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. */
38 extern unsigned pyr_saved_pc(), pyr_frame_chain();
40 CORE_ADDR pyr_frame_chain(frame)
43 int foo=frame - CONTROL_STACK_FRAME_SIZE;
44 /* printf ("...following chain from %x: got %x\n", frame, foo);*/
48 CORE_ADDR pyr_saved_pc(frame)
52 foo = read_memory_integer (((CORE_ADDR)(frame))+60, 4);
53 printf ("..reading pc from frame 0x%0x+%d regs: got %0x\n",
59 /* Pyramid instructions are never longer than this many bytes. */
62 /* Number of elements in the opcode table. */
63 /*const*/ static int nopcodes = (sizeof (pyr_opcodes) / sizeof( pyr_opcodes[0]));
64 #define NOPCODES (nopcodes)
66 extern char *reg_names[];
68 /* Let's be byte-independent so we can use this as a cross-assembler.
69 (will this ever be useful?
73 (p += 4, (((((p[-4] << 8) + p[-3]) << 8) + p[-2]) << 8) + p[-1])
76 /* Print one instruction at address MEMADDR in debugged memory,
77 on STREAM. Returns length of the instruction, in bytes. */
80 print_insn (memaddr, stream)
84 unsigned char buffer[MAXLEN];
85 register int i, nargs, insn_size =4;
86 register unsigned char *p;
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;
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;
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");
112 for (i = 0; i < NOPCODES; i++)
113 if (pyr_opcodes[i].datum.code == insn_opcode)
117 /* FIXME: Handle unrecognised instructions better. */
118 fprintf (stream, "???\t#%08x\t(op=%x mode =%x)",
119 insn, insn_decode.operator, insn_decode.mode);
122 /* Print the mnemonic for the instruction. Pyramid insn operands
123 are so regular that we can deal with almost all of them
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. */
134 fprintf (stream, "%s\t", pyr_opcodes[i].name);
136 /* Print the operands of the insn (as specified in
138 Branch operands of branches are a special case: they are a word
139 offset, not a byte offset. */
141 if (insn_decode.operator == 0x01 || insn_decode.operator == 0x02) {
142 register int bit_codes=(insn >> 16)&0xf;
144 register int displacement = (insn & 0x0000ffff) << 2;
146 static char cc_bit_names[] = "cvzn"; /* z,n,c,v: strange order? */
148 /* Is bfc and no bits specified an unconditional branch?*/
150 if ((bit_codes) & 0x1)
151 fputc (cc_bit_names[i], stream);
155 fprintf (stream, ",%0x",
156 displacement + memaddr);
160 switch (operand_mode) {
162 fprintf (stream, "%s,%s",
163 reg_names [op_1_regno],
164 reg_names [op_2_regno]);
168 fprintf (stream, " 0x%0x,%s",
170 reg_names [op_2_regno]);
174 read_memory (memaddr+4, buffer, MAXLEN);
176 extra_1 = * ((int *) buffer);
177 fprintf (stream, " $0x%0x,%s",
179 reg_names [op_2_regno]);
182 fprintf (stream, " (%s),%s",
183 reg_names [op_1_regno],
184 reg_names [op_2_regno]);
188 read_memory (memaddr+4, buffer, MAXLEN);
190 extra_1 = * ((int *) buffer);
191 fprintf (stream, " 0x%0x(%s),%s",
193 reg_names [op_1_regno],
194 reg_names [op_2_regno]);
197 /* S1 destination mode */
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],
209 ((index_reg_regno) ? " $%#0x,(%s)[%s*%1d]"
212 reg_names [op_2_regno],
213 reg_names [index_reg_regno],
218 read_memory (memaddr+4, buffer, MAXLEN);
220 extra_1 = * ((int *) buffer);
222 ((index_reg_regno) ? " $%#0x,(%s)[%s*%1d]"
225 reg_names [op_2_regno],
226 reg_names [index_reg_regno],
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],
240 read_memory (memaddr+4, buffer, MAXLEN);
242 extra_1 = * ((int *) buffer);
245 ? "%#0x(%s),(%s)[%s*%1d]"
248 reg_names [op_1_regno],
249 reg_names [op_2_regno],
250 reg_names [index_reg_regno],
254 /* S2 destination mode */
256 read_memory (memaddr+4, buffer, MAXLEN);
258 extra_1 = * ((int *) buffer);
260 ((index_reg_regno) ? "%s,%#0x(%s)[%s*%1d]" : "%s,%#0x(%s)"),
261 reg_names [op_1_regno],
263 reg_names [op_2_regno],
264 reg_names [index_reg_regno],
268 read_memory (memaddr+4, buffer, MAXLEN);
270 extra_1 = * ((int *) buffer);
273 " $%#0x,%#0x(%s)[%s*%1d]" : " $%#0x,%#0x(%s)"),
276 reg_names [op_2_regno],
277 reg_names [index_reg_regno],
281 read_memory (memaddr+4, buffer, MAXLEN);
283 extra_1 = * ((int *) buffer);
284 read_memory (memaddr+8, buffer, MAXLEN);
286 extra_2 = * ((int *) buffer);
289 " $%#0x,%#0x(%s)[%s*%1d]" : " $%#0x,%#0x(%s)"),
292 reg_names [op_2_regno],
293 reg_names [index_reg_regno],
298 read_memory (memaddr+4, buffer, MAXLEN);
300 extra_1 = * ((int *) buffer);
303 ? " (%s),%#0x(%s)[%s*%1d]"
305 reg_names [op_1_regno],
307 reg_names [op_2_regno],
308 reg_names [index_reg_regno],
312 read_memory (memaddr+4, buffer, MAXLEN);
314 extra_1 = * ((int *) buffer);
315 read_memory (memaddr+8, buffer, MAXLEN);
317 extra_2 = * ((int *) buffer);
319 ((index_reg_regno) ? "%#0x(%s),%#0x(%s)[%s*%1d]"
320 : "%#0x(%s),%#0x(%s) "),
322 reg_names [op_1_regno],
324 reg_names [op_2_regno],
325 reg_names [index_reg_regno],
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],
337 "\t\t# unknown mode in %08x",