19668Slinton /* Copyright (c) 1982 Regents of the University of California */ 29668Slinton 3*18222Slinton static char sccsid[] = "@(#)vax.c 1.13 (Berkeley) 03/01/85"; 49668Slinton 5*18222Slinton static char rcsid[] = "$Header: machine.c,v 1.5 84/12/26 10:40:05 linton Exp $"; 6*18222Slinton 79668Slinton /* 89668Slinton * Target machine dependent stuff. 99668Slinton */ 109668Slinton 119668Slinton #include "defs.h" 129668Slinton #include "machine.h" 139668Slinton #include "process.h" 1416612Ssam #include "runtime.h" 159668Slinton #include "events.h" 169668Slinton #include "main.h" 179668Slinton #include "symbols.h" 189668Slinton #include "source.h" 199668Slinton #include "mappings.h" 209668Slinton #include "object.h" 21*18222Slinton #include "keywords.h" 229693Slinton #include "ops.h" 239668Slinton #include <signal.h> 249668Slinton 259668Slinton #ifndef public 269668Slinton typedef unsigned int Address; 279668Slinton typedef unsigned char Byte; 289668Slinton typedef unsigned int Word; 299668Slinton 309668Slinton #define NREG 16 319668Slinton 329668Slinton #define ARGP 12 339668Slinton #define FRP 13 349668Slinton #define STKP 14 359668Slinton #define PROGCTR 15 369668Slinton 379668Slinton #define BITSPERBYTE 8 389668Slinton #define BITSPERWORD (BITSPERBYTE * sizeof(Word)) 399668Slinton 409668Slinton #define nargspassed(frame) argn(0, frame) 419668Slinton 429668Slinton #include "source.h" 439668Slinton #include "symbols.h" 449668Slinton 459668Slinton Address pc; 469668Slinton Address prtaddr; 479668Slinton 489668Slinton #endif 499668Slinton 509668Slinton private Address printop(); 519668Slinton 529668Slinton /* 539668Slinton * Decode and print the instructions within the given address range. 549668Slinton */ 559668Slinton 569668Slinton public printinst(lowaddr, highaddr) 579668Slinton Address lowaddr; 589668Slinton Address highaddr; 599668Slinton { 609668Slinton register Address addr; 619668Slinton 629668Slinton for (addr = lowaddr; addr <= highaddr; ) { 639668Slinton addr = printop(addr); 649668Slinton } 659668Slinton prtaddr = addr; 669668Slinton } 679668Slinton 689668Slinton /* 699668Slinton * Another approach: print n instructions starting at the given address. 709668Slinton */ 719668Slinton 729668Slinton public printninst(count, addr) 739668Slinton int count; 749668Slinton Address addr; 759668Slinton { 769668Slinton register Integer i; 779668Slinton register Address newaddr; 789668Slinton 799668Slinton if (count <= 0) { 809668Slinton error("non-positive repetition count"); 819668Slinton } else { 829668Slinton newaddr = addr; 839668Slinton for (i = 0; i < count; i++) { 849668Slinton newaddr = printop(newaddr); 859668Slinton } 869668Slinton prtaddr = newaddr; 879668Slinton } 889668Slinton } 899668Slinton 909668Slinton /* 919668Slinton * Hacked version of adb's VAX instruction decoder. 929668Slinton */ 939668Slinton 949668Slinton private Address printop(addr) 959668Slinton Address addr; 969668Slinton { 979668Slinton Optab op; 989668Slinton VaxOpcode ins; 999668Slinton unsigned char mode; 1009668Slinton int argtype, amode, argno, argval; 1019668Slinton String reg; 1029668Slinton Boolean indexf; 1039668Slinton short offset; 1049668Slinton 1059668Slinton argval = 0; 1069668Slinton indexf = false; 1079668Slinton printf("%08x ", addr); 1089668Slinton iread(&ins, addr, sizeof(ins)); 1099668Slinton addr += 1; 1109668Slinton op = optab[ins]; 1119668Slinton printf("%s", op.iname); 1129668Slinton for (argno = 0; argno < op.numargs; argno++) { 1139668Slinton if (indexf == true) { 1149668Slinton indexf = false; 1159668Slinton } else if (argno == 0) { 1169668Slinton printf("\t"); 1179668Slinton } else { 1189668Slinton printf(","); 1199668Slinton } 1209668Slinton argtype = op.argtype[argno]; 1219668Slinton if (is_branch_disp(argtype)) { 1229668Slinton mode = 0xAF + (typelen(argtype) << 5); 1239668Slinton } else { 1249668Slinton iread(&mode, addr, sizeof(mode)); 1259668Slinton addr += 1; 1269668Slinton } 1279668Slinton reg = regname[regnm(mode)]; 1289668Slinton amode = addrmode(mode); 1299668Slinton switch (amode) { 1309668Slinton case LITSHORT: 1319668Slinton case LITUPTO31: 1329668Slinton case LITUPTO47: 1339668Slinton case LITUPTO63: 1349668Slinton if (typelen(argtype) == TYPF || typelen(argtype) ==TYPD) 1359668Slinton printf("$%s", fltimm[mode]); 1369668Slinton else 1379668Slinton printf("$%x", mode); 1389668Slinton argval = mode; 1399668Slinton break; 1409668Slinton 1419668Slinton case INDEX: 1429668Slinton printf("[%s]", reg); 1439668Slinton indexf = true; 1449668Slinton argno--; 1459668Slinton break; 1469668Slinton 1479668Slinton case REG: 1489668Slinton printf("%s", reg); 1499668Slinton break; 1509668Slinton 1519668Slinton case REGDEF: 1529668Slinton printf("(%s)", reg); 1539668Slinton break; 1549668Slinton 1559668Slinton case AUTODEC: 1569668Slinton printf("-(%s)", reg); 1579668Slinton break; 1589668Slinton 1599668Slinton case AUTOINC: 1609668Slinton if (reg != regname[PROGCTR]) { 1619668Slinton printf("(%s)+", reg); 1629668Slinton } else { 1639668Slinton printf("$"); 1649668Slinton switch (typelen(argtype)) { 1659668Slinton case TYPB: 1669668Slinton argval = printdisp(addr, 1, reg, amode); 1679668Slinton addr += 1; 1689668Slinton break; 1699668Slinton 1709668Slinton case TYPW: 1719668Slinton argval = printdisp(addr, 2, reg, amode); 1729668Slinton addr += 2; 1739668Slinton break; 1749668Slinton 1759668Slinton case TYPL: 1769668Slinton argval = printdisp(addr, 4, reg, amode); 1779668Slinton addr += 4; 1789668Slinton break; 1799668Slinton 1809668Slinton case TYPF: 1819668Slinton iread(&argval, addr, sizeof(argval)); 1829668Slinton printf("%06x", argval); 1839668Slinton addr += 4; 1849668Slinton break; 1859668Slinton 1869668Slinton case TYPQ: 1879668Slinton case TYPD: 1889668Slinton iread(&argval, addr, sizeof(argval)); 1899668Slinton printf("%06x", argval); 1909668Slinton iread(&argval, addr+4, sizeof(argval)); 1919668Slinton printf("%06x", argval); 1929668Slinton addr += 8; 1939668Slinton break; 1949668Slinton } 1959668Slinton } 1969668Slinton break; 1979668Slinton 1989668Slinton case AUTOINCDEF: 1999668Slinton if (reg == regname[PROGCTR]) { 2009668Slinton printf("*$"); 2019668Slinton argval = printdisp(addr, 4, reg, amode); 2029668Slinton addr += 4; 2039668Slinton } else { 2049668Slinton printf("*(%s)+", reg); 2059668Slinton } 2069668Slinton break; 2079668Slinton 2089668Slinton case BYTEDISP: 2099668Slinton argval = printdisp(addr, 1, reg, amode); 2109668Slinton addr += 1; 2119668Slinton break; 2129668Slinton 2139668Slinton case BYTEDISPDEF: 2149668Slinton printf("*"); 2159668Slinton argval = printdisp(addr, 1, reg, amode); 2169668Slinton addr += 1; 2179668Slinton break; 2189668Slinton 2199668Slinton case WORDDISP: 2209668Slinton argval = printdisp(addr, 2, reg, amode); 2219668Slinton addr += 2; 2229668Slinton break; 2239668Slinton 2249668Slinton case WORDDISPDEF: 2259668Slinton printf("*"); 2269668Slinton argval = printdisp(addr, 2, reg, amode); 2279668Slinton addr += 2; 2289668Slinton break; 2299668Slinton 2309668Slinton case LONGDISP: 2319668Slinton argval = printdisp(addr, 4, reg, amode); 2329668Slinton addr += 4; 2339668Slinton break; 2349668Slinton 2359668Slinton case LONGDISPDEF: 2369668Slinton printf("*"); 2379668Slinton argval = printdisp(addr, 4, reg, amode); 2389668Slinton addr += 4; 2399668Slinton break; 2409668Slinton } 2419668Slinton } 2429668Slinton if (ins == O_CASEB || ins == O_CASEW || ins == O_CASEL) { 2439668Slinton for (argno = 0; argno <= argval; argno++) { 2449668Slinton iread(&offset, addr, sizeof(offset)); 2459668Slinton printf("\n\t\t%d", offset); 2469668Slinton addr += 2; 2479668Slinton } 2489668Slinton } 2499668Slinton printf("\n"); 2509668Slinton return addr; 2519668Slinton } 2529668Slinton 2539668Slinton /* 2549668Slinton * Print the displacement of an instruction that uses displacement 2559668Slinton * addressing. 2569668Slinton */ 2579668Slinton 2589668Slinton private int printdisp(addr, nbytes, reg, mode) 2599668Slinton Address addr; 2609668Slinton int nbytes; 2619668Slinton char *reg; 2629668Slinton int mode; 2639668Slinton { 2649668Slinton char byte; 2659668Slinton short hword; 2669668Slinton int argval; 26714338Slinton Symbol f; 2689668Slinton 2699668Slinton switch (nbytes) { 2709668Slinton case 1: 2719668Slinton iread(&byte, addr, sizeof(byte)); 2729668Slinton argval = byte; 2739668Slinton break; 2749668Slinton 2759668Slinton case 2: 2769668Slinton iread(&hword, addr, sizeof(hword)); 2779668Slinton argval = hword; 2789668Slinton break; 2799668Slinton 2809668Slinton case 4: 2819668Slinton iread(&argval, addr, sizeof(argval)); 2829668Slinton break; 2839668Slinton } 2849668Slinton if (reg == regname[PROGCTR] && mode >= BYTEDISP) { 2859668Slinton argval += addr + nbytes; 2869668Slinton } 2879668Slinton if (reg == regname[PROGCTR]) { 28814338Slinton f = whatblock((Address) argval + 2); 28914338Slinton if (codeloc(f) == argval + 2) { 29014338Slinton printf("%s", symname(f)); 29114338Slinton } else { 29214338Slinton printf("%x", argval); 29314338Slinton } 2949668Slinton } else { 295*18222Slinton if (varIsSet("$hexoffsets")) { 296*18222Slinton if (argval < 0) { 297*18222Slinton printf("-%x(%s)", -(argval), reg); 298*18222Slinton } else { 299*18222Slinton printf("%x(%s)", argval, reg); 300*18222Slinton } 301*18222Slinton } else { 302*18222Slinton printf("%d(%s)", argval, reg); 303*18222Slinton } 3049668Slinton } 3059668Slinton return argval; 3069668Slinton } 3079668Slinton 3089668Slinton /* 3099668Slinton * Print the contents of the addresses within the given range 3109668Slinton * according to the given format. 3119668Slinton */ 3129668Slinton 3139668Slinton typedef struct { 3149668Slinton String name; 3159668Slinton String printfstring; 3169668Slinton int length; 3179668Slinton } Format; 3189668Slinton 3199668Slinton private Format fmt[] = { 3209668Slinton { "d", " %d", sizeof(short) }, 3219668Slinton { "D", " %ld", sizeof(long) }, 3229668Slinton { "o", " %o", sizeof(short) }, 3239668Slinton { "O", " %lo", sizeof(long) }, 3249668Slinton { "x", " %04x", sizeof(short) }, 3259668Slinton { "X", " %08x", sizeof(long) }, 3269668Slinton { "b", " \\%o", sizeof(char) }, 3279668Slinton { "c", " '%c'", sizeof(char) }, 3289668Slinton { "s", "%c", sizeof(char) }, 32914338Slinton { "f", " %f", sizeof(float) }, 3309668Slinton { "g", " %g", sizeof(double) }, 3319668Slinton { nil, nil, 0 } 3329668Slinton }; 3339668Slinton 33411174Slinton private Format *findformat(s) 33511174Slinton String s; 33611174Slinton { 33711174Slinton register Format *f; 33811174Slinton 33911174Slinton f = &fmt[0]; 34011174Slinton while (f->name != nil and not streq(f->name, s)) { 34111174Slinton ++f; 34211174Slinton } 34311174Slinton if (f->name == nil) { 34411174Slinton error("bad print format \"%s\"", s); 34511174Slinton } 34611174Slinton return f; 34711174Slinton } 34811174Slinton 3499668Slinton public Address printdata(lowaddr, highaddr, format) 3509668Slinton Address lowaddr; 3519668Slinton Address highaddr; 3529668Slinton String format; 3539668Slinton { 3549668Slinton register int n; 3559668Slinton register Address addr; 3569668Slinton register Format *f; 3579668Slinton int value; 3589668Slinton 3599668Slinton if (lowaddr > highaddr) { 3609668Slinton error("first address larger than second"); 3619668Slinton } 36211174Slinton f = findformat(format); 3639668Slinton n = 0; 3649668Slinton value = 0; 3659668Slinton for (addr = lowaddr; addr <= highaddr; addr += f->length) { 3669668Slinton if (n == 0) { 3679668Slinton printf("%08x: ", addr); 3689668Slinton } 3699668Slinton dread(&value, addr, f->length); 3709668Slinton printf(f->printfstring, value); 3719668Slinton ++n; 3729668Slinton if (n >= (16 div f->length)) { 3739668Slinton putchar('\n'); 3749668Slinton n = 0; 3759668Slinton } 3769668Slinton } 3779668Slinton if (n != 0) { 3789668Slinton putchar('\n'); 3799668Slinton } 3809668Slinton prtaddr = addr; 3819668Slinton return addr; 3829668Slinton } 3839668Slinton 3849668Slinton /* 3859668Slinton * The other approach is to print n items starting with a given address. 3869668Slinton */ 3879668Slinton 3889668Slinton public printndata(count, startaddr, format) 3899668Slinton int count; 3909668Slinton Address startaddr; 3919668Slinton String format; 3929668Slinton { 3939668Slinton register int i, n; 3949668Slinton register Address addr; 3959668Slinton register Format *f; 3969668Slinton register Boolean isstring; 39714338Slinton char c; 39814338Slinton union { 39914338Slinton char charv; 40014338Slinton short shortv; 40114338Slinton int intv; 40214338Slinton float floatv; 40314338Slinton double doublev; 40414338Slinton } value; 4059668Slinton 4069668Slinton if (count <= 0) { 4079668Slinton error("non-positive repetition count"); 4089668Slinton } 40911174Slinton f = findformat(format); 4109668Slinton isstring = (Boolean) streq(f->name, "s"); 4119668Slinton n = 0; 4129668Slinton addr = startaddr; 41314338Slinton value.intv = 0; 4149668Slinton for (i = 0; i < count; i++) { 4159668Slinton if (n == 0) { 4169668Slinton printf("%08x: ", addr); 4179668Slinton } 4189668Slinton if (isstring) { 4199668Slinton putchar('"'); 42014338Slinton dread(&c, addr, sizeof(char)); 42114338Slinton while (c != '\0') { 42214338Slinton printchar(c); 4239668Slinton ++addr; 42414338Slinton dread(&c, addr, sizeof(char)); 4259668Slinton } 4269668Slinton putchar('"'); 4279668Slinton putchar('\n'); 4289668Slinton n = 0; 4299668Slinton addr += sizeof(String); 4309668Slinton } else { 4319668Slinton dread(&value, addr, f->length); 4329668Slinton printf(f->printfstring, value); 4339668Slinton ++n; 4349668Slinton if (n >= (16 div f->length)) { 4359668Slinton putchar('\n'); 4369668Slinton n = 0; 4379668Slinton } 4389668Slinton addr += f->length; 4399668Slinton } 4409668Slinton } 4419668Slinton if (n != 0) { 4429668Slinton putchar('\n'); 4439668Slinton } 4449668Slinton prtaddr = addr; 4459668Slinton } 4469668Slinton 4479668Slinton /* 44811174Slinton * Print out a value according to the given format. 44911174Slinton */ 45011174Slinton 45111174Slinton public printvalue(v, format) 45211174Slinton long v; 45311174Slinton String format; 45411174Slinton { 45511174Slinton Format *f; 45611174Slinton char *p, *q; 45711174Slinton 45811174Slinton f = findformat(format); 45911174Slinton if (streq(f->name, "s")) { 46011174Slinton putchar('"'); 46111174Slinton p = (char *) &v; 46211174Slinton q = p + sizeof(v); 46311174Slinton while (p < q) { 46411174Slinton printchar(*p); 46511174Slinton ++p; 46611174Slinton } 46711174Slinton putchar('"'); 46811174Slinton } else { 46911174Slinton printf(f->printfstring, v); 47011174Slinton } 47111174Slinton putchar('\n'); 47211174Slinton } 47311174Slinton 47411174Slinton /* 4759668Slinton * Print out an execution time error. 4769842Slinton * Assumes the source position of the error has been calculated. 4779668Slinton * 4789668Slinton * Have to check if the -r option was specified; if so then 4799668Slinton * the object file information hasn't been read in yet. 4809668Slinton */ 4819668Slinton 4829668Slinton public printerror() 4839668Slinton { 4849668Slinton extern Integer sys_nsig; 4859668Slinton extern String sys_siglist[]; 486*18222Slinton integer err; 4879668Slinton 4889668Slinton if (isfinished(process)) { 48916932Ssam err = exitcode(process); 490*18222Slinton if (err == 0) { 491*18222Slinton printf("\"%s\" terminated normally\n", objname); 492*18222Slinton } else { 493*18222Slinton printf("\"%s\" terminated abnormally (exit code %d)\n", 494*18222Slinton objname, err 495*18222Slinton ); 496*18222Slinton } 4979668Slinton erecover(); 4989668Slinton } 4999668Slinton if (runfirst) { 500*18222Slinton fprintf(stderr, "Entering debugger ...\n"); 5019668Slinton init(); 5029668Slinton } 5039668Slinton err = errnum(process); 5049668Slinton putchar('\n'); 50516932Ssam printsig(err); 506*18222Slinton putchar(' '); 50716932Ssam printloc(); 50816932Ssam putchar('\n'); 5099668Slinton if (curline > 0) { 5109668Slinton printlines(curline, curline); 5119668Slinton } else { 5129668Slinton printinst(pc, pc); 5139668Slinton } 5149668Slinton erecover(); 5159668Slinton } 5169668Slinton 517*18222Slinton /* 518*18222Slinton * Print out a signal. 519*18222Slinton */ 520*18222Slinton 52116932Ssam private String illinames[] = { 522*18222Slinton "reserved addressing fault", 523*18222Slinton "priviliged instruction fault", 524*18222Slinton "reserved operand fault" 52516932Ssam }; 526*18222Slinton 52716932Ssam private String fpenames[] = { 528*18222Slinton nil, 529*18222Slinton "integer overflow trap", 530*18222Slinton "integer divide by zero trap", 531*18222Slinton "floating overflow trap", 532*18222Slinton "floating/decimal divide by zero trap", 533*18222Slinton "floating underflow trap", 534*18222Slinton "decimal overflow trap", 535*18222Slinton "subscript out of range trap", 536*18222Slinton "floating overflow fault", 537*18222Slinton "floating divide by zero fault", 538*18222Slinton "floating undeflow fault" 53916932Ssam }; 54016932Ssam 541*18222Slinton public printsig (signo) 542*18222Slinton integer signo; 54316932Ssam { 544*18222Slinton integer code; 54516932Ssam 546*18222Slinton if (signo < 0 or signo > sys_nsig) { 547*18222Slinton printf("[signal %d]", signo); 548*18222Slinton } else { 549*18222Slinton printf("%s", sys_siglist[signo]); 55016932Ssam } 551*18222Slinton code = errcode(process); 552*18222Slinton if (signo == SIGILL) { 553*18222Slinton if (code >= 0 and code < sizeof(illinames) / sizeof(illinames[0])) { 554*18222Slinton printf(" (%s)", illinames[code]); 555*18222Slinton } 556*18222Slinton } else if (signo == SIGFPE) { 557*18222Slinton if (code > 0 and code < sizeof(fpenames) / sizeof(fpenames[0])) { 558*18222Slinton printf(" (%s)", fpenames[code]); 559*18222Slinton } 560*18222Slinton } 56116932Ssam } 56216932Ssam 5639668Slinton /* 5649668Slinton * Note the termination of the program. We do this so as to avoid 5659668Slinton * having the process exit, which would make the values of variables 5669668Slinton * inaccessible. We do want to flush all output buffers here, 5679668Slinton * otherwise it'll never get done. 5689668Slinton */ 5699668Slinton 5709668Slinton public endprogram() 5719668Slinton { 5729668Slinton Integer exitcode; 5739668Slinton 5749668Slinton stepto(nextaddr(pc, true)); 5759668Slinton printnews(); 5769668Slinton exitcode = argn(1, nil); 577*18222Slinton if (exitcode != 0) { 578*18222Slinton printf("\nexecution completed (exit code %d)\n", exitcode); 579*18222Slinton } else { 580*18222Slinton printf("\nexecution completed\n"); 581*18222Slinton } 5829668Slinton getsrcpos(); 5839668Slinton erecover(); 5849668Slinton } 5859668Slinton 5869668Slinton /* 5879668Slinton * Single step the machine a source line (or instruction if "inst_tracing" 58810621Slinton * is true). If "isnext" is true, skip over procedure calls. 5899668Slinton */ 5909668Slinton 5919668Slinton private Address getcall(); 5929668Slinton 5939668Slinton public dostep(isnext) 5949668Slinton Boolean isnext; 5959668Slinton { 5969668Slinton register Address addr; 5979668Slinton register Lineno line; 5989668Slinton String filename; 599*18222Slinton Address startaddr; 6009668Slinton 60116612Ssam startaddr = pc; 6029668Slinton addr = nextaddr(pc, isnext); 60310621Slinton if (not inst_tracing and nlhdr.nlines != 0) { 6049668Slinton line = linelookup(addr); 6059668Slinton while (line == 0) { 606*18222Slinton addr = nextaddr(addr, isnext); 6079668Slinton line = linelookup(addr); 6089668Slinton } 60910621Slinton curline = line; 61010621Slinton } else { 61110621Slinton curline = 0; 6129668Slinton } 6139668Slinton stepto(addr); 6149668Slinton filename = srcfilename(addr); 6159668Slinton setsource(filename); 6169668Slinton } 6179668Slinton 6189668Slinton /* 6199668Slinton * Compute the next address that will be executed from the given one. 6209668Slinton * If "isnext" is true then consider a procedure call as straight line code. 6219668Slinton * 6229668Slinton * We must unfortunately do much of the same work that is necessary 6239668Slinton * to print instructions. In addition we have to deal with branches. 6249668Slinton * Unconditional branches we just follow, for conditional branches 6259668Slinton * we continue execution to the current location and then single step 6269668Slinton * the machine. We assume that the last argument in an instruction 6279668Slinton * that branches is the branch address (or relative offset). 6289668Slinton */ 6299668Slinton 630*18222Slinton private Address findnextaddr(); 631*18222Slinton 6329668Slinton public Address nextaddr(startaddr, isnext) 6339668Slinton Address startaddr; 63416612Ssam boolean isnext; 63516612Ssam { 63616612Ssam Address addr; 63716612Ssam 63816612Ssam addr = usignal(process); 63916612Ssam if (addr == 0 or addr == 1) { 64016612Ssam addr = findnextaddr(startaddr, isnext); 64116612Ssam } 64216612Ssam return addr; 64316612Ssam } 64416612Ssam 645*18222Slinton /* 646*18222Slinton * Determine if it's ok to skip function f entered by instruction ins. 647*18222Slinton * If so, we're going to compute the return address and step to it. 648*18222Slinton * Therefore we cannot skip over a function entered by a jsb or bsb, 649*18222Slinton * since the return address is not easily computed for them. 650*18222Slinton */ 651*18222Slinton 652*18222Slinton private boolean skipfunc (ins, f) 653*18222Slinton VaxOpcode ins; 654*18222Slinton Symbol f; 655*18222Slinton { 656*18222Slinton boolean b; 657*18222Slinton 658*18222Slinton b = (boolean) ( 659*18222Slinton ins != O_JSB and ins != O_BSBB and ins != O_BSBW and 660*18222Slinton not inst_tracing and nlhdr.nlines != 0 and 661*18222Slinton nosource(curfunc) and canskip(curfunc) 662*18222Slinton ); 663*18222Slinton return b; 664*18222Slinton } 665*18222Slinton 66616612Ssam private Address findnextaddr(startaddr, isnext) 66716612Ssam Address startaddr; 6689668Slinton Boolean isnext; 6699668Slinton { 6709668Slinton register Address addr; 6719668Slinton Optab op; 6729668Slinton VaxOpcode ins; 6739668Slinton unsigned char mode; 6749668Slinton int argtype, amode, argno, argval; 6759668Slinton String r; 6769668Slinton Boolean indexf; 6779668Slinton enum { KNOWN, SEQUENTIAL, BRANCH } addrstatus; 6789668Slinton 6799668Slinton argval = 0; 6809668Slinton indexf = false; 6819668Slinton addr = startaddr; 6829668Slinton iread(&ins, addr, sizeof(ins)); 6839668Slinton switch (ins) { 684*18222Slinton /* 685*18222Slinton * It used to be that unconditional jumps and branches were handled 686*18222Slinton * by taking their destination address as the next address. While 687*18222Slinton * saving the cost of starting up the process, this approach 688*18222Slinton * doesn't work when jumping indirect (since the value in the 689*18222Slinton * register might not yet have been set). 690*18222Slinton * 691*18222Slinton * So unconditional jumps and branches are now handled the same way 692*18222Slinton * as conditional jumps and branches. 693*18222Slinton * 6949668Slinton case O_BRB: 6959668Slinton case O_BRW: 6969668Slinton addrstatus = BRANCH; 6979668Slinton break; 698*18222Slinton * 699*18222Slinton */ 7009668Slinton 7019668Slinton case O_BSBB: 7029668Slinton case O_BSBW: 7039668Slinton case O_JSB: 7049668Slinton case O_CALLG: 7059668Slinton case O_CALLS: 706*18222Slinton addrstatus = KNOWN; 707*18222Slinton stepto(addr); 708*18222Slinton pstep(process, DEFSIG); 709*18222Slinton addr = reg(PROGCTR); 710*18222Slinton pc = addr; 711*18222Slinton setcurfunc(whatblock(pc)); 712*18222Slinton if (not isbperr()) { 713*18222Slinton printstatus(); 714*18222Slinton /* NOTREACHED */ 715*18222Slinton } 716*18222Slinton bpact(); 717*18222Slinton if (isnext or skipfunc(ins, curfunc)) { 7189668Slinton addrstatus = KNOWN; 719*18222Slinton addr = return_addr(); 7209668Slinton stepto(addr); 72111864Slinton bpact(); 722*18222Slinton } else { 723*18222Slinton callnews(/* iscall = */ true); 7249668Slinton } 7259668Slinton break; 7269668Slinton 7279668Slinton case O_RSB: 7289668Slinton case O_RET: 7299668Slinton addrstatus = KNOWN; 730*18222Slinton stepto(addr); 7319668Slinton callnews(/* iscall = */ false); 732*18222Slinton pstep(process, DEFSIG); 733*18222Slinton addr = reg(PROGCTR); 734*18222Slinton pc = addr; 735*18222Slinton if (not isbperr()) { 736*18222Slinton printstatus(); 73716612Ssam } 73811874Slinton bpact(); 7399668Slinton break; 7409668Slinton 741*18222Slinton case O_BRB: case O_BRW: 74216612Ssam case O_JMP: /* because it may be jmp (r1) */ 7439668Slinton case O_BNEQ: case O_BEQL: case O_BGTR: 7449668Slinton case O_BLEQ: case O_BGEQ: case O_BLSS: 7459668Slinton case O_BGTRU: case O_BLEQU: case O_BVC: 7469668Slinton case O_BVS: case O_BCC: case O_BCS: 7479668Slinton case O_CASEB: case O_CASEW: case O_CASEL: 7489668Slinton case O_BBS: case O_BBC: case O_BBSS: case O_BBCS: 7499668Slinton case O_BBSC: case O_BBCC: case O_BBSSI: 7509668Slinton case O_BBCCI: case O_BLBS: case O_BLBC: 7519668Slinton case O_ACBL: case O_AOBLSS: case O_AOBLEQ: 7529668Slinton case O_SOBGEQ: case O_SOBGTR: 7539668Slinton addrstatus = KNOWN; 7549668Slinton stepto(addr); 75516612Ssam pstep(process, DEFSIG); 7569668Slinton addr = reg(PROGCTR); 7579668Slinton pc = addr; 7589668Slinton if (not isbperr()) { 7599668Slinton printstatus(); 7609668Slinton } 7619668Slinton break; 7629668Slinton 7639668Slinton default: 7649668Slinton addrstatus = SEQUENTIAL; 7659668Slinton break; 7669668Slinton } 7679668Slinton if (addrstatus != KNOWN) { 7689668Slinton addr += 1; 7699668Slinton op = optab[ins]; 7709668Slinton for (argno = 0; argno < op.numargs; argno++) { 7719668Slinton if (indexf == true) { 7729668Slinton indexf = false; 7739668Slinton } 7749668Slinton argtype = op.argtype[argno]; 7759668Slinton if (is_branch_disp(argtype)) { 7769668Slinton mode = 0xAF + (typelen(argtype) << 5); 7779668Slinton } else { 7789668Slinton iread(&mode, addr, sizeof(mode)); 7799668Slinton addr += 1; 7809668Slinton } 7819668Slinton r = regname[regnm(mode)]; 7829668Slinton amode = addrmode(mode); 7839668Slinton switch (amode) { 7849668Slinton case LITSHORT: 7859668Slinton case LITUPTO31: 7869668Slinton case LITUPTO47: 7879668Slinton case LITUPTO63: 7889668Slinton argval = mode; 7899668Slinton break; 7909668Slinton 7919668Slinton case INDEX: 7929668Slinton indexf = true; 7939668Slinton --argno; 7949668Slinton break; 7959668Slinton 7969668Slinton case REG: 7979668Slinton case REGDEF: 7989668Slinton case AUTODEC: 7999668Slinton break; 8009668Slinton 8019668Slinton case AUTOINC: 8029668Slinton if (r == regname[PROGCTR]) { 8039668Slinton switch (typelen(argtype)) { 8049668Slinton case TYPB: 8059668Slinton argval = getdisp(addr, 1, r, amode); 8069668Slinton addr += 1; 8079668Slinton break; 8089668Slinton 8099668Slinton case TYPW: 8109668Slinton argval = getdisp(addr, 2, r, amode); 8119668Slinton addr += 2; 8129668Slinton break; 8139668Slinton 8149668Slinton case TYPL: 8159668Slinton argval = getdisp(addr, 4, r, amode); 8169668Slinton addr += 4; 8179668Slinton break; 8189668Slinton 8199668Slinton case TYPF: 8209668Slinton iread(&argval, addr, sizeof(argval)); 8219668Slinton addr += 4; 8229668Slinton break; 8239668Slinton 8249668Slinton case TYPQ: 8259668Slinton case TYPD: 8269668Slinton iread(&argval, addr+4, sizeof(argval)); 8279668Slinton addr += 8; 8289668Slinton break; 8299668Slinton } 8309668Slinton } 8319668Slinton break; 8329668Slinton 8339668Slinton case AUTOINCDEF: 8349668Slinton if (r == regname[PROGCTR]) { 8359668Slinton argval = getdisp(addr, 4, r, amode); 8369668Slinton addr += 4; 8379668Slinton } 8389668Slinton break; 8399668Slinton 8409668Slinton case BYTEDISP: 8419668Slinton case BYTEDISPDEF: 8429668Slinton argval = getdisp(addr, 1, r, amode); 8439668Slinton addr += 1; 8449668Slinton break; 8459668Slinton 8469668Slinton case WORDDISP: 8479668Slinton case WORDDISPDEF: 8489668Slinton argval = getdisp(addr, 2, r, amode); 8499668Slinton addr += 2; 8509668Slinton break; 8519668Slinton 8529668Slinton case LONGDISP: 8539668Slinton case LONGDISPDEF: 8549668Slinton argval = getdisp(addr, 4, r, amode); 8559668Slinton addr += 4; 8569668Slinton break; 8579668Slinton } 8589668Slinton } 8599668Slinton if (ins == O_CALLS or ins == O_CALLG) { 8609668Slinton argval += 2; 8619668Slinton } 8629668Slinton if (addrstatus == BRANCH) { 8639668Slinton addr = argval; 8649668Slinton } 8659668Slinton } 8669668Slinton return addr; 8679668Slinton } 8689668Slinton 8699668Slinton /* 8709668Slinton * Get the displacement of an instruction that uses displacement addressing. 8719668Slinton */ 8729668Slinton 8739668Slinton private int getdisp(addr, nbytes, reg, mode) 8749668Slinton Address addr; 8759668Slinton int nbytes; 8769668Slinton String reg; 8779668Slinton int mode; 8789668Slinton { 8799668Slinton char byte; 8809668Slinton short hword; 8819668Slinton int argval; 8829668Slinton 8839668Slinton switch (nbytes) { 8849668Slinton case 1: 8859668Slinton iread(&byte, addr, sizeof(byte)); 8869668Slinton argval = byte; 8879668Slinton break; 8889668Slinton 8899668Slinton case 2: 8909668Slinton iread(&hword, addr, sizeof(hword)); 8919668Slinton argval = hword; 8929668Slinton break; 8939668Slinton 8949668Slinton case 4: 8959668Slinton iread(&argval, addr, sizeof(argval)); 8969668Slinton break; 8979668Slinton } 8989668Slinton if (reg == regname[PROGCTR] && mode >= BYTEDISP) { 8999668Slinton argval += addr + nbytes; 9009668Slinton } 9019668Slinton return argval; 9029668Slinton } 9039668Slinton 9049668Slinton #define BP_OP O_BPT /* breakpoint trap */ 9059668Slinton #define BP_ERRNO SIGTRAP /* signal received at a breakpoint */ 9069668Slinton 9079668Slinton /* 9089668Slinton * Setting a breakpoint at a location consists of saving 9099668Slinton * the word at the location and poking a BP_OP there. 9109668Slinton * 9119668Slinton * We save the locations and words on a list for use in unsetting. 9129668Slinton */ 9139668Slinton 9149668Slinton typedef struct Savelist *Savelist; 9159668Slinton 9169668Slinton struct Savelist { 9179668Slinton Address location; 9189668Slinton Byte save; 9199668Slinton Byte refcount; 9209668Slinton Savelist link; 9219668Slinton }; 9229668Slinton 9239668Slinton private Savelist savelist; 9249668Slinton 9259668Slinton /* 9269668Slinton * Set a breakpoint at the given address. Only save the word there 9279668Slinton * if it's not already a breakpoint. 9289668Slinton */ 9299668Slinton 9309668Slinton public setbp(addr) 9319668Slinton Address addr; 9329668Slinton { 9339668Slinton Byte w; 9349668Slinton Byte save; 9359668Slinton register Savelist newsave, s; 9369668Slinton 9379668Slinton for (s = savelist; s != nil; s = s->link) { 9389668Slinton if (s->location == addr) { 9399668Slinton s->refcount++; 9409668Slinton return; 9419668Slinton } 9429668Slinton } 94311174Slinton iread(&save, addr, sizeof(save)); 9449668Slinton newsave = new(Savelist); 9459668Slinton newsave->location = addr; 9469668Slinton newsave->save = save; 9479668Slinton newsave->refcount = 1; 9489668Slinton newsave->link = savelist; 9499668Slinton savelist = newsave; 9509668Slinton w = BP_OP; 9519668Slinton iwrite(&w, addr, sizeof(w)); 9529668Slinton } 9539668Slinton 9549668Slinton /* 9559668Slinton * Unset a breakpoint; unfortunately we have to search the SAVELIST 9569668Slinton * to find the saved value. The assumption is that the SAVELIST will 9579668Slinton * usually be quite small. 9589668Slinton */ 9599668Slinton 9609668Slinton public unsetbp(addr) 9619668Slinton Address addr; 9629668Slinton { 9639668Slinton register Savelist s, prev; 9649668Slinton 9659668Slinton prev = nil; 9669668Slinton for (s = savelist; s != nil; s = s->link) { 9679668Slinton if (s->location == addr) { 9689668Slinton iwrite(&s->save, addr, sizeof(s->save)); 9699668Slinton s->refcount--; 9709668Slinton if (s->refcount == 0) { 9719668Slinton if (prev == nil) { 9729668Slinton savelist = s->link; 9739668Slinton } else { 9749668Slinton prev->link = s->link; 9759668Slinton } 9769668Slinton dispose(s); 9779668Slinton } 9789668Slinton return; 9799668Slinton } 9809668Slinton prev = s; 9819668Slinton } 9829668Slinton panic("unsetbp: couldn't find address %d", addr); 9839668Slinton } 9849668Slinton 9859668Slinton /* 9869668Slinton * Enter a procedure by creating and executing a call instruction. 9879668Slinton */ 9889668Slinton 9899668Slinton #define CALLSIZE 7 /* size of call instruction */ 9909668Slinton 9919668Slinton public beginproc(p, argc) 9929668Slinton Symbol p; 9939668Slinton Integer argc; 9949668Slinton { 9959668Slinton char save[CALLSIZE]; 9969668Slinton struct { 9979668Slinton VaxOpcode op; 9989668Slinton unsigned char numargs; 9999668Slinton unsigned char mode; 10009668Slinton char addr[sizeof(long)]; /* unaligned long */ 10019668Slinton } call; 10029668Slinton long dest; 10039668Slinton 10049668Slinton pc = 2; 10059668Slinton iread(save, pc, sizeof(save)); 10069668Slinton call.op = O_CALLS; 10079668Slinton call.numargs = argc; 10089668Slinton call.mode = 0xef; 10099668Slinton dest = codeloc(p) - 2 - (pc + 7); 10109668Slinton mov(&dest, call.addr, sizeof(call.addr)); 10119668Slinton iwrite(&call, pc, sizeof(call)); 10129668Slinton setreg(PROGCTR, pc); 101316612Ssam pstep(process, DEFSIG); 10149668Slinton iwrite(save, pc, sizeof(save)); 10159668Slinton pc = reg(PROGCTR); 10169668Slinton if (not isbperr()) { 10179668Slinton printstatus(); 10189668Slinton } 10199668Slinton } 1020