* vax-tdep.c (vax_frame_init_saved_regs): New function.
[deliverable/binutils-gdb.git] / gdb / vax-tdep.c
1 /* Print VAX instructions for GDB, the GNU debugger.
2 Copyright 1986, 1989, 1991, 1992, 1995, 1996, 1998, 1999, 2000, 2002
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
53 static unsigned char *print_insn_arg ();
54 \f
55 char *
56 vax_register_name (int regno)
57 {
58 static char *register_names[] =
59 {
60 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
61 "r8", "r9", "r10", "r11", "ap", "fp", "sp", "pc",
62 "ps",
63 };
64
65 if (regno < 0)
66 return (NULL);
67 if (regno >= (sizeof(register_names) / sizeof(*register_names)))
68 return (NULL);
69 return (register_names[regno]);
70 }
71
72 int
73 vax_register_byte (int regno)
74 {
75 return (regno * 4);
76 }
77
78 int
79 vax_register_raw_size (int regno)
80 {
81 return (4);
82 }
83
84 int
85 vax_register_virtual_size (int regno)
86 {
87 return (4);
88 }
89
90 struct type *
91 vax_register_virtual_type (int regno)
92 {
93 return (builtin_type_int);
94 }
95 \f
96 void
97 vax_frame_init_saved_regs (struct frame_info *frame)
98 {
99 int regnum, regmask;
100 CORE_ADDR next_addr;
101
102 if (frame->saved_regs)
103 return;
104
105 frame_saved_regs_zalloc (frame);
106
107 regmask = read_memory_integer (frame->frame + 4, 4) >> 16;
108
109 next_addr = frame->frame + 16;
110
111 /* regmask's low bit is for register 0, which is the first one
112 what would be pushed. */
113 for (regnum = 0; regnum < AP_REGNUM; regnum++)
114 {
115 if (regmask & (1 << regnum))
116 frame->saved_regs[regnum] = next_addr += 4;
117 }
118
119 frame->saved_regs[SP_REGNUM] = next_addr + 4;
120 if (regmask & (1 << FP_REGNUM))
121 frame->saved_regs[SP_REGNUM] +=
122 4 + (4 * read_memory_integer (next_addr + 4, 4));
123
124 frame->saved_regs[PC_REGNUM] = frame->frame + 16;
125 frame->saved_regs[FP_REGNUM] = frame->frame + 12;
126 frame->saved_regs[AP_REGNUM] = frame->frame + 8;
127 frame->saved_regs[PS_REGNUM] = frame->frame + 4;
128 }
129 \f
130 /* Advance PC across any function entry prologue instructions
131 to reach some "real" code. */
132
133 CORE_ADDR
134 vax_skip_prologue (CORE_ADDR pc)
135 {
136 register int op = (unsigned char) read_memory_integer (pc, 1);
137 if (op == 0x11)
138 pc += 2; /* skip brb */
139 if (op == 0x31)
140 pc += 3; /* skip brw */
141 if (op == 0xC2
142 && ((unsigned char) read_memory_integer (pc + 2, 1)) == 0x5E)
143 pc += 3; /* skip subl2 */
144 if (op == 0x9E
145 && ((unsigned char) read_memory_integer (pc + 1, 1)) == 0xAE
146 && ((unsigned char) read_memory_integer (pc + 3, 1)) == 0x5E)
147 pc += 4; /* skip movab */
148 if (op == 0x9E
149 && ((unsigned char) read_memory_integer (pc + 1, 1)) == 0xCE
150 && ((unsigned char) read_memory_integer (pc + 4, 1)) == 0x5E)
151 pc += 5; /* skip movab */
152 if (op == 0x9E
153 && ((unsigned char) read_memory_integer (pc + 1, 1)) == 0xEE
154 && ((unsigned char) read_memory_integer (pc + 6, 1)) == 0x5E)
155 pc += 7; /* skip movab */
156 return pc;
157 }
158
159 /* Return number of args passed to a frame.
160 Can return -1, meaning no way to tell. */
161
162 int
163 vax_frame_num_args (struct frame_info *fi)
164 {
165 return (0xff & read_memory_integer (FRAME_ARGS_ADDRESS (fi), 1));
166 }
167
168
169
170 /* Print the vax instruction at address MEMADDR in debugged memory,
171 from disassembler info INFO.
172 Returns length of the instruction, in bytes. */
173
174 static int
175 vax_print_insn (CORE_ADDR memaddr, disassemble_info *info)
176 {
177 unsigned char buffer[MAXLEN];
178 register int i;
179 register unsigned char *p;
180 const char *d;
181
182 int status = (*info->read_memory_func) (memaddr, buffer, MAXLEN, info);
183 if (status != 0)
184 {
185 (*info->memory_error_func) (status, memaddr, info);
186 return -1;
187 }
188
189 for (i = 0; i < NOPCODES; i++)
190 if (votstrs[i].detail.code == buffer[0]
191 || votstrs[i].detail.code == *(unsigned short *) buffer)
192 break;
193
194 /* Handle undefined instructions. */
195 if (i == NOPCODES)
196 {
197 (*info->fprintf_func) (info->stream, "0%o", buffer[0]);
198 return 1;
199 }
200
201 (*info->fprintf_func) (info->stream, "%s", votstrs[i].name);
202
203 /* Point at first byte of argument data,
204 and at descriptor for first argument. */
205 p = buffer + 1 + (votstrs[i].detail.code >= 0x100);
206 d = votstrs[i].detail.args;
207
208 if (*d)
209 (*info->fprintf_func) (info->stream, " ");
210
211 while (*d)
212 {
213 p = print_insn_arg (d, p, memaddr + (p - buffer), info);
214 d += 2;
215 if (*d)
216 (*info->fprintf_func) (info->stream, ",");
217 }
218 return p - buffer;
219 }
220
221 static unsigned char *
222 print_insn_arg (char *d, register char *p, CORE_ADDR addr,
223 disassemble_info *info)
224 {
225 register int regnum = *p & 0xf;
226 float floatlitbuf;
227
228 if (*d == 'b')
229 {
230 if (d[1] == 'b')
231 (*info->fprintf_func) (info->stream, "0x%x", addr + *p++ + 1);
232 else
233 {
234 (*info->fprintf_func) (info->stream, "0x%x", addr + *(short *) p + 2);
235 p += 2;
236 }
237 }
238 else
239 switch ((*p++ >> 4) & 0xf)
240 {
241 case 0:
242 case 1:
243 case 2:
244 case 3: /* Literal mode */
245 if (d[1] == 'd' || d[1] == 'f' || d[1] == 'g' || d[1] == 'h')
246 {
247 *(int *) &floatlitbuf = 0x4000 + ((p[-1] & 0x3f) << 4);
248 (*info->fprintf_func) (info->stream, "$%f", floatlitbuf);
249 }
250 else
251 (*info->fprintf_func) (info->stream, "$%d", p[-1] & 0x3f);
252 break;
253
254 case 4: /* Indexed */
255 p = (char *) print_insn_arg (d, p, addr + 1, info);
256 (*info->fprintf_func) (info->stream, "[%s]", REGISTER_NAME (regnum));
257 break;
258
259 case 5: /* Register */
260 (*info->fprintf_func) (info->stream, REGISTER_NAME (regnum));
261 break;
262
263 case 7: /* Autodecrement */
264 (*info->fprintf_func) (info->stream, "-");
265 case 6: /* Register deferred */
266 (*info->fprintf_func) (info->stream, "(%s)", REGISTER_NAME (regnum));
267 break;
268
269 case 9: /* Autoincrement deferred */
270 (*info->fprintf_func) (info->stream, "@");
271 if (regnum == PC_REGNUM)
272 {
273 (*info->fprintf_func) (info->stream, "#");
274 info->target = *(long *) p;
275 (*info->print_address_func) (info->target, info);
276 p += 4;
277 break;
278 }
279 case 8: /* Autoincrement */
280 if (regnum == PC_REGNUM)
281 {
282 (*info->fprintf_func) (info->stream, "#");
283 switch (d[1])
284 {
285 case 'b':
286 (*info->fprintf_func) (info->stream, "%d", *p++);
287 break;
288
289 case 'w':
290 (*info->fprintf_func) (info->stream, "%d", *(short *) p);
291 p += 2;
292 break;
293
294 case 'l':
295 (*info->fprintf_func) (info->stream, "%d", *(long *) p);
296 p += 4;
297 break;
298
299 case 'q':
300 (*info->fprintf_func) (info->stream, "0x%x%08x",
301 ((long *) p)[1], ((long *) p)[0]);
302 p += 8;
303 break;
304
305 case 'o':
306 (*info->fprintf_func) (info->stream, "0x%x%08x%08x%08x",
307 ((long *) p)[3], ((long *) p)[2],
308 ((long *) p)[1], ((long *) p)[0]);
309 p += 16;
310 break;
311
312 case 'f':
313 if (INVALID_FLOAT (p, 4))
314 (*info->fprintf_func) (info->stream,
315 "<<invalid float 0x%x>>",
316 *(int *) p);
317 else
318 (*info->fprintf_func) (info->stream, "%f", *(float *) p);
319 p += 4;
320 break;
321
322 case 'd':
323 if (INVALID_FLOAT (p, 8))
324 (*info->fprintf_func) (info->stream,
325 "<<invalid float 0x%x%08x>>",
326 ((long *) p)[1], ((long *) p)[0]);
327 else
328 (*info->fprintf_func) (info->stream, "%f", *(double *) p);
329 p += 8;
330 break;
331
332 case 'g':
333 (*info->fprintf_func) (info->stream, "g-float");
334 p += 8;
335 break;
336
337 case 'h':
338 (*info->fprintf_func) (info->stream, "h-float");
339 p += 16;
340 break;
341
342 }
343 }
344 else
345 (*info->fprintf_func) (info->stream, "(%s)+", REGISTER_NAME (regnum));
346 break;
347
348 case 11: /* Byte displacement deferred */
349 (*info->fprintf_func) (info->stream, "@");
350 case 10: /* Byte displacement */
351 if (regnum == PC_REGNUM)
352 {
353 info->target = addr + *p + 2;
354 (*info->print_address_func) (info->target, info);
355 }
356 else
357 (*info->fprintf_func) (info->stream, "%d(%s)", *p, REGISTER_NAME (regnum));
358 p += 1;
359 break;
360
361 case 13: /* Word displacement deferred */
362 (*info->fprintf_func) (info->stream, "@");
363 case 12: /* Word displacement */
364 if (regnum == PC_REGNUM)
365 {
366 info->target = addr + *(short *) p + 3;
367 (*info->print_address_func) (info->target, info);
368 }
369 else
370 (*info->fprintf_func) (info->stream, "%d(%s)",
371 *(short *) p, REGISTER_NAME (regnum));
372 p += 2;
373 break;
374
375 case 15: /* Long displacement deferred */
376 (*info->fprintf_func) (info->stream, "@");
377 case 14: /* Long displacement */
378 if (regnum == PC_REGNUM)
379 {
380 info->target = addr + *(short *) p + 5;
381 (*info->print_address_func) (info->target, info);
382 }
383 else
384 (*info->fprintf_func) (info->stream, "%d(%s)",
385 *(long *) p, REGISTER_NAME (regnum));
386 p += 4;
387 }
388
389 return (unsigned char *) p;
390 }
391
392 void
393 _initialize_vax_tdep (void)
394 {
395 tm_print_insn = vax_print_insn;
396 }
This page took 0.038868 seconds and 5 git commands to generate.