source: branches/libc-0.6/src/binutils/opcodes/vax-dis.c

Last change on this file was 610, checked in by bird, 22 years ago

This commit was generated by cvs2svn to compensate for changes in r609,
which included commits to RCS files with non-trunk default branches.

  • Property cvs2svn:cvs-rev set to 1.1.1.2
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 9.5 KB
Line 
1/* Print VAX instructions.
2 Copyright 1995, 1998, 2000, 2001, 2002 Free Software Foundation, Inc.
3 Contributed by Pauline Middelink <middelin@polyware.iaf.nl>
4
5This program is free software; you can redistribute it and/or modify
6it under the terms of the GNU General Public License as published by
7the Free Software Foundation; either version 2 of the License, or
8(at your option) any later version.
9
10This program is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program; if not, write to the Free Software
17Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
18
19#include "sysdep.h"
20#include "opcode/vax.h"
21#include "dis-asm.h"
22
23/* Local function prototypes */
24static int fetch_data PARAMS ((struct disassemble_info *, bfd_byte *));
25static int print_insn_arg
26 PARAMS ((const char *, unsigned char *, bfd_vma, disassemble_info *));
27static int print_insn_mode
28 PARAMS ((const char *, int, unsigned char *, bfd_vma, disassemble_info *));
29
30
31static char *reg_names[] =
32{
33 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
34 "r8", "r9", "r10", "r11", "ap", "fp", "sp", "pc"
35};
36
37/* Sign-extend an (unsigned char). */
38#if __STDC__ == 1
39#define COERCE_SIGNED_CHAR(ch) ((signed char)(ch))
40#else
41#define COERCE_SIGNED_CHAR(ch) ((int)(((ch) ^ 0x80) & 0xFF) - 128)
42#endif
43
44/* Get a 1 byte signed integer. */
45#define NEXTBYTE(p) \
46 (p += 1, FETCH_DATA (info, p), \
47 COERCE_SIGNED_CHAR(p[-1]))
48
49/* Get a 2 byte signed integer. */
50#define COERCE16(x) ((int) (((x) ^ 0x8000) - 0x8000))
51#define NEXTWORD(p) \
52 (p += 2, FETCH_DATA (info, p), \
53 COERCE16 ((p[-1] << 8) + p[-2]))
54
55/* Get a 4 byte signed integer. */
56#define COERCE32(x) ((int) (((x) ^ 0x80000000) - 0x80000000))
57#define NEXTLONG(p) \
58 (p += 4, FETCH_DATA (info, p), \
59 (COERCE32 ((((((p[-1] << 8) + p[-2]) << 8) + p[-3]) << 8) + p[-4])))
60
61/* Maximum length of an instruction. */
62#define MAXLEN 25
63
64#include <setjmp.h>
65
66struct private
67{
68 /* Points to first byte not fetched. */
69 bfd_byte *max_fetched;
70 bfd_byte the_buffer[MAXLEN];
71 bfd_vma insn_start;
72 jmp_buf bailout;
73};
74
75/* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
76 to ADDR (exclusive) are valid. Returns 1 for success, longjmps
77 on error. */
78#define FETCH_DATA(info, addr) \
79 ((addr) <= ((struct private *)(info->private_data))->max_fetched \
80 ? 1 : fetch_data ((info), (addr)))
81
82static int
83fetch_data (info, addr)
84 struct disassemble_info *info;
85 bfd_byte *addr;
86{
87 int status;
88 struct private *priv = (struct private *) info->private_data;
89 bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer);
90
91 status = (*info->read_memory_func) (start,
92 priv->max_fetched,
93 addr - priv->max_fetched,
94 info);
95 if (status != 0)
96 {
97 (*info->memory_error_func) (status, start, info);
98 longjmp (priv->bailout, 1);
99 }
100 else
101 priv->max_fetched = addr;
102
103 return 1;
104}
105
106/* Print the vax instruction at address MEMADDR in debugged memory,
107 on INFO->STREAM. Returns length of the instruction, in bytes. */
108
109int
110print_insn_vax (memaddr, info)
111 bfd_vma memaddr;
112 disassemble_info *info;
113{
114 const struct vot *votp;
115 const char *argp;
116 unsigned char *arg;
117 struct private priv;
118 bfd_byte *buffer = priv.the_buffer;
119
120 info->private_data = (PTR) &priv;
121 priv.max_fetched = priv.the_buffer;
122 priv.insn_start = memaddr;
123
124 if (setjmp (priv.bailout) != 0)
125 {
126 /* Error return. */
127 return -1;
128 }
129
130 argp = NULL;
131 /* Check if the info buffer has more than one byte left since
132 the last opcode might be a single byte with no argument data. */
133 if (info->buffer_length - (memaddr - info->buffer_vma) > 1)
134 {
135 FETCH_DATA (info, buffer + 2);
136 }
137 else
138 {
139 FETCH_DATA (info, buffer + 1);
140 buffer[1] = 0;
141 }
142
143 for (votp = &votstrs[0]; votp->name[0]; votp++)
144 {
145 register vax_opcodeT opcode = votp->detail.code;
146
147 /* 2 byte codes match 2 buffer pos. */
148 if ((bfd_byte) opcode == buffer[0]
149 && (opcode >> 8 == 0 || opcode >> 8 == buffer[1]))
150 {
151 argp = votp->detail.args;
152 break;
153 }
154 }
155 if (argp == NULL)
156 {
157 /* Handle undefined instructions. */
158 (*info->fprintf_func) (info->stream, ".word 0x%x",
159 (buffer[0] << 8) + buffer[1]);
160 return 2;
161 }
162
163 /* Point at first byte of argument data, and at descriptor for first
164 argument. */
165 arg = buffer + ((votp->detail.code >> 8) ? 2 : 1);
166
167 /* Make sure we have it in mem */
168 FETCH_DATA (info, arg);
169
170 (*info->fprintf_func) (info->stream, "%s", votp->name);
171 if (*argp)
172 (*info->fprintf_func) (info->stream, " ");
173
174 while (*argp)
175 {
176 arg += print_insn_arg (argp, arg, memaddr + arg - buffer, info);
177 argp += 2;
178 if (*argp)
179 (*info->fprintf_func) (info->stream, ",");
180 }
181
182 return arg - buffer;
183}
184
185/* Returns number of bytes "eaten" by the operand, or return -1 if an
186 invalid operand was found, or -2 if an opcode tabel error was
187 found. */
188
189static int
190print_insn_arg (d, p0, addr, info)
191 const char *d;
192 unsigned char *p0;
193 bfd_vma addr; /* PC for this arg to be relative to */
194 disassemble_info *info;
195{
196 int arg_len;
197
198 /* check validity of addressing length */
199 switch (d[1])
200 {
201 case 'b' : arg_len = 1; break;
202 case 'd' : arg_len = 8; break;
203 case 'f' : arg_len = 4; break;
204 case 'g' : arg_len = 8; break;
205 case 'h' : arg_len = 16; break;
206 case 'l' : arg_len = 4; break;
207 case 'o' : arg_len = 16; break;
208 case 'w' : arg_len = 2; break;
209 case 'q' : arg_len = 8; break;
210 default : abort();
211 }
212
213 /* branches have no mode byte */
214 if (d[0] == 'b')
215 {
216 unsigned char *p = p0;
217
218 if (arg_len == 1)
219 (*info->print_address_func) (addr + 1 + NEXTBYTE (p), info);
220 else
221 (*info->print_address_func) (addr + 2 + NEXTWORD (p), info);
222
223 return p - p0;
224 }
225
226 return print_insn_mode (d, arg_len, p0, addr, info);
227}
228
229static int
230print_insn_mode (d, size, p0, addr, info)
231 const char *d;
232 int size;
233 unsigned char *p0;
234 bfd_vma addr; /* PC for this arg to be relative to */
235 disassemble_info *info;
236{
237 unsigned char *p = p0;
238 unsigned char mode, reg;
239
240 /* fetch and interpret mode byte */
241 mode = (unsigned char) NEXTBYTE (p);
242 reg = mode & 0xF;
243 switch (mode & 0xF0)
244 {
245 case 0x00:
246 case 0x10:
247 case 0x20:
248 case 0x30: /* literal mode $number */
249 if (d[1] == 'd' || d[1] == 'f' || d[1] == 'g' || d[1] == 'h')
250 (*info->fprintf_func) (info->stream, "$0x%x [%c-float]", mode, d[1]);
251 else
252 (*info->fprintf_func) (info->stream, "$0x%x", mode);
253 break;
254 case 0x40: /* index: base-addr[Rn] */
255 p += print_insn_mode (d, size, p0 + 1, addr + 1, info);
256 (*info->fprintf_func) (info->stream, "[%s]", reg_names[reg]);
257 break;
258 case 0x50: /* register: Rn */
259 (*info->fprintf_func) (info->stream, "%s", reg_names[reg]);
260 break;
261 case 0x60: /* register deferred: (Rn) */
262 (*info->fprintf_func) (info->stream, "(%s)", reg_names[reg]);
263 break;
264 case 0x70: /* autodecrement: -(Rn) */
265 (*info->fprintf_func) (info->stream, "-(%s)", reg_names[reg]);
266 break;
267 case 0x80: /* autoincrement: (Rn)+ */
268 if (reg == 0xF)
269 { /* immediate? */
270 int i;
271
272 FETCH_DATA (info, p + size);
273 (*info->fprintf_func) (info->stream, "$0x");
274 if (d[1] == 'd' || d[1] == 'f' || d[1] == 'g' || d[1] == 'h')
275 {
276 int float_word;
277
278 float_word = p[0] | (p[1] << 8);
279 if ((d[1] == 'd' || d[1] == 'f')
280 && (float_word & 0xff80) == 0x8000)
281 {
282 (*info->fprintf_func) (info->stream, "[invalid %c-float]",
283 d[1]);
284 }
285 else
286 {
287 for (i = 0; i < size; i++)
288 (*info->fprintf_func) (info->stream, "%02x",
289 p[size - i - 1]);
290 (*info->fprintf_func) (info->stream, " [%c-float]", d[1]);
291 }
292 }
293 else
294 {
295 for (i = 0; i < size; i++)
296 (*info->fprintf_func) (info->stream, "%02x", p[size - i - 1]);
297 }
298 p += size;
299 }
300 else
301 (*info->fprintf_func) (info->stream, "(%s)+", reg_names[reg]);
302 break;
303 case 0x90: /* autoincrement deferred: @(Rn)+ */
304 if (reg == 0xF)
305 (*info->fprintf_func) (info->stream, "*0x%x", NEXTLONG (p));
306 else
307 (*info->fprintf_func) (info->stream, "@(%s)+", reg_names[reg]);
308 break;
309 case 0xB0: /* displacement byte deferred: *displ(Rn) */
310 (*info->fprintf_func) (info->stream, "*");
311 case 0xA0: /* displacement byte: displ(Rn) */
312 if (reg == 0xF)
313 (*info->print_address_func) (addr + 2 + NEXTBYTE (p), info);
314 else
315 (*info->fprintf_func) (info->stream, "0x%x(%s)", NEXTBYTE (p),
316 reg_names[reg]);
317 break;
318 case 0xD0: /* displacement word deferred: *displ(Rn) */
319 (*info->fprintf_func) (info->stream, "*");
320 case 0xC0: /* displacement word: displ(Rn) */
321 if (reg == 0xF)
322 (*info->print_address_func) (addr + 3 + NEXTWORD (p), info);
323 else
324 (*info->fprintf_func) (info->stream, "0x%x(%s)", NEXTWORD (p),
325 reg_names[reg]);
326 break;
327 case 0xF0: /* displacement long deferred: *displ(Rn) */
328 (*info->fprintf_func) (info->stream, "*");
329 case 0xE0: /* displacement long: displ(Rn) */
330 if (reg == 0xF)
331 (*info->print_address_func) (addr + 5 + NEXTLONG (p), info);
332 else
333 (*info->fprintf_func) (info->stream, "0x%x(%s)", NEXTLONG (p),
334 reg_names[reg]);
335 break;
336 }
337
338 return p - p0;
339}
Note: See TracBrowser for help on using the repository browser.