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