Change GDB over to GNU General Public License version 2.
[external/binutils.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 }