|
|
1.1 ! root 1: /* Print 32000 instructions for GDB, the GNU debugger. ! 2: Copyright (C) 1986,1988 Free Software Foundation, Inc. ! 3: ! 4: GDB is distributed in the hope that it will be useful, but WITHOUT ANY ! 5: WARRANTY. No author or distributor accepts responsibility to anyone ! 6: for the consequences of using it or for whether it serves any ! 7: particular purpose or works at all, unless he says so in writing. ! 8: Refer to the GDB General Public License for full details. ! 9: ! 10: Everyone is granted permission to copy, modify and redistribute GDB, ! 11: but only under the conditions described in the GDB General Public ! 12: License. A copy of this license is supposed to have been given to you ! 13: along with GDB so you can know your rights and responsibilities. It ! 14: should be in a file named COPYING. Among other things, the copyright ! 15: notice and this notice must be preserved on all copies. ! 16: ! 17: In other words, go ahead and share GDB, but don't try to stop ! 18: anyone else from sharing it farther. Help stamp out software hoarding! ! 19: */ ! 20: ! 21: #include <stdio.h> ! 22: ! 23: #include "defs.h" ! 24: #include "param.h" ! 25: #include "symtab.h" ! 26: #include "opcode.h" ! 27: ! 28: /* 32000 instructions are never longer than this. */ ! 29: #define MAXLEN 62 ! 30: ! 31: /* Number of elements in the opcode table. */ ! 32: #define NOPCODES (sizeof notstrs / sizeof notstrs[0]) ! 33: ! 34: extern char *reg_names[]; ! 35: ! 36: #define NEXT_IS_ADDR '|' ! 37: ! 38: /* ! 39: * extract "count" bits starting "offset" bits ! 40: * into buffer ! 41: */ ! 42: ! 43: int ! 44: bit_extract (buffer, offset, count) ! 45: char *buffer; ! 46: int offset; ! 47: int count; ! 48: { ! 49: int result; ! 50: int mask; ! 51: int bit; ! 52: ! 53: buffer += offset >> 3; ! 54: offset &= 7; ! 55: bit = 1; ! 56: result = 0; ! 57: while (count--) ! 58: { ! 59: if ((*buffer & (1 << offset))) ! 60: result |= bit; ! 61: if (++offset == 8) ! 62: { ! 63: offset = 0; ! 64: buffer++; ! 65: } ! 66: bit <<= 1; ! 67: } ! 68: return result; ! 69: } ! 70: ! 71: float ! 72: fbit_extract (buffer, offset, count) ! 73: { ! 74: union { ! 75: int ival; ! 76: float fval; ! 77: } foo; ! 78: ! 79: foo.ival = bit_extract (buffer, offset, 32); ! 80: return foo.fval; ! 81: } ! 82: ! 83: double ! 84: dbit_extract (buffer, offset, count) ! 85: { ! 86: union { ! 87: struct {int low, high; } ival; ! 88: double dval; ! 89: } foo; ! 90: ! 91: foo.ival.low = bit_extract (buffer, offset, 32); ! 92: foo.ival.high = bit_extract (buffer, offset+32, 32); ! 93: return foo.dval; ! 94: } ! 95: ! 96: sign_extend (value, bits) ! 97: { ! 98: value = value & ((1 << bits) - 1); ! 99: return (value & (1 << (bits-1)) ! 100: ? value | (~((1 << bits) - 1)) ! 101: : value); ! 102: } ! 103: ! 104: flip_bytes (ptr, count) ! 105: char *ptr; ! 106: int count; ! 107: { ! 108: char tmp; ! 109: ! 110: while (count > 0) ! 111: { ! 112: tmp = *ptr; ! 113: ptr[0] = ptr[count-1]; ! 114: ptr[count-1] = tmp; ! 115: ptr++; ! 116: count -= 2; ! 117: } ! 118: } ! 119: ! 120: ! 121: /* Print the 32000 instruction at address MEMADDR in debugged memory, ! 122: on STREAM. Returns length of the instruction, in bytes. */ ! 123: ! 124: int ! 125: print_insn (memaddr, stream) ! 126: CORE_ADDR memaddr; ! 127: FILE *stream; ! 128: { ! 129: unsigned char buffer[MAXLEN]; ! 130: register int i; ! 131: register unsigned char *p; ! 132: register char *d; ! 133: unsigned short first_word; ! 134: int gen, disp; ! 135: int ioffset; /* bits into instruction */ ! 136: int aoffset; /* bits into arguments */ ! 137: char arg_bufs[MAX_ARGS+1][ARG_LEN]; ! 138: int argnum; ! 139: int maxarg; ! 140: ! 141: read_memory (memaddr, buffer, MAXLEN); ! 142: ! 143: first_word = *(unsigned short *) buffer; ! 144: for (i = 0; i < NOPCODES; i++) ! 145: if ((first_word & ((1 << notstrs[i].detail.obits) - 1)) ! 146: == notstrs[i].detail.code) ! 147: break; ! 148: ! 149: /* Handle undefined instructions. */ ! 150: if (i == NOPCODES) ! 151: { ! 152: fprintf (stream, "0%o", buffer[0]); ! 153: return 1; ! 154: } ! 155: ! 156: fprintf (stream, "%s", notstrs[i].name); ! 157: ! 158: ioffset = notstrs[i].detail.ibits; ! 159: aoffset = notstrs[i].detail.ibits; ! 160: d = notstrs[i].detail.args; ! 161: ! 162: if (*d) ! 163: { ! 164: fputc ('\t', stream); ! 165: ! 166: maxarg = 0; ! 167: while (*d) ! 168: { ! 169: argnum = *d - '1'; ! 170: d++; ! 171: if (argnum > maxarg && argnum < MAX_ARGS) ! 172: maxarg = argnum; ! 173: ioffset = print_insn_arg (*d, ioffset, &aoffset, buffer, ! 174: memaddr, arg_bufs[argnum]); ! 175: d++; ! 176: } ! 177: for (argnum = 0; argnum <= maxarg; argnum++) ! 178: { ! 179: CORE_ADDR addr; ! 180: char *ch, *index (); ! 181: for (ch = arg_bufs[argnum]; *ch;) ! 182: { ! 183: if (*ch == NEXT_IS_ADDR) ! 184: { ! 185: ++ch; ! 186: addr = atoi (ch); ! 187: print_address (addr, stream); ! 188: while (*ch && *ch != NEXT_IS_ADDR) ! 189: ++ch; ! 190: if (*ch) ! 191: ++ch; ! 192: } ! 193: else ! 194: putc (*ch++, stream); ! 195: } ! 196: if (argnum < maxarg) ! 197: fprintf (stream, ", "); ! 198: } ! 199: } ! 200: return aoffset / 8; ! 201: } ! 202: ! 203: print_insn_arg (d, ioffset, aoffsetp, buffer, addr, result) ! 204: char d; ! 205: int ioffset, *aoffsetp; ! 206: char *buffer; ! 207: CORE_ADDR addr; ! 208: char *result; ! 209: { ! 210: int addr_mode; ! 211: float Fvalue; ! 212: double Lvalue; ! 213: int Ivalue; ! 214: int disp1, disp2; ! 215: int index; ! 216: ! 217: switch (d) ! 218: { ! 219: case 'F': ! 220: case 'L': ! 221: case 'B': ! 222: case 'W': ! 223: case 'D': ! 224: case 'A': ! 225: addr_mode = bit_extract (buffer, ioffset-5, 5); ! 226: ioffset -= 5; ! 227: switch (addr_mode) ! 228: { ! 229: case 0x0: case 0x1: case 0x2: case 0x3: ! 230: case 0x4: case 0x5: case 0x6: case 0x7: ! 231: switch (d) ! 232: { ! 233: case 'F': ! 234: case 'L': ! 235: sprintf (result, "f%d", addr_mode); ! 236: break; ! 237: default: ! 238: sprintf (result, "r%d", addr_mode); ! 239: } ! 240: break; ! 241: case 0x8: case 0x9: case 0xa: case 0xb: ! 242: case 0xc: case 0xd: case 0xe: case 0xf: ! 243: disp1 = get_displacement (buffer, aoffsetp); ! 244: sprintf (result, "%d(r%d)", disp1, addr_mode & 7); ! 245: break; ! 246: case 0x10: ! 247: case 0x11: ! 248: case 0x12: ! 249: disp1 = get_displacement (buffer, aoffsetp); ! 250: disp2 = get_displacement (buffer, aoffsetp); ! 251: sprintf (result, "%d(%d(%s))", disp2, disp1, ! 252: addr_mode==0x10?"fp":addr_mode==0x11?"sp":"sb"); ! 253: break; ! 254: case 0x13: ! 255: sprintf (result, "reserved"); ! 256: break; ! 257: case 0x14: ! 258: switch (d) ! 259: { ! 260: case 'B': ! 261: Ivalue = bit_extract (buffer, *aoffsetp, 8); ! 262: Ivalue = sign_extend (Ivalue, 8); ! 263: *aoffsetp += 8; ! 264: sprintf (result, "$%d", Ivalue); ! 265: break; ! 266: case 'W': ! 267: Ivalue = bit_extract (buffer, *aoffsetp, 16); ! 268: flip_bytes (&Ivalue, 2); ! 269: *aoffsetp += 16; ! 270: Ivalue = sign_extend (Ivalue, 16); ! 271: sprintf (result, "$%d", Ivalue); ! 272: break; ! 273: case 'D': ! 274: Ivalue = bit_extract (buffer, *aoffsetp, 32); ! 275: flip_bytes (&Ivalue, 4); ! 276: *aoffsetp += 32; ! 277: sprintf (result, "$%d", Ivalue); ! 278: break; ! 279: case 'A': ! 280: Ivalue = bit_extract (buffer, *aoffsetp, 32); ! 281: flip_bytes (&Ivalue, 4); ! 282: *aoffsetp += 32; ! 283: sprintf (result, "$|%d|", Ivalue); ! 284: break; ! 285: case 'F': ! 286: Fvalue = fbit_extract (buffer, *aoffsetp, 32); ! 287: flip_bytes (&Fvalue, 4); ! 288: *aoffsetp += 32; ! 289: sprintf (result, "$%g", Fvalue); ! 290: break; ! 291: case 'L': ! 292: Lvalue = dbit_extract (buffer, *aoffsetp, 64); ! 293: flip_bytes (&Lvalue, 8); ! 294: *aoffsetp += 64; ! 295: sprintf (result, "$%g", Lvalue); ! 296: break; ! 297: } ! 298: break; ! 299: case 0x15: ! 300: disp1 = get_displacement (buffer, aoffsetp); ! 301: sprintf (result, "@|%d|", disp1); ! 302: break; ! 303: case 0x16: ! 304: disp1 = get_displacement (buffer, aoffsetp); ! 305: disp2 = get_displacement (buffer, aoffsetp); ! 306: sprintf (result, "EXT(%d) + %d", disp1, disp2); ! 307: break; ! 308: case 0x17: ! 309: sprintf (result, "tos"); ! 310: break; ! 311: case 0x18: ! 312: disp1 = get_displacement (buffer, aoffsetp); ! 313: sprintf (result, "%d(fp)", disp1); ! 314: break; ! 315: case 0x19: ! 316: disp1 = get_displacement (buffer, aoffsetp); ! 317: sprintf (result, "%d(sp)", disp1); ! 318: break; ! 319: case 0x1a: ! 320: disp1 = get_displacement (buffer, aoffsetp); ! 321: sprintf (result, "%d(sb)", disp1); ! 322: break; ! 323: case 0x1b: ! 324: disp1 = get_displacement (buffer, aoffsetp); ! 325: sprintf (result, "|%d|", addr + disp1); ! 326: break; ! 327: case 0x1c: ! 328: case 0x1d: ! 329: case 0x1e: ! 330: case 0x1f: ! 331: index = bit_extract (buffer, *aoffsetp, 8); ! 332: *aoffsetp += 8; ! 333: print_insn_arg (d, *aoffsetp, aoffsetp, buffer, addr, ! 334: result); ! 335: { ! 336: static char *ind[] = {"b", "w", "d", "q"}; ! 337: char *off; ! 338: ! 339: off = result + strlen (result); ! 340: sprintf (off, "[r%d:%s]", index & 7, ! 341: ind[addr_mode & 3]); ! 342: } ! 343: break; ! 344: } ! 345: break; ! 346: case 'q': ! 347: Ivalue = bit_extract (buffer, ioffset-4, 4); ! 348: Ivalue = sign_extend (Ivalue, 4); ! 349: sprintf (result, "%d", Ivalue); ! 350: ioffset -= 4; ! 351: break; ! 352: case 'r': ! 353: Ivalue = bit_extract (buffer, ioffset-3, 3); ! 354: sprintf (result, "r%d", Ivalue&7); ! 355: ioffset -= 3; ! 356: break; ! 357: case 'd': ! 358: sprintf (result, "%d", get_displacement (buffer, aoffsetp)); ! 359: break; ! 360: case 'p': ! 361: sprintf (result, "%c%d%c", NEXT_IS_ADDR, ! 362: addr + get_displacement (buffer, aoffsetp), ! 363: NEXT_IS_ADDR); ! 364: break; ! 365: case 'i': ! 366: Ivalue = bit_extract (buffer, *aoffsetp, 8); ! 367: *aoffsetp += 8; ! 368: sprintf (result, "0x%x", Ivalue); ! 369: break; ! 370: } ! 371: return ioffset; ! 372: } ! 373: ! 374: get_displacement (buffer, aoffsetp) ! 375: char *buffer; ! 376: int *aoffsetp; ! 377: { ! 378: int Ivalue; ! 379: ! 380: Ivalue = bit_extract (buffer, *aoffsetp, 8); ! 381: switch (Ivalue & 0xc0) ! 382: { ! 383: case 0x00: ! 384: case 0x40: ! 385: Ivalue = sign_extend (Ivalue, 7); ! 386: *aoffsetp += 8; ! 387: break; ! 388: case 0x80: ! 389: Ivalue = bit_extract (buffer, *aoffsetp, 16); ! 390: flip_bytes (&Ivalue, 2); ! 391: Ivalue = sign_extend (Ivalue, 14); ! 392: *aoffsetp += 16; ! 393: break; ! 394: case 0xc0: ! 395: Ivalue = bit_extract (buffer, *aoffsetp, 32); ! 396: flip_bytes (&Ivalue, 4); ! 397: Ivalue = sign_extend (Ivalue, 30); ! 398: *aoffsetp += 32; ! 399: break; ! 400: } ! 401: return Ivalue; ! 402: } ! 403: ! 404: /* Return the number of locals in the current frame given a pc ! 405: pointing to the enter instruction. This is used in the macro ! 406: FRAME_FIND_SAVED_REGS. */ ! 407: ! 408: ns32k_localcount (enter_pc) ! 409: CORE_ADDR enter_pc; ! 410: { ! 411: unsigned char localtype; ! 412: int localcount; ! 413: ! 414: localtype = read_memory_integer (enter_pc+2, 1); ! 415: if ((localtype & 0x80) == 0) ! 416: localcount = localtype; ! 417: else if ((localtype & 0xc0) == 0x80) ! 418: localcount = (((localtype & 0x3f) << 8) ! 419: | (read_memory_integer (enter_pc+3, 1) & 0xff)); ! 420: else ! 421: localcount = (((localtype & 0x3f) << 24) ! 422: | ((read_memory_integer (enter_pc+3, 1) & 0xff) << 16) ! 423: | ((read_memory_integer (enter_pc+4, 1) & 0xff) << 8 ) ! 424: | (read_memory_integer (enter_pc+5, 1) & 0xff)); ! 425: return localcount; ! 426: } ! 427: ! 428: /* ! 429: * Get the address of the enter opcode for the function ! 430: * containing PC, if there is an enter for the function, ! 431: * and if the pc is between the enter and exit. ! 432: * Returns positive address if pc is between enter/exit, ! 433: * 1 if pc before enter or after exit, 0 otherwise. ! 434: */ ! 435: ! 436: CORE_ADDR ! 437: ns32k_get_enter_addr (pc) ! 438: CORE_ADDR pc; ! 439: { ! 440: CORE_ADDR enter_addr; ! 441: unsigned char op; ! 442: ! 443: if (ABOUT_TO_RETURN (pc)) ! 444: return 1; /* after exit */ ! 445: ! 446: enter_addr = get_pc_function_start (pc); ! 447: ! 448: if (pc == enter_addr) ! 449: return 1; /* before enter */ ! 450: ! 451: op = read_memory_integer (enter_addr, 1); ! 452: ! 453: if (op != 0x82) ! 454: return 0; /* function has no enter/exit */ ! 455: ! 456: return enter_addr; /* pc is between enter and exit */ ! 457: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.