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