* vax-tdep.c: Update copyright years.
[external/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 /* Advance PC across any function entry prologue instructions
97    to reach some "real" code.  */
98
99 CORE_ADDR
100 vax_skip_prologue (CORE_ADDR pc)
101 {
102   register int op = (unsigned char) read_memory_integer (pc, 1);
103   if (op == 0x11)
104     pc += 2;                    /* skip brb */
105   if (op == 0x31)
106     pc += 3;                    /* skip brw */
107   if (op == 0xC2
108       && ((unsigned char) read_memory_integer (pc + 2, 1)) == 0x5E)
109     pc += 3;                    /* skip subl2 */
110   if (op == 0x9E
111       && ((unsigned char) read_memory_integer (pc + 1, 1)) == 0xAE
112       && ((unsigned char) read_memory_integer (pc + 3, 1)) == 0x5E)
113     pc += 4;                    /* skip movab */
114   if (op == 0x9E
115       && ((unsigned char) read_memory_integer (pc + 1, 1)) == 0xCE
116       && ((unsigned char) read_memory_integer (pc + 4, 1)) == 0x5E)
117     pc += 5;                    /* skip movab */
118   if (op == 0x9E
119       && ((unsigned char) read_memory_integer (pc + 1, 1)) == 0xEE
120       && ((unsigned char) read_memory_integer (pc + 6, 1)) == 0x5E)
121     pc += 7;                    /* skip movab */
122   return pc;
123 }
124
125 /* Return number of args passed to a frame.
126    Can return -1, meaning no way to tell.  */
127
128 int
129 vax_frame_num_args (struct frame_info *fi)
130 {
131   return (0xff & read_memory_integer (FRAME_ARGS_ADDRESS (fi), 1));
132 }
133
134
135
136 /* Print the vax instruction at address MEMADDR in debugged memory,
137    from disassembler info INFO.
138    Returns length of the instruction, in bytes.  */
139
140 static int
141 vax_print_insn (CORE_ADDR memaddr, disassemble_info *info)
142 {
143   unsigned char buffer[MAXLEN];
144   register int i;
145   register unsigned char *p;
146   const char *d;
147
148   int status = (*info->read_memory_func) (memaddr, buffer, MAXLEN, info);
149   if (status != 0)
150     {
151       (*info->memory_error_func) (status, memaddr, info);
152       return -1;
153     }
154
155   for (i = 0; i < NOPCODES; i++)
156     if (votstrs[i].detail.code == buffer[0]
157         || votstrs[i].detail.code == *(unsigned short *) buffer)
158       break;
159
160   /* Handle undefined instructions.  */
161   if (i == NOPCODES)
162     {
163       (*info->fprintf_func) (info->stream, "0%o", buffer[0]);
164       return 1;
165     }
166
167   (*info->fprintf_func) (info->stream, "%s", votstrs[i].name);
168
169   /* Point at first byte of argument data,
170      and at descriptor for first argument.  */
171   p = buffer + 1 + (votstrs[i].detail.code >= 0x100);
172   d = votstrs[i].detail.args;
173
174   if (*d)
175     (*info->fprintf_func) (info->stream, " ");
176
177   while (*d)
178     {
179       p = print_insn_arg (d, p, memaddr + (p - buffer), info);
180       d += 2;
181       if (*d)
182         (*info->fprintf_func) (info->stream, ",");
183     }
184   return p - buffer;
185 }
186
187 static unsigned char *
188 print_insn_arg (char *d, register char *p, CORE_ADDR addr,
189                 disassemble_info *info)
190 {
191   register int regnum = *p & 0xf;
192   float floatlitbuf;
193
194   if (*d == 'b')
195     {
196       if (d[1] == 'b')
197         (*info->fprintf_func) (info->stream, "0x%x", addr + *p++ + 1);
198       else
199         {
200           (*info->fprintf_func) (info->stream, "0x%x", addr + *(short *) p + 2);
201           p += 2;
202         }
203     }
204   else
205     switch ((*p++ >> 4) & 0xf)
206       {
207       case 0:
208       case 1:
209       case 2:
210       case 3:                   /* Literal mode */
211         if (d[1] == 'd' || d[1] == 'f' || d[1] == 'g' || d[1] == 'h')
212           {
213             *(int *) &floatlitbuf = 0x4000 + ((p[-1] & 0x3f) << 4);
214             (*info->fprintf_func) (info->stream, "$%f", floatlitbuf);
215           }
216         else
217           (*info->fprintf_func) (info->stream, "$%d", p[-1] & 0x3f);
218         break;
219
220       case 4:                   /* Indexed */
221         p = (char *) print_insn_arg (d, p, addr + 1, info);
222         (*info->fprintf_func) (info->stream, "[%s]", REGISTER_NAME (regnum));
223         break;
224
225       case 5:                   /* Register */
226         (*info->fprintf_func) (info->stream, REGISTER_NAME (regnum));
227         break;
228
229       case 7:                   /* Autodecrement */
230         (*info->fprintf_func) (info->stream, "-");
231       case 6:                   /* Register deferred */
232         (*info->fprintf_func) (info->stream, "(%s)", REGISTER_NAME (regnum));
233         break;
234
235       case 9:                   /* Autoincrement deferred */
236         (*info->fprintf_func) (info->stream, "@");
237         if (regnum == PC_REGNUM)
238           {
239             (*info->fprintf_func) (info->stream, "#");
240             info->target = *(long *) p;
241             (*info->print_address_func) (info->target, info);
242             p += 4;
243             break;
244           }
245       case 8:                   /* Autoincrement */
246         if (regnum == PC_REGNUM)
247           {
248             (*info->fprintf_func) (info->stream, "#");
249             switch (d[1])
250               {
251               case 'b':
252                 (*info->fprintf_func) (info->stream, "%d", *p++);
253                 break;
254
255               case 'w':
256                 (*info->fprintf_func) (info->stream, "%d", *(short *) p);
257                 p += 2;
258                 break;
259
260               case 'l':
261                 (*info->fprintf_func) (info->stream, "%d", *(long *) p);
262                 p += 4;
263                 break;
264
265               case 'q':
266                 (*info->fprintf_func) (info->stream, "0x%x%08x",
267                                        ((long *) p)[1], ((long *) p)[0]);
268                 p += 8;
269                 break;
270
271               case 'o':
272                 (*info->fprintf_func) (info->stream, "0x%x%08x%08x%08x",
273                                        ((long *) p)[3], ((long *) p)[2],
274                                        ((long *) p)[1], ((long *) p)[0]);
275                 p += 16;
276                 break;
277
278               case 'f':
279                 if (INVALID_FLOAT (p, 4))
280                   (*info->fprintf_func) (info->stream,
281                                          "<<invalid float 0x%x>>",
282                                          *(int *) p);
283                 else
284                   (*info->fprintf_func) (info->stream, "%f", *(float *) p);
285                 p += 4;
286                 break;
287
288               case 'd':
289                 if (INVALID_FLOAT (p, 8))
290                   (*info->fprintf_func) (info->stream,
291                                          "<<invalid float 0x%x%08x>>",
292                                          ((long *) p)[1], ((long *) p)[0]);
293                 else
294                   (*info->fprintf_func) (info->stream, "%f", *(double *) p);
295                 p += 8;
296                 break;
297
298               case 'g':
299                 (*info->fprintf_func) (info->stream, "g-float");
300                 p += 8;
301                 break;
302
303               case 'h':
304                 (*info->fprintf_func) (info->stream, "h-float");
305                 p += 16;
306                 break;
307
308               }
309           }
310         else
311           (*info->fprintf_func) (info->stream, "(%s)+", REGISTER_NAME (regnum));
312         break;
313
314       case 11:                  /* Byte displacement deferred */
315         (*info->fprintf_func) (info->stream, "@");
316       case 10:                  /* Byte displacement */
317         if (regnum == PC_REGNUM)
318           {
319             info->target = addr + *p + 2;
320             (*info->print_address_func) (info->target, info);
321           }
322         else
323           (*info->fprintf_func) (info->stream, "%d(%s)", *p, REGISTER_NAME (regnum));
324         p += 1;
325         break;
326
327       case 13:                  /* Word displacement deferred */
328         (*info->fprintf_func) (info->stream, "@");
329       case 12:                  /* Word displacement */
330         if (regnum == PC_REGNUM)
331           {
332             info->target = addr + *(short *) p + 3;
333             (*info->print_address_func) (info->target, info);
334           }
335         else
336           (*info->fprintf_func) (info->stream, "%d(%s)",
337                                  *(short *) p, REGISTER_NAME (regnum));
338         p += 2;
339         break;
340
341       case 15:                  /* Long displacement deferred */
342         (*info->fprintf_func) (info->stream, "@");
343       case 14:                  /* Long displacement */
344         if (regnum == PC_REGNUM)
345           {
346             info->target = addr + *(short *) p + 5;
347             (*info->print_address_func) (info->target, info);
348           }
349         else
350           (*info->fprintf_func) (info->stream, "%d(%s)",
351                                  *(long *) p, REGISTER_NAME (regnum));
352         p += 4;
353       }
354
355   return (unsigned char *) p;
356 }
357
358 void
359 _initialize_vax_tdep (void)
360 {
361   tm_print_insn = vax_print_insn;
362 }