* defs.h: Incorporate param.h. All users changed.
[binutils-gdb.git] / gdb / vax-pinsn.c
1 /* Print VAX instructions for GDB, the GNU debugger.
2 Copyright 1986, 1989, 1991 Free Software Foundation, Inc.
3
4 This file is part of GDB.
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 "symtab.h"
24 #include "vax-opcode.h"
25
26 /* Vax instructions are never longer than this. */
27 #define MAXLEN 62
28
29 /* Number of elements in the opcode table. */
30 #define NOPCODES (sizeof votstrs / sizeof votstrs[0])
31
32 extern char *reg_names[];
33
34 static unsigned char *print_insn_arg ();
35 \f
36 /* Print the vax instruction at address MEMADDR in debugged memory,
37 on STREAM. Returns length of the instruction, in bytes. */
38
39 int
40 print_insn (memaddr, stream)
41 CORE_ADDR memaddr;
42 FILE *stream;
43 {
44 unsigned char buffer[MAXLEN];
45 register int i;
46 register unsigned char *p;
47 register char *d;
48
49 read_memory (memaddr, buffer, MAXLEN);
50
51 for (i = 0; i < NOPCODES; i++)
52 if (votstrs[i].detail.code == buffer[0]
53 || votstrs[i].detail.code == *(unsigned short *)buffer)
54 break;
55
56 /* Handle undefined instructions. */
57 if (i == NOPCODES)
58 {
59 fprintf (stream, "0%o", buffer[0]);
60 return 1;
61 }
62
63 fprintf (stream, "%s", votstrs[i].name);
64
65 /* Point at first byte of argument data,
66 and at descriptor for first argument. */
67 p = buffer + 1 + (votstrs[i].detail.code >= 0x100);
68 d = votstrs[i].detail.args;
69
70 if (*d)
71 fputc (' ', stream);
72
73 while (*d)
74 {
75 p = print_insn_arg (d, p, memaddr + (p - buffer), stream);
76 d += 2;
77 if (*d)
78 fprintf (stream, ",");
79 }
80 return p - buffer;
81 }
82
83 static unsigned char *
84 print_insn_arg (d, p, addr, stream)
85 char *d;
86 register char *p;
87 CORE_ADDR addr;
88 FILE *stream;
89 {
90 register int regnum = *p & 0xf;
91 float floatlitbuf;
92
93 if (*d == 'b')
94 {
95 if (d[1] == 'b')
96 fprintf (stream, "0x%x", addr + *p++ + 1);
97 else
98 {
99 fprintf (stream, "0x%x", addr + *(short *)p + 2);
100 p += 2;
101 }
102 }
103 else
104 switch ((*p++ >> 4) & 0xf)
105 {
106 case 0:
107 case 1:
108 case 2:
109 case 3: /* Literal mode */
110 if (d[1] == 'd' || d[1] == 'f' || d[1] == 'g' || d[1] == 'h')
111 {
112 *(int *)&floatlitbuf = 0x4000 + ((p[-1] & 0x3f) << 4);
113 fprintf (stream, "$%f", floatlitbuf);
114 }
115 else
116 fprintf (stream, "$%d", p[-1] & 0x3f);
117 break;
118
119 case 4: /* Indexed */
120 p = (char *) print_insn_arg (d, p, addr + 1, stream);
121 fprintf (stream, "[%s]", reg_names[regnum]);
122 break;
123
124 case 5: /* Register */
125 fprintf (stream, reg_names[regnum]);
126 break;
127
128 case 7: /* Autodecrement */
129 fputc ('-', stream);
130 case 6: /* Register deferred */
131 fprintf (stream, "(%s)", reg_names[regnum]);
132 break;
133
134 case 9: /* Autoincrement deferred */
135 fputc ('@', stream);
136 if (regnum == PC_REGNUM)
137 {
138 fputc ('#', stream);
139 print_address (*(long *)p, stream);
140 p += 4;
141 break;
142 }
143 case 8: /* Autoincrement */
144 if (regnum == PC_REGNUM)
145 {
146 fputc ('#', stream);
147 switch (d[1])
148 {
149 case 'b':
150 fprintf (stream, "%d", *p++);
151 break;
152
153 case 'w':
154 fprintf (stream, "%d", *(short *)p);
155 p += 2;
156 break;
157
158 case 'l':
159 fprintf (stream, "%d", *(long *)p);
160 p += 4;
161 break;
162
163 case 'q':
164 fprintf (stream, "0x%x%08x", ((long *)p)[1], ((long *)p)[0]);
165 p += 8;
166 break;
167
168 case 'o':
169 fprintf (stream, "0x%x%08x%08x%08x",
170 ((long *)p)[3], ((long *)p)[2],
171 ((long *)p)[1], ((long *)p)[0]);
172 p += 16;
173 break;
174
175 case 'f':
176 if (INVALID_FLOAT (p, 4))
177 fprintf (stream, "<<invalid float 0x%x>>", *(int *) p);
178 else
179 fprintf (stream, "%f", *(float *) p);
180 p += 4;
181 break;
182
183 case 'd':
184 if (INVALID_FLOAT (p, 8))
185 fprintf (stream, "<<invalid float 0x%x%08x>>",
186 ((long *)p)[1], ((long *)p)[0]);
187 else
188 fprintf (stream, "%f", *(double *) p);
189 p += 8;
190 break;
191
192 case 'g':
193 fprintf (stream, "g-float");
194 p += 8;
195 break;
196
197 case 'h':
198 fprintf (stream, "h-float");
199 p += 16;
200 break;
201
202 }
203 }
204 else
205 fprintf (stream, "(%s)+", reg_names[regnum]);
206 break;
207
208 case 11: /* Byte displacement deferred */
209 fputc ('@', stream);
210 case 10: /* Byte displacement */
211 if (regnum == PC_REGNUM)
212 print_address (addr + *p + 2, stream);
213 else
214 fprintf (stream, "%d(%s)", *p, reg_names[regnum]);
215 p += 1;
216 break;
217
218 case 13: /* Word displacement deferred */
219 fputc ('@', stream);
220 case 12: /* Word displacement */
221 if (regnum == PC_REGNUM)
222 print_address (addr + *(short *)p + 3, stream);
223 else
224 fprintf (stream, "%d(%s)", *(short *)p, reg_names[regnum]);
225 p += 2;
226 break;
227
228 case 15: /* Long displacement deferred */
229 fputc ('@', stream);
230 case 14: /* Long displacement */
231 if (regnum == PC_REGNUM)
232 print_address (addr + *(long *)p + 5, stream);
233 else
234 fprintf (stream, "%d(%s)", *(long *)p, reg_names[regnum]);
235 p += 4;
236 }
237
238 return (unsigned char *) p;
239 }