* linker.c (link_action): Ignore duplicate warning syms.
[deliverable/binutils-gdb.git] / gdb / vax-tdep.c
... / ...
CommitLineData
1/* Print VAX instructions for GDB, the GNU debugger.
2 Copyright 1986, 1989, 1991, 1992, 1995, 1996, 1998, 1999, 2000
3 Free Software Foundation, Inc.
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
21
22#include "defs.h"
23#include "symtab.h"
24#include "opcode/vax.h"
25#include "gdbcore.h"
26#include "frame.h"
27#include "value.h"
28
29/* Return 1 if P points to an invalid floating point value.
30 LEN is the length in bytes -- not relevant on the Vax. */
31
32/* FIXME: cagney/2002-01-19: The macro below was originally defined in
33 tm-vax.h and used in values.c. Two problems. Firstly this is a
34 very non-portable and secondly it is wrong. The VAX should be
35 using floatformat and associated methods to identify and handle
36 invalid floating-point values. Adding to the poor target's woes
37 there is no floatformat_vax_{f,d} and no TARGET_FLOAT_FORMAT
38 et.al.. */
39
40/* FIXME: cagney/2002-01-19: It turns out that the only thing that
41 uses this macro is the vax disassembler code (so how old is this
42 target?). This target should instead be using the opcodes
43 disassembler. That allowing the macro to be eliminated. */
44
45#define INVALID_FLOAT(p, len) ((*(short *) p & 0xff80) == 0x8000)
46
47/* Vax instructions are never longer than this. */
48#define MAXLEN 62
49
50/* Number of elements in the opcode table. */
51#define NOPCODES (sizeof votstrs / sizeof votstrs[0])
52
53static unsigned char *print_insn_arg ();
54\f
55/* Advance PC across any function entry prologue instructions
56 to reach some "real" code. */
57
58CORE_ADDR
59vax_skip_prologue (CORE_ADDR pc)
60{
61 register int op = (unsigned char) read_memory_integer (pc, 1);
62 if (op == 0x11)
63 pc += 2; /* skip brb */
64 if (op == 0x31)
65 pc += 3; /* skip brw */
66 if (op == 0xC2
67 && ((unsigned char) read_memory_integer (pc + 2, 1)) == 0x5E)
68 pc += 3; /* skip subl2 */
69 if (op == 0x9E
70 && ((unsigned char) read_memory_integer (pc + 1, 1)) == 0xAE
71 && ((unsigned char) read_memory_integer (pc + 3, 1)) == 0x5E)
72 pc += 4; /* skip movab */
73 if (op == 0x9E
74 && ((unsigned char) read_memory_integer (pc + 1, 1)) == 0xCE
75 && ((unsigned char) read_memory_integer (pc + 4, 1)) == 0x5E)
76 pc += 5; /* skip movab */
77 if (op == 0x9E
78 && ((unsigned char) read_memory_integer (pc + 1, 1)) == 0xEE
79 && ((unsigned char) read_memory_integer (pc + 6, 1)) == 0x5E)
80 pc += 7; /* skip movab */
81 return pc;
82}
83
84/* Return number of args passed to a frame.
85 Can return -1, meaning no way to tell. */
86
87int
88vax_frame_num_args (struct frame_info *fi)
89{
90 return (0xff & read_memory_integer (FRAME_ARGS_ADDRESS (fi), 1));
91}
92
93
94
95/* Print the vax instruction at address MEMADDR in debugged memory,
96 from disassembler info INFO.
97 Returns length of the instruction, in bytes. */
98
99static int
100vax_print_insn (CORE_ADDR memaddr, disassemble_info *info)
101{
102 unsigned char buffer[MAXLEN];
103 register int i;
104 register unsigned char *p;
105 const char *d;
106
107 int status = (*info->read_memory_func) (memaddr, buffer, MAXLEN, info);
108 if (status != 0)
109 {
110 (*info->memory_error_func) (status, memaddr, info);
111 return -1;
112 }
113
114 for (i = 0; i < NOPCODES; i++)
115 if (votstrs[i].detail.code == buffer[0]
116 || votstrs[i].detail.code == *(unsigned short *) buffer)
117 break;
118
119 /* Handle undefined instructions. */
120 if (i == NOPCODES)
121 {
122 (*info->fprintf_func) (info->stream, "0%o", buffer[0]);
123 return 1;
124 }
125
126 (*info->fprintf_func) (info->stream, "%s", votstrs[i].name);
127
128 /* Point at first byte of argument data,
129 and at descriptor for first argument. */
130 p = buffer + 1 + (votstrs[i].detail.code >= 0x100);
131 d = votstrs[i].detail.args;
132
133 if (*d)
134 (*info->fprintf_func) (info->stream, " ");
135
136 while (*d)
137 {
138 p = print_insn_arg (d, p, memaddr + (p - buffer), info);
139 d += 2;
140 if (*d)
141 (*info->fprintf_func) (info->stream, ",");
142 }
143 return p - buffer;
144}
145
146static unsigned char *
147print_insn_arg (char *d, register char *p, CORE_ADDR addr,
148 disassemble_info *info)
149{
150 register int regnum = *p & 0xf;
151 float floatlitbuf;
152
153 if (*d == 'b')
154 {
155 if (d[1] == 'b')
156 (*info->fprintf_func) (info->stream, "0x%x", addr + *p++ + 1);
157 else
158 {
159 (*info->fprintf_func) (info->stream, "0x%x", addr + *(short *) p + 2);
160 p += 2;
161 }
162 }
163 else
164 switch ((*p++ >> 4) & 0xf)
165 {
166 case 0:
167 case 1:
168 case 2:
169 case 3: /* Literal mode */
170 if (d[1] == 'd' || d[1] == 'f' || d[1] == 'g' || d[1] == 'h')
171 {
172 *(int *) &floatlitbuf = 0x4000 + ((p[-1] & 0x3f) << 4);
173 (*info->fprintf_func) (info->stream, "$%f", floatlitbuf);
174 }
175 else
176 (*info->fprintf_func) (info->stream, "$%d", p[-1] & 0x3f);
177 break;
178
179 case 4: /* Indexed */
180 p = (char *) print_insn_arg (d, p, addr + 1, info);
181 (*info->fprintf_func) (info->stream, "[%s]", REGISTER_NAME (regnum));
182 break;
183
184 case 5: /* Register */
185 (*info->fprintf_func) (info->stream, REGISTER_NAME (regnum));
186 break;
187
188 case 7: /* Autodecrement */
189 (*info->fprintf_func) (info->stream, "-");
190 case 6: /* Register deferred */
191 (*info->fprintf_func) (info->stream, "(%s)", REGISTER_NAME (regnum));
192 break;
193
194 case 9: /* Autoincrement deferred */
195 (*info->fprintf_func) (info->stream, "@");
196 if (regnum == PC_REGNUM)
197 {
198 (*info->fprintf_func) (info->stream, "#");
199 info->target = *(long *) p;
200 (*info->print_address_func) (info->target, info);
201 p += 4;
202 break;
203 }
204 case 8: /* Autoincrement */
205 if (regnum == PC_REGNUM)
206 {
207 (*info->fprintf_func) (info->stream, "#");
208 switch (d[1])
209 {
210 case 'b':
211 (*info->fprintf_func) (info->stream, "%d", *p++);
212 break;
213
214 case 'w':
215 (*info->fprintf_func) (info->stream, "%d", *(short *) p);
216 p += 2;
217 break;
218
219 case 'l':
220 (*info->fprintf_func) (info->stream, "%d", *(long *) p);
221 p += 4;
222 break;
223
224 case 'q':
225 (*info->fprintf_func) (info->stream, "0x%x%08x",
226 ((long *) p)[1], ((long *) p)[0]);
227 p += 8;
228 break;
229
230 case 'o':
231 (*info->fprintf_func) (info->stream, "0x%x%08x%08x%08x",
232 ((long *) p)[3], ((long *) p)[2],
233 ((long *) p)[1], ((long *) p)[0]);
234 p += 16;
235 break;
236
237 case 'f':
238 if (INVALID_FLOAT (p, 4))
239 (*info->fprintf_func) (info->stream,
240 "<<invalid float 0x%x>>",
241 *(int *) p);
242 else
243 (*info->fprintf_func) (info->stream, "%f", *(float *) p);
244 p += 4;
245 break;
246
247 case 'd':
248 if (INVALID_FLOAT (p, 8))
249 (*info->fprintf_func) (info->stream,
250 "<<invalid float 0x%x%08x>>",
251 ((long *) p)[1], ((long *) p)[0]);
252 else
253 (*info->fprintf_func) (info->stream, "%f", *(double *) p);
254 p += 8;
255 break;
256
257 case 'g':
258 (*info->fprintf_func) (info->stream, "g-float");
259 p += 8;
260 break;
261
262 case 'h':
263 (*info->fprintf_func) (info->stream, "h-float");
264 p += 16;
265 break;
266
267 }
268 }
269 else
270 (*info->fprintf_func) (info->stream, "(%s)+", REGISTER_NAME (regnum));
271 break;
272
273 case 11: /* Byte displacement deferred */
274 (*info->fprintf_func) (info->stream, "@");
275 case 10: /* Byte displacement */
276 if (regnum == PC_REGNUM)
277 {
278 info->target = addr + *p + 2;
279 (*info->print_address_func) (info->target, info);
280 }
281 else
282 (*info->fprintf_func) (info->stream, "%d(%s)", *p, REGISTER_NAME (regnum));
283 p += 1;
284 break;
285
286 case 13: /* Word displacement deferred */
287 (*info->fprintf_func) (info->stream, "@");
288 case 12: /* Word displacement */
289 if (regnum == PC_REGNUM)
290 {
291 info->target = addr + *(short *) p + 3;
292 (*info->print_address_func) (info->target, info);
293 }
294 else
295 (*info->fprintf_func) (info->stream, "%d(%s)",
296 *(short *) p, REGISTER_NAME (regnum));
297 p += 2;
298 break;
299
300 case 15: /* Long displacement deferred */
301 (*info->fprintf_func) (info->stream, "@");
302 case 14: /* Long displacement */
303 if (regnum == PC_REGNUM)
304 {
305 info->target = addr + *(short *) p + 5;
306 (*info->print_address_func) (info->target, info);
307 }
308 else
309 (*info->fprintf_func) (info->stream, "%d(%s)",
310 *(long *) p, REGISTER_NAME (regnum));
311 p += 4;
312 }
313
314 return (unsigned char *) p;
315}
316
317void
318_initialize_vax_tdep (void)
319{
320 tm_print_insn = vax_print_insn;
321}
This page took 0.026703 seconds and 4 git commands to generate.