BSD 4_3_Net_2 release
[unix-history] / usr / src / usr.bin / gdb / config / vax-pinsn.c
CommitLineData
af359dea
C
1/*-
2 * This code is derived from software copyrighted by the Free Software
3 * Foundation.
4 *
5 * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
6 */
7
8#ifndef lint
9static char sccsid[] = "@(#)vax-pinsn.c 6.3 (Berkeley) 5/8/91";
10#endif /* not lint */
11
12/* Print vax instructions for GDB, the GNU debugger.
13 Copyright (C) 1986, 1989 Free Software Foundation, Inc.
14
15This file is part of GDB.
16
17GDB is free software; you can redistribute it and/or modify
18it under the terms of the GNU General Public License as published by
19the Free Software Foundation; either version 1, or (at your option)
20any later version.
21
22GDB is distributed in the hope that it will be useful,
23but WITHOUT ANY WARRANTY; without even the implied warranty of
24MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25GNU General Public License for more details.
26
27You should have received a copy of the GNU General Public License
28along with GDB; see the file COPYING. If not, write to
29the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
30
31#include <stdio.h>
32
33#include "defs.h"
34#include "param.h"
35#include "symtab.h"
36#include "vax-opcode.h"
37
38/* Vax instructions are never longer than this. */
39#define MAXLEN 62
40
41/* Number of elements in the opcode table. */
42#define NOPCODES (sizeof votstrs / sizeof votstrs[0])
43
44extern char *reg_names[];
45
46static unsigned char *print_insn_arg ();
47\f
48/* Print the vax instruction at address MEMADDR in debugged memory,
49 on STREAM. Returns length of the instruction, in bytes. */
50
51int
52print_insn (memaddr, stream)
53 CORE_ADDR memaddr;
54 FILE *stream;
55{
56 unsigned char buffer[MAXLEN];
57 register int i;
58 register unsigned char *p;
59 register char *d;
60
61 read_memory (memaddr, buffer, MAXLEN);
62
63 for (i = 0; i < NOPCODES; i++)
64 if (votstrs[i].detail.code == buffer[0]
65 || votstrs[i].detail.code == *(unsigned short *)buffer)
66 break;
67
68 /* Handle undefined instructions. */
69 if (i == NOPCODES)
70 {
71 fprintf (stream, "0%o", buffer[0]);
72 return 1;
73 }
74
75 fprintf (stream, "%s", votstrs[i].name);
76
77 /* Point at first byte of argument data,
78 and at descriptor for first argument. */
79 p = buffer + 1 + (votstrs[i].detail.code >= 0x100);
80 d = votstrs[i].detail.args;
81
82 if (*d)
83 fputc (' ', stream);
84
85 while (*d)
86 {
87 p = print_insn_arg (d, p, memaddr + (p - buffer), stream);
88 d += 2;
89 if (*d)
90 fprintf (stream, ",");
91 }
92 return p - buffer;
93}
94
95static unsigned char *
96print_insn_arg (d, p, addr, stream)
97 char *d;
98 register char *p;
99 CORE_ADDR addr;
100 FILE *stream;
101{
102 register int regnum = *p & 0xf;
103 float floatlitbuf;
104
105 if (*d == 'b')
106 {
107 if (d[1] == 'b')
108 fprintf (stream, "0x%x", addr + *p++ + 1);
109 else
110 {
111 fprintf (stream, "0x%x", addr + *(short *)p + 2);
112 p += 2;
113 }
114 }
115 else
116 switch ((*p++ >> 4) & 0xf)
117 {
118 case 0:
119 case 1:
120 case 2:
121 case 3: /* Literal mode */
122 if (d[1] == 'd' || d[1] == 'f' || d[1] == 'g' || d[1] == 'h')
123 {
124 *(int *)&floatlitbuf = 0x4000 + ((p[-1] & 0x3f) << 4);
125 fprintf (stream, "$%f", floatlitbuf);
126 }
127 else
128 fprintf (stream, "$%d", p[-1] & 0x3f);
129 break;
130
131 case 4: /* Indexed */
132 p = (char *) print_insn_arg (d, p, addr + 1, stream);
133 fprintf (stream, "[%s]", reg_names[regnum]);
134 break;
135
136 case 5: /* Register */
137 fprintf (stream, reg_names[regnum]);
138 break;
139
140 case 7: /* Autodecrement */
141 fputc ('-', stream);
142 case 6: /* Register deferred */
143 fprintf (stream, "(%s)", reg_names[regnum]);
144 break;
145
146 case 9: /* Autoincrement deferred */
147 fputc ('@', stream);
148 if (regnum == PC_REGNUM)
149 {
150 fputc ('#', stream);
151 print_address (*(long *)p, stream);
152 p += 4;
153 break;
154 }
155 case 8: /* Autoincrement */
156 if (regnum == PC_REGNUM)
157 {
158 fputc ('#', stream);
159 switch (d[1])
160 {
161 case 'b':
162 fprintf (stream, "%d", *p++);
163 break;
164
165 case 'w':
166 fprintf (stream, "%d", *(short *)p);
167 p += 2;
168 break;
169
170 case 'l':
171 fprintf (stream, "%d", *(long *)p);
172 p += 4;
173 break;
174
175 case 'q':
176 fprintf (stream, "0x%x%08x", ((long *)p)[1], ((long *)p)[0]);
177 p += 8;
178 break;
179
180 case 'o':
181 fprintf (stream, "0x%x%08x%08x%08x",
182 ((long *)p)[3], ((long *)p)[2],
183 ((long *)p)[1], ((long *)p)[0]);
184 p += 16;
185 break;
186
187 case 'f':
188 if (INVALID_FLOAT (p, 4))
189 fprintf (stream, "<<invalid float 0x%x>>", *(int *) p);
190 else
191 fprintf (stream, "%f", *(float *) p);
192 p += 4;
193 break;
194
195 case 'd':
196 if (INVALID_FLOAT (p, 8))
197 fprintf (stream, "<<invalid float 0x%x%08x>>",
198 ((long *)p)[1], ((long *)p)[0]);
199 else
200 fprintf (stream, "%f", *(double *) p);
201 p += 8;
202 break;
203
204 case 'g':
205 fprintf (stream, "g-float");
206 p += 8;
207 break;
208
209 case 'h':
210 fprintf (stream, "h-float");
211 p += 16;
212 break;
213
214 }
215 }
216 else
217 fprintf (stream, "(%s)+", reg_names[regnum]);
218 break;
219
220 case 11: /* Byte displacement deferred */
221 fputc ('@', stream);
222 case 10: /* Byte displacement */
223 if (regnum == PC_REGNUM)
224 print_address (addr + *p + 2, stream);
225 else
226 fprintf (stream, "%d(%s)", *p, reg_names[regnum]);
227 p += 1;
228 break;
229
230 case 13: /* Word displacement deferred */
231 fputc ('@', stream);
232 case 12: /* Word displacement */
233 if (regnum == PC_REGNUM)
234 print_address (addr + *(short *)p + 3, stream);
235 else
236 fprintf (stream, "%d(%s)", *(short *)p, reg_names[regnum]);
237 p += 2;
238 break;
239
240 case 15: /* Long displacement deferred */
241 fputc ('@', stream);
242 case 14: /* Long displacement */
243 if (regnum == PC_REGNUM)
244 print_address (addr + *(long *)p + 5, stream);
245 else
246 fprintf (stream, "%d(%s)", *(long *)p, reg_names[regnum]);
247 p += 4;
248 }
249
250 return (unsigned char *) p;
251}