00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "sysdep.h"
00025 #include "opcode/vax.h"
00026 #include "dis-asm.h"
00027
00028
00029 static int fetch_data PARAMS ((struct disassemble_info *, bfd_byte *));
00030 static int print_insn_arg
00031 PARAMS ((const char *, unsigned char *, bfd_vma, disassemble_info *));
00032 static int print_insn_mode
00033 PARAMS ((const char *, int, unsigned char *, bfd_vma, disassemble_info *));
00034
00035
00036 static char *reg_names[] =
00037 {
00038 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
00039 "r8", "r9", "r10", "r11", "ap", "fp", "sp", "pc"
00040 };
00041
00042
00043 static char *entry_mask_bit[] =
00044 {
00045
00046
00047 "~r0~", "~r1~",
00048
00049 "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11",
00050
00051
00052 "~ap~", "~fp~",
00053
00054 "IntOvfl", "DecOvfl",
00055 };
00056
00057
00058 #if __STDC__ == 1
00059 #define COERCE_SIGNED_CHAR(ch) ((signed char)(ch))
00060 #else
00061 #define COERCE_SIGNED_CHAR(ch) ((int)(((ch) ^ 0x80) & 0xFF) - 128)
00062 #endif
00063
00064
00065 #define NEXTBYTE(p) \
00066 (p += 1, FETCH_DATA (info, p), \
00067 COERCE_SIGNED_CHAR(p[-1]))
00068
00069
00070 #define COERCE16(x) ((int) (((x) ^ 0x8000) - 0x8000))
00071 #define NEXTWORD(p) \
00072 (p += 2, FETCH_DATA (info, p), \
00073 COERCE16 ((p[-1] << 8) + p[-2]))
00074
00075
00076 #define COERCE32(x) ((int) (((x) ^ 0x80000000) - 0x80000000))
00077 #define NEXTLONG(p) \
00078 (p += 4, FETCH_DATA (info, p), \
00079 (COERCE32 ((((((p[-1] << 8) + p[-2]) << 8) + p[-3]) << 8) + p[-4])))
00080
00081
00082 #define MAXLEN 25
00083
00084 #include <setjmp.h>
00085
00086 struct private
00087 {
00088
00089 bfd_byte *max_fetched;
00090 bfd_byte the_buffer[MAXLEN];
00091 bfd_vma insn_start;
00092 jmp_buf bailout;
00093 };
00094
00095
00096
00097
00098 #define FETCH_DATA(info, addr) \
00099 ((addr) <= ((struct private *)(info->private_data))->max_fetched \
00100 ? 1 : fetch_data ((info), (addr)))
00101
00102 static int
00103 fetch_data (info, addr)
00104 struct disassemble_info *info;
00105 bfd_byte *addr;
00106 {
00107 int status;
00108 struct private *priv = (struct private *) info->private_data;
00109 bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer);
00110
00111 status = (*info->read_memory_func) (start,
00112 priv->max_fetched,
00113 addr - priv->max_fetched,
00114 info);
00115 if (status != 0)
00116 {
00117 (*info->memory_error_func) (status, start, info);
00118 longjmp (priv->bailout, 1);
00119 }
00120 else
00121 priv->max_fetched = addr;
00122
00123 return 1;
00124 }
00125
00126
00127
00128
00129 int
00130 print_insn_vax (memaddr, info)
00131 bfd_vma memaddr;
00132 disassemble_info *info;
00133 {
00134 const struct vot *votp;
00135 const char *argp;
00136 unsigned char *arg;
00137 struct private priv;
00138 bfd_byte *buffer = priv.the_buffer;
00139
00140 info->private_data = (PTR) &priv;
00141 priv.max_fetched = priv.the_buffer;
00142 priv.insn_start = memaddr;
00143
00144 if (setjmp (priv.bailout) != 0)
00145 {
00146
00147 return -1;
00148 }
00149
00150 argp = NULL;
00151
00152
00153 if (info->buffer_length - (memaddr - info->buffer_vma) > 1)
00154 {
00155 FETCH_DATA (info, buffer + 2);
00156 }
00157 else
00158 {
00159 FETCH_DATA (info, buffer + 1);
00160 buffer[1] = 0;
00161 }
00162
00163
00164 if (info->symbols
00165 && info->symbols[0]
00166 && (info->symbols[0]->flags & BSF_FUNCTION)
00167 && memaddr == bfd_asymbol_value (info->symbols[0]))
00168 {
00169 int i = 0;
00170 int register_mask = buffer[1] << 8 | buffer[0];
00171
00172 (*info->fprintf_func) (info->stream, "Entry mask 0x%04x = <",
00173 register_mask);
00174
00175 for (i = 15; i >= 0; i--)
00176 if (register_mask & (1 << i))
00177 (*info->fprintf_func) (info->stream, " %s", entry_mask_bit[i]);
00178
00179 (*info->fprintf_func) (info->stream, " >");
00180
00181 return 2;
00182 }
00183
00184 for (votp = &votstrs[0]; votp->name[0]; votp++)
00185 {
00186 register vax_opcodeT opcode = votp->detail.code;
00187
00188
00189 if ((bfd_byte) opcode == buffer[0]
00190 && (opcode >> 8 == 0 || opcode >> 8 == buffer[1]))
00191 {
00192 argp = votp->detail.args;
00193 break;
00194 }
00195 }
00196 if (argp == NULL)
00197 {
00198
00199 (*info->fprintf_func) (info->stream, ".word 0x%x",
00200 (buffer[0] << 8) + buffer[1]);
00201 return 2;
00202 }
00203
00204
00205
00206 arg = buffer + ((votp->detail.code >> 8) ? 2 : 1);
00207
00208
00209 FETCH_DATA (info, arg);
00210
00211 (*info->fprintf_func) (info->stream, "%s", votp->name);
00212 if (*argp)
00213 (*info->fprintf_func) (info->stream, " ");
00214
00215 while (*argp)
00216 {
00217 arg += print_insn_arg (argp, arg, memaddr + arg - buffer, info);
00218 argp += 2;
00219 if (*argp)
00220 (*info->fprintf_func) (info->stream, ",");
00221 }
00222
00223 return arg - buffer;
00224 }
00225
00226
00227
00228
00229
00230 static int
00231 print_insn_arg (d, p0, addr, info)
00232 const char *d;
00233 unsigned char *p0;
00234 bfd_vma addr;
00235 disassemble_info *info;
00236 {
00237 int arg_len;
00238
00239
00240 switch (d[1])
00241 {
00242 case 'b' : arg_len = 1; break;
00243 case 'd' : arg_len = 8; break;
00244 case 'f' : arg_len = 4; break;
00245 case 'g' : arg_len = 8; break;
00246 case 'h' : arg_len = 16; break;
00247 case 'l' : arg_len = 4; break;
00248 case 'o' : arg_len = 16; break;
00249 case 'w' : arg_len = 2; break;
00250 case 'q' : arg_len = 8; break;
00251 default : abort();
00252 }
00253
00254
00255 if (d[0] == 'b')
00256 {
00257 unsigned char *p = p0;
00258
00259 if (arg_len == 1)
00260 (*info->print_address_func) (addr + 1 + NEXTBYTE (p), info);
00261 else
00262 (*info->print_address_func) (addr + 2 + NEXTWORD (p), info);
00263
00264 return p - p0;
00265 }
00266
00267 return print_insn_mode (d, arg_len, p0, addr, info);
00268 }
00269
00270 static int
00271 print_insn_mode (d, size, p0, addr, info)
00272 const char *d;
00273 int size;
00274 unsigned char *p0;
00275 bfd_vma addr;
00276 disassemble_info *info;
00277 {
00278 unsigned char *p = p0;
00279 unsigned char mode, reg;
00280
00281
00282 mode = (unsigned char) NEXTBYTE (p);
00283 reg = mode & 0xF;
00284 switch (mode & 0xF0)
00285 {
00286 case 0x00:
00287 case 0x10:
00288 case 0x20:
00289 case 0x30:
00290 if (d[1] == 'd' || d[1] == 'f' || d[1] == 'g' || d[1] == 'h')
00291 (*info->fprintf_func) (info->stream, "$0x%x [%c-float]", mode, d[1]);
00292 else
00293 (*info->fprintf_func) (info->stream, "$0x%x", mode);
00294 break;
00295 case 0x40:
00296 p += print_insn_mode (d, size, p0 + 1, addr + 1, info);
00297 (*info->fprintf_func) (info->stream, "[%s]", reg_names[reg]);
00298 break;
00299 case 0x50:
00300 (*info->fprintf_func) (info->stream, "%s", reg_names[reg]);
00301 break;
00302 case 0x60:
00303 (*info->fprintf_func) (info->stream, "(%s)", reg_names[reg]);
00304 break;
00305 case 0x70:
00306 (*info->fprintf_func) (info->stream, "-(%s)", reg_names[reg]);
00307 break;
00308 case 0x80:
00309 if (reg == 0xF)
00310 {
00311 int i;
00312
00313 FETCH_DATA (info, p + size);
00314 (*info->fprintf_func) (info->stream, "$0x");
00315 if (d[1] == 'd' || d[1] == 'f' || d[1] == 'g' || d[1] == 'h')
00316 {
00317 int float_word;
00318
00319 float_word = p[0] | (p[1] << 8);
00320 if ((d[1] == 'd' || d[1] == 'f')
00321 && (float_word & 0xff80) == 0x8000)
00322 {
00323 (*info->fprintf_func) (info->stream, "[invalid %c-float]",
00324 d[1]);
00325 }
00326 else
00327 {
00328 for (i = 0; i < size; i++)
00329 (*info->fprintf_func) (info->stream, "%02x",
00330 p[size - i - 1]);
00331 (*info->fprintf_func) (info->stream, " [%c-float]", d[1]);
00332 }
00333 }
00334 else
00335 {
00336 for (i = 0; i < size; i++)
00337 (*info->fprintf_func) (info->stream, "%02x", p[size - i - 1]);
00338 }
00339 p += size;
00340 }
00341 else
00342 (*info->fprintf_func) (info->stream, "(%s)+", reg_names[reg]);
00343 break;
00344 case 0x90:
00345 if (reg == 0xF)
00346 (*info->fprintf_func) (info->stream, "*0x%x", NEXTLONG (p));
00347 else
00348 (*info->fprintf_func) (info->stream, "@(%s)+", reg_names[reg]);
00349 break;
00350 case 0xB0:
00351 (*info->fprintf_func) (info->stream, "*");
00352 case 0xA0:
00353 if (reg == 0xF)
00354 (*info->print_address_func) (addr + 2 + NEXTBYTE (p), info);
00355 else
00356 (*info->fprintf_func) (info->stream, "0x%x(%s)", NEXTBYTE (p),
00357 reg_names[reg]);
00358 break;
00359 case 0xD0:
00360 (*info->fprintf_func) (info->stream, "*");
00361 case 0xC0:
00362 if (reg == 0xF)
00363 (*info->print_address_func) (addr + 3 + NEXTWORD (p), info);
00364 else
00365 (*info->fprintf_func) (info->stream, "0x%x(%s)", NEXTWORD (p),
00366 reg_names[reg]);
00367 break;
00368 case 0xF0:
00369 (*info->fprintf_func) (info->stream, "*");
00370 case 0xE0:
00371 if (reg == 0xF)
00372 (*info->print_address_func) (addr + 5 + NEXTLONG (p), info);
00373 else
00374 (*info->fprintf_func) (info->stream, "0x%x(%s)", NEXTLONG (p),
00375 reg_names[reg]);
00376 break;
00377 }
00378
00379 return p - p0;
00380 }