19668Slinton /* Copyright (c) 1982 Regents of the University of California */ 29668Slinton 3*16932Ssam static char sccsid[] = "@(#)vax.c 1.11 (Berkeley) 08/12/84"; 49668Slinton 59668Slinton /* 69668Slinton * Target machine dependent stuff. 79668Slinton */ 89668Slinton 99668Slinton #include "defs.h" 109668Slinton #include "machine.h" 119668Slinton #include "process.h" 1216612Ssam #include "runtime.h" 139668Slinton #include "events.h" 149668Slinton #include "main.h" 159668Slinton #include "symbols.h" 169668Slinton #include "source.h" 179668Slinton #include "mappings.h" 189668Slinton #include "object.h" 199693Slinton #include "ops.h" 209668Slinton #include <signal.h> 219668Slinton 229668Slinton #ifndef public 239668Slinton typedef unsigned int Address; 249668Slinton typedef unsigned char Byte; 259668Slinton typedef unsigned int Word; 269668Slinton 279668Slinton #define NREG 16 289668Slinton 299668Slinton #define ARGP 12 309668Slinton #define FRP 13 319668Slinton #define STKP 14 329668Slinton #define PROGCTR 15 339668Slinton 349668Slinton #define BITSPERBYTE 8 359668Slinton #define BITSPERWORD (BITSPERBYTE * sizeof(Word)) 369668Slinton 379668Slinton #define nargspassed(frame) argn(0, frame) 389668Slinton 399668Slinton #include "source.h" 409668Slinton #include "symbols.h" 419668Slinton 429668Slinton Address pc; 439668Slinton Address prtaddr; 449668Slinton 459668Slinton #endif 469668Slinton 479668Slinton private Address printop(); 489668Slinton 499668Slinton /* 509668Slinton * Decode and print the instructions within the given address range. 519668Slinton */ 529668Slinton 539668Slinton public printinst(lowaddr, highaddr) 549668Slinton Address lowaddr; 559668Slinton Address highaddr; 569668Slinton { 579668Slinton register Address addr; 589668Slinton 599668Slinton for (addr = lowaddr; addr <= highaddr; ) { 609668Slinton addr = printop(addr); 619668Slinton } 629668Slinton prtaddr = addr; 639668Slinton } 649668Slinton 659668Slinton /* 669668Slinton * Another approach: print n instructions starting at the given address. 679668Slinton */ 689668Slinton 699668Slinton public printninst(count, addr) 709668Slinton int count; 719668Slinton Address addr; 729668Slinton { 739668Slinton register Integer i; 749668Slinton register Address newaddr; 759668Slinton 769668Slinton if (count <= 0) { 779668Slinton error("non-positive repetition count"); 789668Slinton } else { 799668Slinton newaddr = addr; 809668Slinton for (i = 0; i < count; i++) { 819668Slinton newaddr = printop(newaddr); 829668Slinton } 839668Slinton prtaddr = newaddr; 849668Slinton } 859668Slinton } 869668Slinton 879668Slinton /* 889668Slinton * Hacked version of adb's VAX instruction decoder. 899668Slinton */ 909668Slinton 919668Slinton private Address printop(addr) 929668Slinton Address addr; 939668Slinton { 949668Slinton Optab op; 959668Slinton VaxOpcode ins; 969668Slinton unsigned char mode; 979668Slinton int argtype, amode, argno, argval; 989668Slinton String reg; 999668Slinton Boolean indexf; 1009668Slinton short offset; 1019668Slinton 1029668Slinton argval = 0; 1039668Slinton indexf = false; 1049668Slinton printf("%08x ", addr); 1059668Slinton iread(&ins, addr, sizeof(ins)); 1069668Slinton addr += 1; 1079668Slinton op = optab[ins]; 1089668Slinton printf("%s", op.iname); 1099668Slinton for (argno = 0; argno < op.numargs; argno++) { 1109668Slinton if (indexf == true) { 1119668Slinton indexf = false; 1129668Slinton } else if (argno == 0) { 1139668Slinton printf("\t"); 1149668Slinton } else { 1159668Slinton printf(","); 1169668Slinton } 1179668Slinton argtype = op.argtype[argno]; 1189668Slinton if (is_branch_disp(argtype)) { 1199668Slinton mode = 0xAF + (typelen(argtype) << 5); 1209668Slinton } else { 1219668Slinton iread(&mode, addr, sizeof(mode)); 1229668Slinton addr += 1; 1239668Slinton } 1249668Slinton reg = regname[regnm(mode)]; 1259668Slinton amode = addrmode(mode); 1269668Slinton switch (amode) { 1279668Slinton case LITSHORT: 1289668Slinton case LITUPTO31: 1299668Slinton case LITUPTO47: 1309668Slinton case LITUPTO63: 1319668Slinton if (typelen(argtype) == TYPF || typelen(argtype) ==TYPD) 1329668Slinton printf("$%s", fltimm[mode]); 1339668Slinton else 1349668Slinton printf("$%x", mode); 1359668Slinton argval = mode; 1369668Slinton break; 1379668Slinton 1389668Slinton case INDEX: 1399668Slinton printf("[%s]", reg); 1409668Slinton indexf = true; 1419668Slinton argno--; 1429668Slinton break; 1439668Slinton 1449668Slinton case REG: 1459668Slinton printf("%s", reg); 1469668Slinton break; 1479668Slinton 1489668Slinton case REGDEF: 1499668Slinton printf("(%s)", reg); 1509668Slinton break; 1519668Slinton 1529668Slinton case AUTODEC: 1539668Slinton printf("-(%s)", reg); 1549668Slinton break; 1559668Slinton 1569668Slinton case AUTOINC: 1579668Slinton if (reg != regname[PROGCTR]) { 1589668Slinton printf("(%s)+", reg); 1599668Slinton } else { 1609668Slinton printf("$"); 1619668Slinton switch (typelen(argtype)) { 1629668Slinton case TYPB: 1639668Slinton argval = printdisp(addr, 1, reg, amode); 1649668Slinton addr += 1; 1659668Slinton break; 1669668Slinton 1679668Slinton case TYPW: 1689668Slinton argval = printdisp(addr, 2, reg, amode); 1699668Slinton addr += 2; 1709668Slinton break; 1719668Slinton 1729668Slinton case TYPL: 1739668Slinton argval = printdisp(addr, 4, reg, amode); 1749668Slinton addr += 4; 1759668Slinton break; 1769668Slinton 1779668Slinton case TYPF: 1789668Slinton iread(&argval, addr, sizeof(argval)); 1799668Slinton printf("%06x", argval); 1809668Slinton addr += 4; 1819668Slinton break; 1829668Slinton 1839668Slinton case TYPQ: 1849668Slinton case TYPD: 1859668Slinton iread(&argval, addr, sizeof(argval)); 1869668Slinton printf("%06x", argval); 1879668Slinton iread(&argval, addr+4, sizeof(argval)); 1889668Slinton printf("%06x", argval); 1899668Slinton addr += 8; 1909668Slinton break; 1919668Slinton } 1929668Slinton } 1939668Slinton break; 1949668Slinton 1959668Slinton case AUTOINCDEF: 1969668Slinton if (reg == regname[PROGCTR]) { 1979668Slinton printf("*$"); 1989668Slinton argval = printdisp(addr, 4, reg, amode); 1999668Slinton addr += 4; 2009668Slinton } else { 2019668Slinton printf("*(%s)+", reg); 2029668Slinton } 2039668Slinton break; 2049668Slinton 2059668Slinton case BYTEDISP: 2069668Slinton argval = printdisp(addr, 1, reg, amode); 2079668Slinton addr += 1; 2089668Slinton break; 2099668Slinton 2109668Slinton case BYTEDISPDEF: 2119668Slinton printf("*"); 2129668Slinton argval = printdisp(addr, 1, reg, amode); 2139668Slinton addr += 1; 2149668Slinton break; 2159668Slinton 2169668Slinton case WORDDISP: 2179668Slinton argval = printdisp(addr, 2, reg, amode); 2189668Slinton addr += 2; 2199668Slinton break; 2209668Slinton 2219668Slinton case WORDDISPDEF: 2229668Slinton printf("*"); 2239668Slinton argval = printdisp(addr, 2, reg, amode); 2249668Slinton addr += 2; 2259668Slinton break; 2269668Slinton 2279668Slinton case LONGDISP: 2289668Slinton argval = printdisp(addr, 4, reg, amode); 2299668Slinton addr += 4; 2309668Slinton break; 2319668Slinton 2329668Slinton case LONGDISPDEF: 2339668Slinton printf("*"); 2349668Slinton argval = printdisp(addr, 4, reg, amode); 2359668Slinton addr += 4; 2369668Slinton break; 2379668Slinton } 2389668Slinton } 2399668Slinton if (ins == O_CASEB || ins == O_CASEW || ins == O_CASEL) { 2409668Slinton for (argno = 0; argno <= argval; argno++) { 2419668Slinton iread(&offset, addr, sizeof(offset)); 2429668Slinton printf("\n\t\t%d", offset); 2439668Slinton addr += 2; 2449668Slinton } 2459668Slinton } 2469668Slinton printf("\n"); 2479668Slinton return addr; 2489668Slinton } 2499668Slinton 2509668Slinton /* 2519668Slinton * Print the displacement of an instruction that uses displacement 2529668Slinton * addressing. 2539668Slinton */ 2549668Slinton 2559668Slinton private int printdisp(addr, nbytes, reg, mode) 2569668Slinton Address addr; 2579668Slinton int nbytes; 2589668Slinton char *reg; 2599668Slinton int mode; 2609668Slinton { 2619668Slinton char byte; 2629668Slinton short hword; 2639668Slinton int argval; 26414338Slinton Symbol f; 2659668Slinton 2669668Slinton switch (nbytes) { 2679668Slinton case 1: 2689668Slinton iread(&byte, addr, sizeof(byte)); 2699668Slinton argval = byte; 2709668Slinton break; 2719668Slinton 2729668Slinton case 2: 2739668Slinton iread(&hword, addr, sizeof(hword)); 2749668Slinton argval = hword; 2759668Slinton break; 2769668Slinton 2779668Slinton case 4: 2789668Slinton iread(&argval, addr, sizeof(argval)); 2799668Slinton break; 2809668Slinton } 2819668Slinton if (reg == regname[PROGCTR] && mode >= BYTEDISP) { 2829668Slinton argval += addr + nbytes; 2839668Slinton } 2849668Slinton if (reg == regname[PROGCTR]) { 28514338Slinton f = whatblock((Address) argval + 2); 28614338Slinton if (codeloc(f) == argval + 2) { 28714338Slinton printf("%s", symname(f)); 28814338Slinton } else { 28914338Slinton printf("%x", argval); 29014338Slinton } 2919668Slinton } else { 2929668Slinton printf("%d(%s)", argval, reg); 2939668Slinton } 2949668Slinton return argval; 2959668Slinton } 2969668Slinton 2979668Slinton /* 2989668Slinton * Print the contents of the addresses within the given range 2999668Slinton * according to the given format. 3009668Slinton */ 3019668Slinton 3029668Slinton typedef struct { 3039668Slinton String name; 3049668Slinton String printfstring; 3059668Slinton int length; 3069668Slinton } Format; 3079668Slinton 3089668Slinton private Format fmt[] = { 3099668Slinton { "d", " %d", sizeof(short) }, 3109668Slinton { "D", " %ld", sizeof(long) }, 3119668Slinton { "o", " %o", sizeof(short) }, 3129668Slinton { "O", " %lo", sizeof(long) }, 3139668Slinton { "x", " %04x", sizeof(short) }, 3149668Slinton { "X", " %08x", sizeof(long) }, 3159668Slinton { "b", " \\%o", sizeof(char) }, 3169668Slinton { "c", " '%c'", sizeof(char) }, 3179668Slinton { "s", "%c", sizeof(char) }, 31814338Slinton { "f", " %f", sizeof(float) }, 3199668Slinton { "g", " %g", sizeof(double) }, 3209668Slinton { nil, nil, 0 } 3219668Slinton }; 3229668Slinton 32311174Slinton private Format *findformat(s) 32411174Slinton String s; 32511174Slinton { 32611174Slinton register Format *f; 32711174Slinton 32811174Slinton f = &fmt[0]; 32911174Slinton while (f->name != nil and not streq(f->name, s)) { 33011174Slinton ++f; 33111174Slinton } 33211174Slinton if (f->name == nil) { 33311174Slinton error("bad print format \"%s\"", s); 33411174Slinton } 33511174Slinton return f; 33611174Slinton } 33711174Slinton 3389668Slinton public Address printdata(lowaddr, highaddr, format) 3399668Slinton Address lowaddr; 3409668Slinton Address highaddr; 3419668Slinton String format; 3429668Slinton { 3439668Slinton register int n; 3449668Slinton register Address addr; 3459668Slinton register Format *f; 3469668Slinton int value; 3479668Slinton 3489668Slinton if (lowaddr > highaddr) { 3499668Slinton error("first address larger than second"); 3509668Slinton } 35111174Slinton f = findformat(format); 3529668Slinton n = 0; 3539668Slinton value = 0; 3549668Slinton for (addr = lowaddr; addr <= highaddr; addr += f->length) { 3559668Slinton if (n == 0) { 3569668Slinton printf("%08x: ", addr); 3579668Slinton } 3589668Slinton dread(&value, addr, f->length); 3599668Slinton printf(f->printfstring, value); 3609668Slinton ++n; 3619668Slinton if (n >= (16 div f->length)) { 3629668Slinton putchar('\n'); 3639668Slinton n = 0; 3649668Slinton } 3659668Slinton } 3669668Slinton if (n != 0) { 3679668Slinton putchar('\n'); 3689668Slinton } 3699668Slinton prtaddr = addr; 3709668Slinton return addr; 3719668Slinton } 3729668Slinton 3739668Slinton /* 3749668Slinton * The other approach is to print n items starting with a given address. 3759668Slinton */ 3769668Slinton 3779668Slinton public printndata(count, startaddr, format) 3789668Slinton int count; 3799668Slinton Address startaddr; 3809668Slinton String format; 3819668Slinton { 3829668Slinton register int i, n; 3839668Slinton register Address addr; 3849668Slinton register Format *f; 3859668Slinton register Boolean isstring; 38614338Slinton char c; 38714338Slinton union { 38814338Slinton char charv; 38914338Slinton short shortv; 39014338Slinton int intv; 39114338Slinton float floatv; 39214338Slinton double doublev; 39314338Slinton } value; 3949668Slinton 3959668Slinton if (count <= 0) { 3969668Slinton error("non-positive repetition count"); 3979668Slinton } 39811174Slinton f = findformat(format); 3999668Slinton isstring = (Boolean) streq(f->name, "s"); 4009668Slinton n = 0; 4019668Slinton addr = startaddr; 40214338Slinton value.intv = 0; 4039668Slinton for (i = 0; i < count; i++) { 4049668Slinton if (n == 0) { 4059668Slinton printf("%08x: ", addr); 4069668Slinton } 4079668Slinton if (isstring) { 4089668Slinton putchar('"'); 40914338Slinton dread(&c, addr, sizeof(char)); 41014338Slinton while (c != '\0') { 41114338Slinton printchar(c); 4129668Slinton ++addr; 41314338Slinton dread(&c, addr, sizeof(char)); 4149668Slinton } 4159668Slinton putchar('"'); 4169668Slinton putchar('\n'); 4179668Slinton n = 0; 4189668Slinton addr += sizeof(String); 4199668Slinton } else { 4209668Slinton dread(&value, addr, f->length); 4219668Slinton printf(f->printfstring, value); 4229668Slinton ++n; 4239668Slinton if (n >= (16 div f->length)) { 4249668Slinton putchar('\n'); 4259668Slinton n = 0; 4269668Slinton } 4279668Slinton addr += f->length; 4289668Slinton } 4299668Slinton } 4309668Slinton if (n != 0) { 4319668Slinton putchar('\n'); 4329668Slinton } 4339668Slinton prtaddr = addr; 4349668Slinton } 4359668Slinton 4369668Slinton /* 43711174Slinton * Print out a value according to the given format. 43811174Slinton */ 43911174Slinton 44011174Slinton public printvalue(v, format) 44111174Slinton long v; 44211174Slinton String format; 44311174Slinton { 44411174Slinton Format *f; 44511174Slinton char *p, *q; 44611174Slinton 44711174Slinton f = findformat(format); 44811174Slinton if (streq(f->name, "s")) { 44911174Slinton putchar('"'); 45011174Slinton p = (char *) &v; 45111174Slinton q = p + sizeof(v); 45211174Slinton while (p < q) { 45311174Slinton printchar(*p); 45411174Slinton ++p; 45511174Slinton } 45611174Slinton putchar('"'); 45711174Slinton } else { 45811174Slinton printf(f->printfstring, v); 45911174Slinton } 46011174Slinton putchar('\n'); 46111174Slinton } 46211174Slinton 46311174Slinton /* 4649668Slinton * Print out an execution time error. 4659842Slinton * Assumes the source position of the error has been calculated. 4669668Slinton * 4679668Slinton * Have to check if the -r option was specified; if so then 4689668Slinton * the object file information hasn't been read in yet. 4699668Slinton */ 4709668Slinton 4719668Slinton public printerror() 4729668Slinton { 4739668Slinton extern Integer sys_nsig; 4749668Slinton extern String sys_siglist[]; 4759668Slinton Integer err; 4769668Slinton 4779668Slinton if (isfinished(process)) { 478*16932Ssam err = exitcode(process); 479*16932Ssam printf("\"%s\" terminated", objname); 480*16932Ssam if (err) 481*16932Ssam printf("abnormally (exit code %d)", err); 482*16932Ssam putchar('\n'); 4839668Slinton erecover(); 4849668Slinton } 4859668Slinton if (runfirst) { 4869668Slinton fprintf(stderr, "Entering debugger ..."); 4879668Slinton init(); 4889668Slinton fprintf(stderr, " type 'help' for help\n"); 4899668Slinton } 4909668Slinton err = errnum(process); 4919668Slinton putchar('\n'); 492*16932Ssam printsig(err); 493*16932Ssam printloc(); 494*16932Ssam putchar('\n'); 4959668Slinton if (curline > 0) { 4969668Slinton printlines(curline, curline); 4979668Slinton } else { 4989668Slinton printinst(pc, pc); 4999668Slinton } 5009668Slinton erecover(); 5019668Slinton } 5029668Slinton 503*16932Ssam private String illinames[] = { 504*16932Ssam "reserved addressing fault", 505*16932Ssam "priviliged instruction fault", 506*16932Ssam "reserved operand fault" 507*16932Ssam }; 508*16932Ssam private String fpenames[] = { 509*16932Ssam nil, 510*16932Ssam "integer overflow trap", 511*16932Ssam "integer divide by zero trap", 512*16932Ssam "floating overflow trap", 513*16932Ssam "floating/decimal divide by zero trap", 514*16932Ssam "floating underflow trap", 515*16932Ssam "decimal overflow trap", 516*16932Ssam "subscript out of range trap", 517*16932Ssam "floating overflow fault", 518*16932Ssam "floating divide by zero fault", 519*16932Ssam "floating undeflow fault" 520*16932Ssam }; 521*16932Ssam 522*16932Ssam public printsig(signo) 523*16932Ssam Integer signo; 524*16932Ssam { 525*16932Ssam Integer sigcode; 526*16932Ssam 527*16932Ssam if (0 < signo && signo < sys_nsig) 528*16932Ssam printf("%s ", sys_siglist[signo]); 529*16932Ssam else 530*16932Ssam printf("signal %d ", signo); 531*16932Ssam sigcode = errcode(process); 532*16932Ssam switch (signo) { 533*16932Ssam 534*16932Ssam case SIGFPE: 535*16932Ssam if (sigcode > 0 && 536*16932Ssam sigcode < sizeof fpenames / sizeof fpenames[0]) 537*16932Ssam printf("(%s) ", fpenames[sigcode]); 538*16932Ssam break; 539*16932Ssam 540*16932Ssam case SIGILL: 541*16932Ssam if (sigcode >= 0 && 542*16932Ssam sigcode < sizeof illinames / sizeof illinames[0]) 543*16932Ssam printf("(%s) ", illinames[sigcode]); 544*16932Ssam break; 545*16932Ssam } 546*16932Ssam } 547*16932Ssam 5489668Slinton /* 5499668Slinton * Note the termination of the program. We do this so as to avoid 5509668Slinton * having the process exit, which would make the values of variables 5519668Slinton * inaccessible. We do want to flush all output buffers here, 5529668Slinton * otherwise it'll never get done. 5539668Slinton */ 5549668Slinton 5559668Slinton public endprogram() 5569668Slinton { 5579668Slinton Integer exitcode; 5589668Slinton 5599668Slinton stepto(nextaddr(pc, true)); 5609668Slinton printnews(); 5619668Slinton exitcode = argn(1, nil); 562*16932Ssam printf("\nexecution completed"); 563*16932Ssam if (exitcode) 564*16932Ssam printf(" (exit code %d)", exitcode); 565*16932Ssam putchar('\n'); 5669668Slinton getsrcpos(); 5679668Slinton erecover(); 5689668Slinton } 5699668Slinton 5709668Slinton /* 5719668Slinton * Single step the machine a source line (or instruction if "inst_tracing" 57210621Slinton * is true). If "isnext" is true, skip over procedure calls. 5739668Slinton */ 5749668Slinton 5759668Slinton private Address getcall(); 5769668Slinton 5779668Slinton public dostep(isnext) 5789668Slinton Boolean isnext; 5799668Slinton { 5809668Slinton register Address addr; 5819668Slinton register Lineno line; 5829668Slinton String filename; 58316612Ssam Address startaddr, prevaddr; 5849668Slinton 58516612Ssam startaddr = pc; 58616612Ssam prevaddr = startaddr; 5879668Slinton addr = nextaddr(pc, isnext); 58810621Slinton if (not inst_tracing and nlhdr.nlines != 0) { 5899668Slinton line = linelookup(addr); 5909668Slinton while (line == 0) { 59116612Ssam prevaddr = addr; 5929668Slinton addr = nextaddr(addr, isnext); 5939668Slinton line = linelookup(addr); 5949668Slinton } 59510621Slinton curline = line; 59610621Slinton } else { 59710621Slinton curline = 0; 5989668Slinton } 59916612Ssam if (addr == startaddr) { 60016612Ssam stepto(prevaddr); 60116612Ssam } 6029668Slinton stepto(addr); 6039668Slinton filename = srcfilename(addr); 6049668Slinton setsource(filename); 6059668Slinton } 6069668Slinton 6079668Slinton /* 6089668Slinton * Compute the next address that will be executed from the given one. 6099668Slinton * If "isnext" is true then consider a procedure call as straight line code. 6109668Slinton * 6119668Slinton * We must unfortunately do much of the same work that is necessary 6129668Slinton * to print instructions. In addition we have to deal with branches. 6139668Slinton * Unconditional branches we just follow, for conditional branches 6149668Slinton * we continue execution to the current location and then single step 6159668Slinton * the machine. We assume that the last argument in an instruction 6169668Slinton * that branches is the branch address (or relative offset). 6179668Slinton */ 6189668Slinton 61916612Ssam private Address findnextaddr(); 62016612Ssam 6219668Slinton public Address nextaddr(startaddr, isnext) 6229668Slinton Address startaddr; 62316612Ssam boolean isnext; 62416612Ssam { 62516612Ssam Address addr; 62616612Ssam 62716612Ssam addr = usignal(process); 62816612Ssam if (addr == 0 or addr == 1) { 62916612Ssam addr = findnextaddr(startaddr, isnext); 63016612Ssam } 63116612Ssam return addr; 63216612Ssam } 63316612Ssam 63416612Ssam private Address findnextaddr(startaddr, isnext) 63516612Ssam Address startaddr; 6369668Slinton Boolean isnext; 6379668Slinton { 6389668Slinton register Address addr; 6399668Slinton Optab op; 6409668Slinton VaxOpcode ins; 6419668Slinton unsigned char mode; 6429668Slinton int argtype, amode, argno, argval; 6439668Slinton String r; 6449668Slinton Boolean indexf; 6459668Slinton enum { KNOWN, SEQUENTIAL, BRANCH } addrstatus; 6469668Slinton 6479668Slinton argval = 0; 6489668Slinton indexf = false; 6499668Slinton addr = startaddr; 6509668Slinton iread(&ins, addr, sizeof(ins)); 6519668Slinton switch (ins) { 6529668Slinton case O_BRB: 6539668Slinton case O_BRW: 6549668Slinton addrstatus = BRANCH; 6559668Slinton break; 6569668Slinton 6579668Slinton case O_BSBB: 6589668Slinton case O_BSBW: 6599668Slinton case O_JSB: 6609668Slinton case O_CALLG: 6619668Slinton case O_CALLS: 6629668Slinton if (isnext) { 6639668Slinton addrstatus = SEQUENTIAL; 6649668Slinton } else { 6659668Slinton addrstatus = KNOWN; 6669668Slinton stepto(addr); 66716612Ssam pstep(process, DEFSIG); 6689668Slinton addr = reg(PROGCTR); 6699668Slinton pc = addr; 67016612Ssam setcurfunc(whatblock(pc)); 6719668Slinton if (not isbperr()) { 6729668Slinton printstatus(); 67311864Slinton /* NOTREACHED */ 67411864Slinton } 67511864Slinton bpact(); 67611864Slinton if (nosource(curfunc) and canskip(curfunc) and 67711864Slinton nlhdr.nlines != 0) { 67811864Slinton addrstatus = KNOWN; 67911864Slinton addr = return_addr(); 68011864Slinton stepto(addr); 68111874Slinton bpact(); 6829668Slinton } else { 68311864Slinton callnews(/* iscall = */ true); 6849668Slinton } 6859668Slinton } 6869668Slinton break; 6879668Slinton 6889668Slinton case O_RSB: 6899668Slinton case O_RET: 6909668Slinton addrstatus = KNOWN; 6919668Slinton callnews(/* iscall = */ false); 6929668Slinton addr = return_addr(); 69316612Ssam if (addr == pc) { /* recursive ret to self */ 69416612Ssam pstep(process, DEFSIG); 69516612Ssam } else { 69616612Ssam stepto(addr); 69716612Ssam } 69811874Slinton bpact(); 6999668Slinton break; 7009668Slinton 70116612Ssam case O_JMP: /* because it may be jmp (r1) */ 7029668Slinton case O_BNEQ: case O_BEQL: case O_BGTR: 7039668Slinton case O_BLEQ: case O_BGEQ: case O_BLSS: 7049668Slinton case O_BGTRU: case O_BLEQU: case O_BVC: 7059668Slinton case O_BVS: case O_BCC: case O_BCS: 7069668Slinton case O_CASEB: case O_CASEW: case O_CASEL: 7079668Slinton case O_BBS: case O_BBC: case O_BBSS: case O_BBCS: 7089668Slinton case O_BBSC: case O_BBCC: case O_BBSSI: 7099668Slinton case O_BBCCI: case O_BLBS: case O_BLBC: 7109668Slinton case O_ACBL: case O_AOBLSS: case O_AOBLEQ: 7119668Slinton case O_SOBGEQ: case O_SOBGTR: 7129668Slinton addrstatus = KNOWN; 7139668Slinton stepto(addr); 71416612Ssam pstep(process, DEFSIG); 7159668Slinton addr = reg(PROGCTR); 7169668Slinton pc = addr; 7179668Slinton if (not isbperr()) { 7189668Slinton printstatus(); 7199668Slinton } 7209668Slinton break; 7219668Slinton 7229668Slinton default: 7239668Slinton addrstatus = SEQUENTIAL; 7249668Slinton break; 7259668Slinton } 7269668Slinton if (addrstatus != KNOWN) { 7279668Slinton addr += 1; 7289668Slinton op = optab[ins]; 7299668Slinton for (argno = 0; argno < op.numargs; argno++) { 7309668Slinton if (indexf == true) { 7319668Slinton indexf = false; 7329668Slinton } 7339668Slinton argtype = op.argtype[argno]; 7349668Slinton if (is_branch_disp(argtype)) { 7359668Slinton mode = 0xAF + (typelen(argtype) << 5); 7369668Slinton } else { 7379668Slinton iread(&mode, addr, sizeof(mode)); 7389668Slinton addr += 1; 7399668Slinton } 7409668Slinton r = regname[regnm(mode)]; 7419668Slinton amode = addrmode(mode); 7429668Slinton switch (amode) { 7439668Slinton case LITSHORT: 7449668Slinton case LITUPTO31: 7459668Slinton case LITUPTO47: 7469668Slinton case LITUPTO63: 7479668Slinton argval = mode; 7489668Slinton break; 7499668Slinton 7509668Slinton case INDEX: 7519668Slinton indexf = true; 7529668Slinton --argno; 7539668Slinton break; 7549668Slinton 7559668Slinton case REG: 7569668Slinton case REGDEF: 7579668Slinton case AUTODEC: 7589668Slinton break; 7599668Slinton 7609668Slinton case AUTOINC: 7619668Slinton if (r == regname[PROGCTR]) { 7629668Slinton switch (typelen(argtype)) { 7639668Slinton case TYPB: 7649668Slinton argval = getdisp(addr, 1, r, amode); 7659668Slinton addr += 1; 7669668Slinton break; 7679668Slinton 7689668Slinton case TYPW: 7699668Slinton argval = getdisp(addr, 2, r, amode); 7709668Slinton addr += 2; 7719668Slinton break; 7729668Slinton 7739668Slinton case TYPL: 7749668Slinton argval = getdisp(addr, 4, r, amode); 7759668Slinton addr += 4; 7769668Slinton break; 7779668Slinton 7789668Slinton case TYPF: 7799668Slinton iread(&argval, addr, sizeof(argval)); 7809668Slinton addr += 4; 7819668Slinton break; 7829668Slinton 7839668Slinton case TYPQ: 7849668Slinton case TYPD: 7859668Slinton iread(&argval, addr+4, sizeof(argval)); 7869668Slinton addr += 8; 7879668Slinton break; 7889668Slinton } 7899668Slinton } 7909668Slinton break; 7919668Slinton 7929668Slinton case AUTOINCDEF: 7939668Slinton if (r == regname[PROGCTR]) { 7949668Slinton argval = getdisp(addr, 4, r, amode); 7959668Slinton addr += 4; 7969668Slinton } 7979668Slinton break; 7989668Slinton 7999668Slinton case BYTEDISP: 8009668Slinton case BYTEDISPDEF: 8019668Slinton argval = getdisp(addr, 1, r, amode); 8029668Slinton addr += 1; 8039668Slinton break; 8049668Slinton 8059668Slinton case WORDDISP: 8069668Slinton case WORDDISPDEF: 8079668Slinton argval = getdisp(addr, 2, r, amode); 8089668Slinton addr += 2; 8099668Slinton break; 8109668Slinton 8119668Slinton case LONGDISP: 8129668Slinton case LONGDISPDEF: 8139668Slinton argval = getdisp(addr, 4, r, amode); 8149668Slinton addr += 4; 8159668Slinton break; 8169668Slinton } 8179668Slinton } 8189668Slinton if (ins == O_CALLS or ins == O_CALLG) { 8199668Slinton argval += 2; 8209668Slinton } 8219668Slinton if (addrstatus == BRANCH) { 8229668Slinton addr = argval; 8239668Slinton } 8249668Slinton } 8259668Slinton return addr; 8269668Slinton } 8279668Slinton 8289668Slinton /* 8299668Slinton * Get the displacement of an instruction that uses displacement addressing. 8309668Slinton */ 8319668Slinton 8329668Slinton private int getdisp(addr, nbytes, reg, mode) 8339668Slinton Address addr; 8349668Slinton int nbytes; 8359668Slinton String reg; 8369668Slinton int mode; 8379668Slinton { 8389668Slinton char byte; 8399668Slinton short hword; 8409668Slinton int argval; 8419668Slinton 8429668Slinton switch (nbytes) { 8439668Slinton case 1: 8449668Slinton iread(&byte, addr, sizeof(byte)); 8459668Slinton argval = byte; 8469668Slinton break; 8479668Slinton 8489668Slinton case 2: 8499668Slinton iread(&hword, addr, sizeof(hword)); 8509668Slinton argval = hword; 8519668Slinton break; 8529668Slinton 8539668Slinton case 4: 8549668Slinton iread(&argval, addr, sizeof(argval)); 8559668Slinton break; 8569668Slinton } 8579668Slinton if (reg == regname[PROGCTR] && mode >= BYTEDISP) { 8589668Slinton argval += addr + nbytes; 8599668Slinton } 8609668Slinton return argval; 8619668Slinton } 8629668Slinton 8639668Slinton #define BP_OP O_BPT /* breakpoint trap */ 8649668Slinton #define BP_ERRNO SIGTRAP /* signal received at a breakpoint */ 8659668Slinton 8669668Slinton /* 8679668Slinton * Setting a breakpoint at a location consists of saving 8689668Slinton * the word at the location and poking a BP_OP there. 8699668Slinton * 8709668Slinton * We save the locations and words on a list for use in unsetting. 8719668Slinton */ 8729668Slinton 8739668Slinton typedef struct Savelist *Savelist; 8749668Slinton 8759668Slinton struct Savelist { 8769668Slinton Address location; 8779668Slinton Byte save; 8789668Slinton Byte refcount; 8799668Slinton Savelist link; 8809668Slinton }; 8819668Slinton 8829668Slinton private Savelist savelist; 8839668Slinton 8849668Slinton /* 8859668Slinton * Set a breakpoint at the given address. Only save the word there 8869668Slinton * if it's not already a breakpoint. 8879668Slinton */ 8889668Slinton 8899668Slinton public setbp(addr) 8909668Slinton Address addr; 8919668Slinton { 8929668Slinton Byte w; 8939668Slinton Byte save; 8949668Slinton register Savelist newsave, s; 8959668Slinton 8969668Slinton for (s = savelist; s != nil; s = s->link) { 8979668Slinton if (s->location == addr) { 8989668Slinton s->refcount++; 8999668Slinton return; 9009668Slinton } 9019668Slinton } 90211174Slinton iread(&save, addr, sizeof(save)); 9039668Slinton newsave = new(Savelist); 9049668Slinton newsave->location = addr; 9059668Slinton newsave->save = save; 9069668Slinton newsave->refcount = 1; 9079668Slinton newsave->link = savelist; 9089668Slinton savelist = newsave; 9099668Slinton w = BP_OP; 9109668Slinton iwrite(&w, addr, sizeof(w)); 9119668Slinton } 9129668Slinton 9139668Slinton /* 9149668Slinton * Unset a breakpoint; unfortunately we have to search the SAVELIST 9159668Slinton * to find the saved value. The assumption is that the SAVELIST will 9169668Slinton * usually be quite small. 9179668Slinton */ 9189668Slinton 9199668Slinton public unsetbp(addr) 9209668Slinton Address addr; 9219668Slinton { 9229668Slinton register Savelist s, prev; 9239668Slinton 9249668Slinton prev = nil; 9259668Slinton for (s = savelist; s != nil; s = s->link) { 9269668Slinton if (s->location == addr) { 9279668Slinton iwrite(&s->save, addr, sizeof(s->save)); 9289668Slinton s->refcount--; 9299668Slinton if (s->refcount == 0) { 9309668Slinton if (prev == nil) { 9319668Slinton savelist = s->link; 9329668Slinton } else { 9339668Slinton prev->link = s->link; 9349668Slinton } 9359668Slinton dispose(s); 9369668Slinton } 9379668Slinton return; 9389668Slinton } 9399668Slinton prev = s; 9409668Slinton } 9419668Slinton panic("unsetbp: couldn't find address %d", addr); 9429668Slinton } 9439668Slinton 9449668Slinton /* 9459668Slinton * Predicate to test if the reason the process stopped was because 9469668Slinton * of a breakpoint. 9479668Slinton */ 9489668Slinton 9499668Slinton public Boolean isbperr() 9509668Slinton { 9519668Slinton return (Boolean) (not isfinished(process) and errnum(process) == SIGTRAP); 9529668Slinton } 9539668Slinton 9549668Slinton /* 9559668Slinton * Enter a procedure by creating and executing a call instruction. 9569668Slinton */ 9579668Slinton 9589668Slinton #define CALLSIZE 7 /* size of call instruction */ 9599668Slinton 9609668Slinton public beginproc(p, argc) 9619668Slinton Symbol p; 9629668Slinton Integer argc; 9639668Slinton { 9649668Slinton char save[CALLSIZE]; 9659668Slinton struct { 9669668Slinton VaxOpcode op; 9679668Slinton unsigned char numargs; 9689668Slinton unsigned char mode; 9699668Slinton char addr[sizeof(long)]; /* unaligned long */ 9709668Slinton } call; 9719668Slinton long dest; 9729668Slinton 9739668Slinton pc = 2; 9749668Slinton iread(save, pc, sizeof(save)); 9759668Slinton call.op = O_CALLS; 9769668Slinton call.numargs = argc; 9779668Slinton call.mode = 0xef; 9789668Slinton dest = codeloc(p) - 2 - (pc + 7); 9799668Slinton mov(&dest, call.addr, sizeof(call.addr)); 9809668Slinton iwrite(&call, pc, sizeof(call)); 9819668Slinton setreg(PROGCTR, pc); 98216612Ssam pstep(process, DEFSIG); 9839668Slinton iwrite(save, pc, sizeof(save)); 9849668Slinton pc = reg(PROGCTR); 9859668Slinton if (not isbperr()) { 9869668Slinton printstatus(); 9879668Slinton } 9889668Slinton } 989