xref: /openbsd-src/gnu/usr.bin/binutils/gdb/vax-tdep.c (revision b2ea75c1b17e1a9a339660e7ed45cd24946b230e)
1 /* Print VAX instructions for GDB, the GNU debugger.
2    Copyright 1986, 1989, 1991, 1992 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, Boston, MA 02111-1307, USA.  */
19 
20 #include "defs.h"
21 #include "symtab.h"
22 #include "opcode/vax.h"
23 
24 /* Vax instructions are never longer than this.  */
25 #define MAXLEN 62
26 
27 /* Number of elements in the opcode table.  */
28 #define NOPCODES (sizeof votstrs / sizeof votstrs[0])
29 
30 static unsigned char *print_insn_arg ();
31 
32 /* Print the vax instruction at address MEMADDR in debugged memory,
33    on STREAM.  Returns length of the instruction, in bytes.  */
34 
35 int
36 vax_print_insn (memaddr, stream)
37      CORE_ADDR memaddr;
38      GDB_FILE *stream;
39 {
40   unsigned char buffer[MAXLEN];
41   register int i;
42   register unsigned char *p;
43   register char *d;
44 
45   read_memory (memaddr, buffer, MAXLEN);
46 
47   for (i = 0; i < NOPCODES; i++)
48     if (votstrs[i].detail.code == buffer[0]
49 	|| votstrs[i].detail.code == *(unsigned short *)buffer)
50       break;
51 
52   /* Handle undefined instructions.  */
53   if (i == NOPCODES)
54     {
55       fprintf_unfiltered (stream, "0%o", buffer[0]);
56       return 1;
57     }
58 
59   fprintf_unfiltered (stream, "%s", votstrs[i].name);
60 
61   /* Point at first byte of argument data,
62      and at descriptor for first argument.  */
63   p = buffer + 1 + (votstrs[i].detail.code >= 0x100);
64   d = votstrs[i].detail.args;
65 
66   if (*d)
67     fputc_unfiltered (' ', stream);
68 
69   while (*d)
70     {
71       p = print_insn_arg (d, p, memaddr + (p - buffer), stream);
72       d += 2;
73       if (*d)
74 	fprintf_unfiltered (stream, ",");
75     }
76   return p - buffer;
77 }
78 
79 static unsigned char *
80 print_insn_arg (d, p, addr, stream)
81      char *d;
82      register char *p;
83      CORE_ADDR addr;
84      GDB_FILE *stream;
85 {
86   register int regnum = *p & 0xf;
87   float floatlitbuf;
88 
89   if (*d == 'b')
90     {
91       if (d[1] == 'b')
92 	fprintf_unfiltered (stream, "0x%x", addr + *p++ + 1);
93       else
94 	{
95 	  fprintf_unfiltered (stream, "0x%x", addr + *(short *)p + 2);
96 	  p += 2;
97 	}
98     }
99   else
100     switch ((*p++ >> 4) & 0xf)
101       {
102       case 0:
103       case 1:
104       case 2:
105       case 3:			/* Literal mode */
106 	if (d[1] == 'd' || d[1] == 'f' || d[1] == 'g' || d[1] == 'h')
107 	  {
108 	    *(int *)&floatlitbuf = 0x4000 + ((p[-1] & 0x3f) << 4);
109 	    fprintf_unfiltered (stream, "$%f", floatlitbuf);
110 	  }
111 	else
112 	  fprintf_unfiltered (stream, "$%d", p[-1] & 0x3f);
113 	break;
114 
115       case 4:			/* Indexed */
116 	p = (char *) print_insn_arg (d, p, addr + 1, stream);
117 	fprintf_unfiltered (stream, "[%s]", reg_names[regnum]);
118 	break;
119 
120       case 5:			/* Register */
121 	fprintf_unfiltered (stream, reg_names[regnum]);
122 	break;
123 
124       case 7:			/* Autodecrement */
125 	fputc_unfiltered ('-', stream);
126       case 6:			/* Register deferred */
127 	fprintf_unfiltered (stream, "(%s)", reg_names[regnum]);
128 	break;
129 
130       case 9:			/* Autoincrement deferred */
131 	fputc_unfiltered ('@', stream);
132 	if (regnum == PC_REGNUM)
133 	  {
134 	    fputc_unfiltered ('#', stream);
135 	    print_address (*(long *)p, stream);
136 	    p += 4;
137 	    break;
138 	  }
139       case 8:			/* Autoincrement */
140 	if (regnum == PC_REGNUM)
141 	  {
142 	    fputc_unfiltered ('#', stream);
143 	    switch (d[1])
144 	      {
145 	      case 'b':
146 		fprintf_unfiltered (stream, "%d", *p++);
147 		break;
148 
149 	      case 'w':
150 		fprintf_unfiltered (stream, "%d", *(short *)p);
151 		p += 2;
152 		break;
153 
154 	      case 'l':
155 		fprintf_unfiltered (stream, "%d", *(long *)p);
156 		p += 4;
157 		break;
158 
159 	      case 'q':
160 		fprintf_unfiltered (stream, "0x%x%08x", ((long *)p)[1], ((long *)p)[0]);
161 		p += 8;
162 		break;
163 
164 	      case 'o':
165 		fprintf_unfiltered (stream, "0x%x%08x%08x%08x",
166 			 ((long *)p)[3], ((long *)p)[2],
167 			 ((long *)p)[1], ((long *)p)[0]);
168 		p += 16;
169 		break;
170 
171 	      case 'f':
172 		if (INVALID_FLOAT (p, 4))
173 		  fprintf_unfiltered (stream, "<<invalid float 0x%x>>", *(int *) p);
174 		else
175 		  fprintf_unfiltered (stream, "%f", *(float *) p);
176 		p += 4;
177 		break;
178 
179 	      case 'd':
180 		if (INVALID_FLOAT (p, 8))
181 		  fprintf_unfiltered (stream, "<<invalid float 0x%x%08x>>",
182 			   ((long *)p)[1], ((long *)p)[0]);
183 		else
184 		  fprintf_unfiltered (stream, "%f", *(double *) p);
185 		p += 8;
186 		break;
187 
188 	      case 'g':
189 		fprintf_unfiltered (stream, "g-float");
190 		p += 8;
191 		break;
192 
193 	      case 'h':
194 		fprintf_unfiltered (stream, "h-float");
195 		p += 16;
196 		break;
197 
198 	      }
199 	  }
200 	else
201 	  fprintf_unfiltered (stream, "(%s)+", reg_names[regnum]);
202 	break;
203 
204       case 11:			/* Byte displacement deferred */
205 	fputc_unfiltered ('@', stream);
206       case 10:			/* Byte displacement */
207 	if (regnum == PC_REGNUM)
208 	  print_address (addr + *p + 2, stream);
209 	else
210 	  fprintf_unfiltered (stream, "%d(%s)", *p, reg_names[regnum]);
211 	p += 1;
212 	break;
213 
214       case 13:			/* Word displacement deferred */
215 	fputc_unfiltered ('@', stream);
216       case 12:			/* Word displacement */
217 	if (regnum == PC_REGNUM)
218 	  print_address (addr + *(short *)p + 3, stream);
219 	else
220 	  fprintf_unfiltered (stream, "%d(%s)", *(short *)p, reg_names[regnum]);
221 	p += 2;
222 	break;
223 
224       case 15:			/* Long displacement deferred */
225 	fputc_unfiltered ('@', stream);
226       case 14:			/* Long displacement */
227 	if (regnum == PC_REGNUM)
228 	  print_address (addr + *(long *)p + 5, stream);
229 	else
230 	  fprintf_unfiltered (stream, "%d(%s)", *(long *)p, reg_names[regnum]);
231 	p += 4;
232       }
233 
234   return (unsigned char *) p;
235 }
236