* vax-tdep.c (vax_frame_init_saved_regs): New function.
[platform/upstream/binutils.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 }