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, 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 from disassembler info INFO. 34 Returns length of the instruction, in bytes. */ 35 36 static int 37 vax_print_insn (memaddr, info) 38 CORE_ADDR memaddr; 39 disassemble_info *info; 40 { 41 unsigned char buffer[MAXLEN]; 42 register int i; 43 register unsigned char *p; 44 register char *d; 45 46 int status = (*info->read_memory_func) (memaddr, buffer, MAXLEN, info); 47 if (status != 0) 48 { 49 (*info->memory_error_func) (status, memaddr, info); 50 return -1; 51 } 52 53 for (i = 0; i < NOPCODES; i++) 54 if (votstrs[i].detail.code == buffer[0] 55 || votstrs[i].detail.code == *(unsigned short *)buffer) 56 break; 57 58 /* Handle undefined instructions. */ 59 if (i == NOPCODES) 60 { 61 (*info->fprintf_func) (info->stream, "0%o", buffer[0]); 62 return 1; 63 } 64 65 (*info->fprintf_func) (info->stream, "%s", votstrs[i].name); 66 67 /* Point at first byte of argument data, 68 and at descriptor for first argument. */ 69 p = buffer + 1 + (votstrs[i].detail.code >= 0x100); 70 d = (char *)votstrs[i].detail.args; 71 72 if (*d) 73 (*info->fprintf_func) (info->stream, " "); 74 75 while (*d) 76 { 77 p = print_insn_arg (d, p, memaddr + (p - buffer), info); 78 d += 2; 79 if (*d) 80 (*info->fprintf_func) (info->stream, ","); 81 } 82 return p - buffer; 83 } 84 85 static unsigned char * 86 print_insn_arg (d, p, addr, info) 87 char *d; 88 register char *p; 89 CORE_ADDR addr; 90 disassemble_info *info; 91 { 92 register int regnum = *p & 0xf; 93 float floatlitbuf; 94 95 if (*d == 'b') 96 { 97 if (d[1] == 'b') 98 (*info->fprintf_func) (info->stream, "0x%x", addr + *p++ + 1); 99 else 100 { 101 (*info->fprintf_func) (info->stream, "0x%x", addr + *(short *)p + 2); 102 p += 2; 103 } 104 } 105 else 106 switch ((*p++ >> 4) & 0xf) 107 { 108 case 0: 109 case 1: 110 case 2: 111 case 3: /* Literal mode */ 112 if (d[1] == 'd' || d[1] == 'f' || d[1] == 'g' || d[1] == 'h') 113 { 114 *(int *)&floatlitbuf = 0x4000 + ((p[-1] & 0x3f) << 4); 115 (*info->fprintf_func) (info->stream, "$%f", floatlitbuf); 116 } 117 else 118 (*info->fprintf_func) (info->stream, "$%d", p[-1] & 0x3f); 119 break; 120 121 case 4: /* Indexed */ 122 p = (char *) print_insn_arg (d, p, addr + 1, info); 123 (*info->fprintf_func) (info->stream, "[%s]", reg_names[regnum]); 124 break; 125 126 case 5: /* Register */ 127 (*info->fprintf_func) (info->stream, reg_names[regnum]); 128 break; 129 130 case 7: /* Autodecrement */ 131 (*info->fprintf_func) (info->stream, "-"); 132 case 6: /* Register deferred */ 133 (*info->fprintf_func) (info->stream, "(%s)", reg_names[regnum]); 134 break; 135 136 case 9: /* Autoincrement deferred */ 137 (*info->fprintf_func) (info->stream, "@"); 138 if (regnum == PC_REGNUM) 139 { 140 (*info->fprintf_func) (info->stream, "#"); 141 info->target = *(long *)p; 142 (*info->print_address_func) (info->target, info); 143 p += 4; 144 break; 145 } 146 case 8: /* Autoincrement */ 147 if (regnum == PC_REGNUM) 148 { 149 (*info->fprintf_func) (info->stream, "#"); 150 switch (d[1]) 151 { 152 case 'b': 153 (*info->fprintf_func) (info->stream, "%d", *p++); 154 break; 155 156 case 'w': 157 (*info->fprintf_func) (info->stream, "%d", *(short *)p); 158 p += 2; 159 break; 160 161 case 'l': 162 (*info->fprintf_func) (info->stream, "%d", *(long *)p); 163 p += 4; 164 break; 165 166 case 'q': 167 (*info->fprintf_func) (info->stream, "0x%x%08x", 168 ((long *)p)[1], ((long *)p)[0]); 169 p += 8; 170 break; 171 172 case 'o': 173 (*info->fprintf_func) (info->stream, "0x%x%08x%08x%08x", 174 ((long *)p)[3], ((long *)p)[2], 175 ((long *)p)[1], ((long *)p)[0]); 176 p += 16; 177 break; 178 179 case 'f': 180 if (INVALID_FLOAT (p, 4)) 181 (*info->fprintf_func) (info->stream, 182 "<<invalid float 0x%x>>", 183 *(int *) p); 184 else 185 (*info->fprintf_func) (info->stream, "%f", *(float *) p); 186 p += 4; 187 break; 188 189 case 'd': 190 if (INVALID_FLOAT (p, 8)) 191 (*info->fprintf_func) (info->stream, 192 "<<invalid float 0x%x%08x>>", 193 ((long *)p)[1], ((long *)p)[0]); 194 else 195 (*info->fprintf_func) (info->stream, "%f", *(double *) p); 196 p += 8; 197 break; 198 199 case 'g': 200 (*info->fprintf_func) (info->stream, "g-float"); 201 p += 8; 202 break; 203 204 case 'h': 205 (*info->fprintf_func) (info->stream, "h-float"); 206 p += 16; 207 break; 208 209 } 210 } 211 else 212 (*info->fprintf_func) (info->stream, "(%s)+", reg_names[regnum]); 213 break; 214 215 case 11: /* Byte displacement deferred */ 216 (*info->fprintf_func) (info->stream, "@"); 217 case 10: /* Byte displacement */ 218 if (regnum == PC_REGNUM) 219 { 220 info->target = addr + *p + 2; 221 (*info->print_address_func) (info->target, info); 222 } 223 else 224 (*info->fprintf_func) (info->stream, "%d(%s)", *p, reg_names[regnum]); 225 p += 1; 226 break; 227 228 case 13: /* Word displacement deferred */ 229 (*info->fprintf_func) (info->stream, "@"); 230 case 12: /* Word displacement */ 231 if (regnum == PC_REGNUM) 232 { 233 info->target = addr + *(short *)p + 3; 234 (*info->print_address_func) (info->target, info); 235 } 236 else 237 (*info->fprintf_func) (info->stream, "%d(%s)", 238 *(short *)p, reg_names[regnum]); 239 p += 2; 240 break; 241 242 case 15: /* Long displacement deferred */ 243 (*info->fprintf_func) (info->stream, "@"); 244 case 14: /* Long displacement */ 245 if (regnum == PC_REGNUM) 246 { 247 info->target = addr + *(long *)p + 5; 248 (*info->print_address_func) (info->target, info); 249 } 250 else 251 (*info->fprintf_func) (info->stream, "%d(%s)", 252 *(long *)p, reg_names[regnum]); 253 p += 4; 254 } 255 256 return (unsigned char *) p; 257 } 258 259 void 260 _initialize_vax_tdep () 261 { 262 tm_print_insn = vax_print_insn; 263 } 264