gdb-2.5.3
[deliverable/binutils-gdb.git] / gdb / vax-pinsn.c
CommitLineData
7b4ac7e1 1/* Print vax instructions for GDB, the GNU debugger.
2 Copyright (C) 1986 Free Software Foundation, Inc.
3
4GDB is distributed in the hope that it will be useful, but WITHOUT ANY
5WARRANTY. No author or distributor accepts responsibility to anyone
6for the consequences of using it or for whether it serves any
7particular purpose or works at all, unless he says so in writing.
8Refer to the GDB General Public License for full details.
9
10Everyone is granted permission to copy, modify and redistribute GDB,
11but only under the conditions described in the GDB General Public
12License. A copy of this license is supposed to have been given to you
13along with GDB so you can know your rights and responsibilities. It
14should be in a file named COPYING. Among other things, the copyright
15notice and this notice must be preserved on all copies.
16
17In other words, go ahead and share GDB, but don't try to stop
18anyone else from sharing it farther. Help stamp out software hoarding!
19*/
20
21#include <stdio.h>
22
23#include "defs.h"
24#include "param.h"
25#include "symtab.h"
26#include "vax-opcode.h"
27
28/* Vax instructions are never longer than this. */
29#define MAXLEN 62
30
31/* Number of elements in the opcode table. */
32#define NOPCODES (sizeof votstrs / sizeof votstrs[0])
33
34extern char *reg_names[];
35
36static unsigned char *print_insn_arg ();
37\f
38/* Print the vax instruction at address MEMADDR in debugged memory,
39 on STREAM. Returns length of the instruction, in bytes. */
40
41int
42print_insn (memaddr, stream)
43 CORE_ADDR memaddr;
44 FILE *stream;
45{
46 unsigned char buffer[MAXLEN];
47 register int i;
48 register unsigned char *p;
49 register char *d;
50
51 read_memory (memaddr, buffer, MAXLEN);
52
53 for (i = 0; i < NOPCODES; i++)
54 if (votstrs[i].detail.code == buffer[0]
55 || votstrs[i].detail.code == *(unsigned short *)buffer)
56 break;
57
58 /* Handle undefined instructions. */
59 if (i == NOPCODES)
60 {
61 fprintf (stream, "0%o", buffer[0]);
62 return 1;
63 }
64
65 fprintf (stream, "%s", votstrs[i].name);
66
67 /* Point at first byte of argument data,
68 and at descriptor for first argument. */
69 p = buffer + 1 + (votstrs[i].detail.code >= 0x100);
70 d = votstrs[i].detail.args;
71
72 if (*d)
73 fputc (' ', stream);
74
75 while (*d)
76 {
77 p = print_insn_arg (d, p, memaddr + (p - buffer), stream);
78 d += 2;
79 if (*d)
80 fprintf (stream, ",");
81 }
82 return p - buffer;
83}
84
85static unsigned char *
86print_insn_arg (d, p, addr, stream)
87 char *d;
88 register char *p;
89 CORE_ADDR addr;
90 FILE *stream;
91{
92 register int regnum = *p & 0xf;
93 float floatlitbuf;
94
95 if (*d == 'b')
96 {
97 if (d[1] == 'b')
98 fprintf (stream, "0x%x", addr + *p++ + 1);
99 else
100 {
101 fprintf (stream, "0x%x", addr + *(short *)p + 2);
102 p += 2;
103 }
104 }
105 else
106 switch ((*p++ >> 4) & 0xf)
107 {
108 case 0:
109 case 1:
110 case 2:
111 case 3: /* Literal mode */
112 if (d[1] == 'd' || d[1] == 'f' || d[1] == 'g' || d[1] == 'h')
113 {
114 *(int *)&floatlitbuf = 0x4000 + ((p[-1] & 0x3f) << 4);
115 fprintf (stream, "$%f", floatlitbuf);
116 }
117 else
118 fprintf (stream, "$%d", p[-1] & 0x3f);
119 break;
120
121 case 4: /* Indexed */
122 p = (char *) print_insn_arg (d, p, addr + 1, stream);
123 fprintf (stream, "[%s]", reg_names[regnum]);
124 break;
125
126 case 5: /* Register */
127 fprintf (stream, reg_names[regnum]);
128 break;
129
130 case 7: /* Autodecrement */
131 fputc ('-', stream);
132 case 6: /* Register deferred */
133 fprintf (stream, "(%s)", reg_names[regnum]);
134 break;
135
136 case 9: /* Autoincrement deferred */
137 fputc ('@', stream);
138 if (regnum == PC_REGNUM)
139 {
140 fputc ('#', stream);
141 print_address (*(long *)p, stream);
142 p += 4;
143 break;
144 }
145 case 8: /* Autoincrement */
146 if (regnum == PC_REGNUM)
147 {
148 fputc ('#', stream);
149 switch (d[1])
150 {
151 case 'b':
152 fprintf (stream, "%d", *p++);
153 break;
154
155 case 'w':
156 fprintf (stream, "%d", *(short *)p);
157 p += 2;
158 break;
159
160 case 'l':
161 fprintf (stream, "%d", *(long *)p);
162 p += 4;
163 break;
164
165 case 'q':
166 fprintf (stream, "0x%x%08x", ((long *)p)[1], ((long *)p)[0]);
167 p += 8;
168 break;
169
170 case 'o':
171 fprintf (stream, "0x%x%08x%08x%08x",
172 ((long *)p)[3], ((long *)p)[2],
173 ((long *)p)[1], ((long *)p)[0]);
174 p += 16;
175 break;
176
177 case 'f':
178 if (INVALID_FLOAT (p, 4))
179 fprintf (stream, "<<invalid float 0x%x>>", *(int *) p);
180 else
181 fprintf (stream, "%f", *(float *) p);
182 p += 4;
183 break;
184
185 case 'd':
186 if (INVALID_FLOAT (p, 8))
187 fprintf (stream, "<<invalid float 0x%x%08x>>",
188 ((long *)p)[1], ((long *)p)[0]);
189 else
190 fprintf (stream, "%f", *(double *) p);
191 p += 8;
192 break;
193
194 case 'g':
195 fprintf (stream, "g-float");
196 p += 8;
197 break;
198
199 case 'h':
200 fprintf (stream, "h-float");
201 p += 16;
202 break;
203
204 }
205 }
206 else
207 fprintf (stream, "(%s)+", reg_names[regnum]);
208 break;
209
210 case 11: /* Byte displacement deferred */
211 fputc ('@', stream);
212 case 10: /* Byte displacement */
213 if (regnum == PC_REGNUM)
214 print_address (addr + *p + 2, stream);
215 else
216 fprintf (stream, "%d(%s)", *p, reg_names[regnum]);
217 p += 1;
218 break;
219
220 case 13: /* Word displacement deferred */
221 fputc ('@', stream);
222 case 12: /* Word displacement */
223 if (regnum == PC_REGNUM)
224 print_address (addr + *(short *)p + 3, stream);
225 else
226 fprintf (stream, "%d(%s)", *(short *)p, reg_names[regnum]);
227 p += 2;
228 break;
229
230 case 15: /* Long displacement deferred */
231 fputc ('@', stream);
232 case 14: /* Long displacement */
233 if (regnum == PC_REGNUM)
234 print_address (addr + *(long *)p + 5, stream);
235 else
236 fprintf (stream, "%d(%s)", *(long *)p, reg_names[regnum]);
237 p += 4;
238 }
239
240 return (unsigned char *) p;
241}
This page took 0.03248 seconds and 4 git commands to generate.