19668Slinton /* Copyright (c) 1982 Regents of the University of California */ 29668Slinton 3*16612Ssam static char sccsid[] = "@(#)machine.c 1.9 8/5/83"; 49668Slinton 5*16612Ssam static char rcsid[] = "$Header: machine.c,v 1.3 84/03/27 10:21:26 linton Exp $"; 6*16612Ssam 79668Slinton /* 89668Slinton * Target machine dependent stuff. 99668Slinton */ 109668Slinton 119668Slinton #include "defs.h" 129668Slinton #include "machine.h" 139668Slinton #include "process.h" 14*16612Ssam #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" 219693Slinton #include "ops.h" 229668Slinton #include <signal.h> 239668Slinton 249668Slinton #ifndef public 259668Slinton typedef unsigned int Address; 269668Slinton typedef unsigned char Byte; 279668Slinton typedef unsigned int Word; 289668Slinton 299668Slinton #define NREG 16 309668Slinton 319668Slinton #define ARGP 12 329668Slinton #define FRP 13 339668Slinton #define STKP 14 349668Slinton #define PROGCTR 15 359668Slinton 369668Slinton #define BITSPERBYTE 8 379668Slinton #define BITSPERWORD (BITSPERBYTE * sizeof(Word)) 389668Slinton 399668Slinton #define nargspassed(frame) argn(0, frame) 409668Slinton 419668Slinton #include "source.h" 429668Slinton #include "symbols.h" 439668Slinton 449668Slinton Address pc; 459668Slinton Address prtaddr; 469668Slinton 479668Slinton #endif 489668Slinton 499668Slinton private Address printop(); 509668Slinton 519668Slinton /* 529668Slinton * Decode and print the instructions within the given address range. 539668Slinton */ 549668Slinton 559668Slinton public printinst(lowaddr, highaddr) 569668Slinton Address lowaddr; 579668Slinton Address highaddr; 589668Slinton { 599668Slinton register Address addr; 609668Slinton 619668Slinton for (addr = lowaddr; addr <= highaddr; ) { 629668Slinton addr = printop(addr); 639668Slinton } 649668Slinton prtaddr = addr; 659668Slinton } 669668Slinton 679668Slinton /* 689668Slinton * Another approach: print n instructions starting at the given address. 699668Slinton */ 709668Slinton 719668Slinton public printninst(count, addr) 729668Slinton int count; 739668Slinton Address addr; 749668Slinton { 759668Slinton register Integer i; 769668Slinton register Address newaddr; 779668Slinton 789668Slinton if (count <= 0) { 799668Slinton error("non-positive repetition count"); 809668Slinton } else { 819668Slinton newaddr = addr; 829668Slinton for (i = 0; i < count; i++) { 839668Slinton newaddr = printop(newaddr); 849668Slinton } 859668Slinton prtaddr = newaddr; 869668Slinton } 879668Slinton } 889668Slinton 899668Slinton /* 909668Slinton * Hacked version of adb's VAX instruction decoder. 919668Slinton */ 929668Slinton 939668Slinton private Address printop(addr) 949668Slinton Address addr; 959668Slinton { 969668Slinton Optab op; 979668Slinton VaxOpcode ins; 989668Slinton unsigned char mode; 999668Slinton int argtype, amode, argno, argval; 1009668Slinton String reg; 1019668Slinton Boolean indexf; 1029668Slinton short offset; 1039668Slinton 1049668Slinton argval = 0; 1059668Slinton indexf = false; 1069668Slinton printf("%08x ", addr); 1079668Slinton iread(&ins, addr, sizeof(ins)); 1089668Slinton addr += 1; 1099668Slinton op = optab[ins]; 1109668Slinton printf("%s", op.iname); 1119668Slinton for (argno = 0; argno < op.numargs; argno++) { 1129668Slinton if (indexf == true) { 1139668Slinton indexf = false; 1149668Slinton } else if (argno == 0) { 1159668Slinton printf("\t"); 1169668Slinton } else { 1179668Slinton printf(","); 1189668Slinton } 1199668Slinton argtype = op.argtype[argno]; 1209668Slinton if (is_branch_disp(argtype)) { 1219668Slinton mode = 0xAF + (typelen(argtype) << 5); 1229668Slinton } else { 1239668Slinton iread(&mode, addr, sizeof(mode)); 1249668Slinton addr += 1; 1259668Slinton } 1269668Slinton reg = regname[regnm(mode)]; 1279668Slinton amode = addrmode(mode); 1289668Slinton switch (amode) { 1299668Slinton case LITSHORT: 1309668Slinton case LITUPTO31: 1319668Slinton case LITUPTO47: 1329668Slinton case LITUPTO63: 1339668Slinton if (typelen(argtype) == TYPF || typelen(argtype) ==TYPD) 1349668Slinton printf("$%s", fltimm[mode]); 1359668Slinton else 1369668Slinton printf("$%x", mode); 1379668Slinton argval = mode; 1389668Slinton break; 1399668Slinton 1409668Slinton case INDEX: 1419668Slinton printf("[%s]", reg); 1429668Slinton indexf = true; 1439668Slinton argno--; 1449668Slinton break; 1459668Slinton 1469668Slinton case REG: 1479668Slinton printf("%s", reg); 1489668Slinton break; 1499668Slinton 1509668Slinton case REGDEF: 1519668Slinton printf("(%s)", reg); 1529668Slinton break; 1539668Slinton 1549668Slinton case AUTODEC: 1559668Slinton printf("-(%s)", reg); 1569668Slinton break; 1579668Slinton 1589668Slinton case AUTOINC: 1599668Slinton if (reg != regname[PROGCTR]) { 1609668Slinton printf("(%s)+", reg); 1619668Slinton } else { 1629668Slinton printf("$"); 1639668Slinton switch (typelen(argtype)) { 1649668Slinton case TYPB: 1659668Slinton argval = printdisp(addr, 1, reg, amode); 1669668Slinton addr += 1; 1679668Slinton break; 1689668Slinton 1699668Slinton case TYPW: 1709668Slinton argval = printdisp(addr, 2, reg, amode); 1719668Slinton addr += 2; 1729668Slinton break; 1739668Slinton 1749668Slinton case TYPL: 1759668Slinton argval = printdisp(addr, 4, reg, amode); 1769668Slinton addr += 4; 1779668Slinton break; 1789668Slinton 1799668Slinton case TYPF: 1809668Slinton iread(&argval, addr, sizeof(argval)); 1819668Slinton printf("%06x", argval); 1829668Slinton addr += 4; 1839668Slinton break; 1849668Slinton 1859668Slinton case TYPQ: 1869668Slinton case TYPD: 1879668Slinton iread(&argval, addr, sizeof(argval)); 1889668Slinton printf("%06x", argval); 1899668Slinton iread(&argval, addr+4, sizeof(argval)); 1909668Slinton printf("%06x", argval); 1919668Slinton addr += 8; 1929668Slinton break; 1939668Slinton } 1949668Slinton } 1959668Slinton break; 1969668Slinton 1979668Slinton case AUTOINCDEF: 1989668Slinton if (reg == regname[PROGCTR]) { 1999668Slinton printf("*$"); 2009668Slinton argval = printdisp(addr, 4, reg, amode); 2019668Slinton addr += 4; 2029668Slinton } else { 2039668Slinton printf("*(%s)+", reg); 2049668Slinton } 2059668Slinton break; 2069668Slinton 2079668Slinton case BYTEDISP: 2089668Slinton argval = printdisp(addr, 1, reg, amode); 2099668Slinton addr += 1; 2109668Slinton break; 2119668Slinton 2129668Slinton case BYTEDISPDEF: 2139668Slinton printf("*"); 2149668Slinton argval = printdisp(addr, 1, reg, amode); 2159668Slinton addr += 1; 2169668Slinton break; 2179668Slinton 2189668Slinton case WORDDISP: 2199668Slinton argval = printdisp(addr, 2, reg, amode); 2209668Slinton addr += 2; 2219668Slinton break; 2229668Slinton 2239668Slinton case WORDDISPDEF: 2249668Slinton printf("*"); 2259668Slinton argval = printdisp(addr, 2, reg, amode); 2269668Slinton addr += 2; 2279668Slinton break; 2289668Slinton 2299668Slinton case LONGDISP: 2309668Slinton argval = printdisp(addr, 4, reg, amode); 2319668Slinton addr += 4; 2329668Slinton break; 2339668Slinton 2349668Slinton case LONGDISPDEF: 2359668Slinton printf("*"); 2369668Slinton argval = printdisp(addr, 4, reg, amode); 2379668Slinton addr += 4; 2389668Slinton break; 2399668Slinton } 2409668Slinton } 2419668Slinton if (ins == O_CASEB || ins == O_CASEW || ins == O_CASEL) { 2429668Slinton for (argno = 0; argno <= argval; argno++) { 2439668Slinton iread(&offset, addr, sizeof(offset)); 2449668Slinton printf("\n\t\t%d", offset); 2459668Slinton addr += 2; 2469668Slinton } 2479668Slinton } 2489668Slinton printf("\n"); 2499668Slinton return addr; 2509668Slinton } 2519668Slinton 2529668Slinton /* 2539668Slinton * Print the displacement of an instruction that uses displacement 2549668Slinton * addressing. 2559668Slinton */ 2569668Slinton 2579668Slinton private int printdisp(addr, nbytes, reg, mode) 2589668Slinton Address addr; 2599668Slinton int nbytes; 2609668Slinton char *reg; 2619668Slinton int mode; 2629668Slinton { 2639668Slinton char byte; 2649668Slinton short hword; 2659668Slinton int argval; 26614338Slinton Symbol f; 2679668Slinton 2689668Slinton switch (nbytes) { 2699668Slinton case 1: 2709668Slinton iread(&byte, addr, sizeof(byte)); 2719668Slinton argval = byte; 2729668Slinton break; 2739668Slinton 2749668Slinton case 2: 2759668Slinton iread(&hword, addr, sizeof(hword)); 2769668Slinton argval = hword; 2779668Slinton break; 2789668Slinton 2799668Slinton case 4: 2809668Slinton iread(&argval, addr, sizeof(argval)); 2819668Slinton break; 2829668Slinton } 2839668Slinton if (reg == regname[PROGCTR] && mode >= BYTEDISP) { 2849668Slinton argval += addr + nbytes; 2859668Slinton } 2869668Slinton if (reg == regname[PROGCTR]) { 28714338Slinton f = whatblock((Address) argval + 2); 28814338Slinton if (codeloc(f) == argval + 2) { 28914338Slinton printf("%s", symname(f)); 29014338Slinton } else { 29114338Slinton printf("%x", argval); 29214338Slinton } 2939668Slinton } else { 2949668Slinton printf("%d(%s)", argval, reg); 2959668Slinton } 2969668Slinton return argval; 2979668Slinton } 2989668Slinton 2999668Slinton /* 3009668Slinton * Print the contents of the addresses within the given range 3019668Slinton * according to the given format. 3029668Slinton */ 3039668Slinton 3049668Slinton typedef struct { 3059668Slinton String name; 3069668Slinton String printfstring; 3079668Slinton int length; 3089668Slinton } Format; 3099668Slinton 3109668Slinton private Format fmt[] = { 3119668Slinton { "d", " %d", sizeof(short) }, 3129668Slinton { "D", " %ld", sizeof(long) }, 3139668Slinton { "o", " %o", sizeof(short) }, 3149668Slinton { "O", " %lo", sizeof(long) }, 3159668Slinton { "x", " %04x", sizeof(short) }, 3169668Slinton { "X", " %08x", sizeof(long) }, 3179668Slinton { "b", " \\%o", sizeof(char) }, 3189668Slinton { "c", " '%c'", sizeof(char) }, 3199668Slinton { "s", "%c", sizeof(char) }, 32014338Slinton { "f", " %f", sizeof(float) }, 3219668Slinton { "g", " %g", sizeof(double) }, 3229668Slinton { nil, nil, 0 } 3239668Slinton }; 3249668Slinton 32511174Slinton private Format *findformat(s) 32611174Slinton String s; 32711174Slinton { 32811174Slinton register Format *f; 32911174Slinton 33011174Slinton f = &fmt[0]; 33111174Slinton while (f->name != nil and not streq(f->name, s)) { 33211174Slinton ++f; 33311174Slinton } 33411174Slinton if (f->name == nil) { 33511174Slinton error("bad print format \"%s\"", s); 33611174Slinton } 33711174Slinton return f; 33811174Slinton } 33911174Slinton 3409668Slinton public Address printdata(lowaddr, highaddr, format) 3419668Slinton Address lowaddr; 3429668Slinton Address highaddr; 3439668Slinton String format; 3449668Slinton { 3459668Slinton register int n; 3469668Slinton register Address addr; 3479668Slinton register Format *f; 3489668Slinton int value; 3499668Slinton 3509668Slinton if (lowaddr > highaddr) { 3519668Slinton error("first address larger than second"); 3529668Slinton } 35311174Slinton f = findformat(format); 3549668Slinton n = 0; 3559668Slinton value = 0; 3569668Slinton for (addr = lowaddr; addr <= highaddr; addr += f->length) { 3579668Slinton if (n == 0) { 3589668Slinton printf("%08x: ", addr); 3599668Slinton } 3609668Slinton dread(&value, addr, f->length); 3619668Slinton printf(f->printfstring, value); 3629668Slinton ++n; 3639668Slinton if (n >= (16 div f->length)) { 3649668Slinton putchar('\n'); 3659668Slinton n = 0; 3669668Slinton } 3679668Slinton } 3689668Slinton if (n != 0) { 3699668Slinton putchar('\n'); 3709668Slinton } 3719668Slinton prtaddr = addr; 3729668Slinton return addr; 3739668Slinton } 3749668Slinton 3759668Slinton /* 3769668Slinton * The other approach is to print n items starting with a given address. 3779668Slinton */ 3789668Slinton 3799668Slinton public printndata(count, startaddr, format) 3809668Slinton int count; 3819668Slinton Address startaddr; 3829668Slinton String format; 3839668Slinton { 3849668Slinton register int i, n; 3859668Slinton register Address addr; 3869668Slinton register Format *f; 3879668Slinton register Boolean isstring; 38814338Slinton char c; 38914338Slinton union { 39014338Slinton char charv; 39114338Slinton short shortv; 39214338Slinton int intv; 39314338Slinton float floatv; 39414338Slinton double doublev; 39514338Slinton } value; 3969668Slinton 3979668Slinton if (count <= 0) { 3989668Slinton error("non-positive repetition count"); 3999668Slinton } 40011174Slinton f = findformat(format); 4019668Slinton isstring = (Boolean) streq(f->name, "s"); 4029668Slinton n = 0; 4039668Slinton addr = startaddr; 40414338Slinton value.intv = 0; 4059668Slinton for (i = 0; i < count; i++) { 4069668Slinton if (n == 0) { 4079668Slinton printf("%08x: ", addr); 4089668Slinton } 4099668Slinton if (isstring) { 4109668Slinton putchar('"'); 41114338Slinton dread(&c, addr, sizeof(char)); 41214338Slinton while (c != '\0') { 41314338Slinton printchar(c); 4149668Slinton ++addr; 41514338Slinton dread(&c, addr, sizeof(char)); 4169668Slinton } 4179668Slinton putchar('"'); 4189668Slinton putchar('\n'); 4199668Slinton n = 0; 4209668Slinton addr += sizeof(String); 4219668Slinton } else { 4229668Slinton dread(&value, addr, f->length); 4239668Slinton printf(f->printfstring, value); 4249668Slinton ++n; 4259668Slinton if (n >= (16 div f->length)) { 4269668Slinton putchar('\n'); 4279668Slinton n = 0; 4289668Slinton } 4299668Slinton addr += f->length; 4309668Slinton } 4319668Slinton } 4329668Slinton if (n != 0) { 4339668Slinton putchar('\n'); 4349668Slinton } 4359668Slinton prtaddr = addr; 4369668Slinton } 4379668Slinton 4389668Slinton /* 43911174Slinton * Print out a value according to the given format. 44011174Slinton */ 44111174Slinton 44211174Slinton public printvalue(v, format) 44311174Slinton long v; 44411174Slinton String format; 44511174Slinton { 44611174Slinton Format *f; 44711174Slinton char *p, *q; 44811174Slinton 44911174Slinton f = findformat(format); 45011174Slinton if (streq(f->name, "s")) { 45111174Slinton putchar('"'); 45211174Slinton p = (char *) &v; 45311174Slinton q = p + sizeof(v); 45411174Slinton while (p < q) { 45511174Slinton printchar(*p); 45611174Slinton ++p; 45711174Slinton } 45811174Slinton putchar('"'); 45911174Slinton } else { 46011174Slinton printf(f->printfstring, v); 46111174Slinton } 46211174Slinton putchar('\n'); 46311174Slinton } 46411174Slinton 46511174Slinton /* 4669668Slinton * Print out an execution time error. 4679842Slinton * Assumes the source position of the error has been calculated. 4689668Slinton * 4699668Slinton * Have to check if the -r option was specified; if so then 4709668Slinton * the object file information hasn't been read in yet. 4719668Slinton */ 4729668Slinton 4739668Slinton public printerror() 4749668Slinton { 4759668Slinton extern Integer sys_nsig; 4769668Slinton extern String sys_siglist[]; 4779668Slinton Integer err; 4789668Slinton 4799668Slinton if (isfinished(process)) { 4809668Slinton printf("\"%s\" exits with code %d\n", objname, exitcode(process)); 4819668Slinton erecover(); 4829668Slinton } 4839668Slinton if (runfirst) { 4849668Slinton fprintf(stderr, "Entering debugger ..."); 4859668Slinton init(); 4869668Slinton fprintf(stderr, " type 'help' for help\n"); 4879668Slinton } 4889668Slinton err = errnum(process); 4899668Slinton if (err == SIGINT) { 4909668Slinton printf("\n\ninterrupt "); 4919668Slinton printloc(); 4929668Slinton } else if (err == SIGTRAP) { 4939668Slinton printf("\nerror "); 4949668Slinton printloc(); 4959668Slinton } else { 4969668Slinton if (err < 0 or err > sys_nsig) { 4979668Slinton printf("\nsignal %d ", err); 4989668Slinton } else { 4999668Slinton printf("\n%s ", sys_siglist[err]); 5009668Slinton } 5019668Slinton printloc(); 5029668Slinton } 5039668Slinton putchar('\n'); 5049668Slinton if (curline > 0) { 5059668Slinton printlines(curline, curline); 5069668Slinton } else { 5079668Slinton printinst(pc, pc); 5089668Slinton } 5099668Slinton erecover(); 5109668Slinton } 5119668Slinton 5129668Slinton /* 5139668Slinton * Note the termination of the program. We do this so as to avoid 5149668Slinton * having the process exit, which would make the values of variables 5159668Slinton * inaccessible. We do want to flush all output buffers here, 5169668Slinton * otherwise it'll never get done. 5179668Slinton */ 5189668Slinton 5199668Slinton public endprogram() 5209668Slinton { 5219668Slinton Integer exitcode; 5229668Slinton 5239668Slinton stepto(nextaddr(pc, true)); 5249668Slinton printnews(); 5259668Slinton exitcode = argn(1, nil); 5269668Slinton printf("\nexecution completed, exit code is %d\n", exitcode); 5279668Slinton getsrcpos(); 5289668Slinton erecover(); 5299668Slinton } 5309668Slinton 5319668Slinton /* 5329668Slinton * Single step the machine a source line (or instruction if "inst_tracing" 53310621Slinton * is true). If "isnext" is true, skip over procedure calls. 5349668Slinton */ 5359668Slinton 5369668Slinton private Address getcall(); 5379668Slinton 5389668Slinton public dostep(isnext) 5399668Slinton Boolean isnext; 5409668Slinton { 5419668Slinton register Address addr; 5429668Slinton register Lineno line; 5439668Slinton String filename; 544*16612Ssam Address startaddr, prevaddr; 5459668Slinton 546*16612Ssam startaddr = pc; 547*16612Ssam prevaddr = startaddr; 5489668Slinton addr = nextaddr(pc, isnext); 54910621Slinton if (not inst_tracing and nlhdr.nlines != 0) { 5509668Slinton line = linelookup(addr); 5519668Slinton while (line == 0) { 552*16612Ssam prevaddr = addr; 5539668Slinton addr = nextaddr(addr, isnext); 5549668Slinton line = linelookup(addr); 5559668Slinton } 55610621Slinton curline = line; 55710621Slinton } else { 55810621Slinton curline = 0; 5599668Slinton } 560*16612Ssam if (addr == startaddr) { 561*16612Ssam stepto(prevaddr); 562*16612Ssam } 5639668Slinton stepto(addr); 5649668Slinton filename = srcfilename(addr); 5659668Slinton setsource(filename); 5669668Slinton } 5679668Slinton 5689668Slinton /* 5699668Slinton * Compute the next address that will be executed from the given one. 5709668Slinton * If "isnext" is true then consider a procedure call as straight line code. 5719668Slinton * 5729668Slinton * We must unfortunately do much of the same work that is necessary 5739668Slinton * to print instructions. In addition we have to deal with branches. 5749668Slinton * Unconditional branches we just follow, for conditional branches 5759668Slinton * we continue execution to the current location and then single step 5769668Slinton * the machine. We assume that the last argument in an instruction 5779668Slinton * that branches is the branch address (or relative offset). 5789668Slinton */ 5799668Slinton 580*16612Ssam private Address findnextaddr(); 581*16612Ssam 5829668Slinton public Address nextaddr(startaddr, isnext) 5839668Slinton Address startaddr; 584*16612Ssam boolean isnext; 585*16612Ssam { 586*16612Ssam Address addr; 587*16612Ssam 588*16612Ssam addr = usignal(process); 589*16612Ssam if (addr == 0 or addr == 1) { 590*16612Ssam addr = findnextaddr(startaddr, isnext); 591*16612Ssam } 592*16612Ssam return addr; 593*16612Ssam } 594*16612Ssam 595*16612Ssam private Address findnextaddr(startaddr, isnext) 596*16612Ssam Address startaddr; 5979668Slinton Boolean isnext; 5989668Slinton { 5999668Slinton register Address addr; 6009668Slinton Optab op; 6019668Slinton VaxOpcode ins; 6029668Slinton unsigned char mode; 6039668Slinton int argtype, amode, argno, argval; 6049668Slinton String r; 6059668Slinton Boolean indexf; 6069668Slinton enum { KNOWN, SEQUENTIAL, BRANCH } addrstatus; 6079668Slinton 6089668Slinton argval = 0; 6099668Slinton indexf = false; 6109668Slinton addr = startaddr; 6119668Slinton iread(&ins, addr, sizeof(ins)); 6129668Slinton switch (ins) { 6139668Slinton case O_BRB: 6149668Slinton case O_BRW: 6159668Slinton addrstatus = BRANCH; 6169668Slinton break; 6179668Slinton 6189668Slinton case O_BSBB: 6199668Slinton case O_BSBW: 6209668Slinton case O_JSB: 6219668Slinton case O_CALLG: 6229668Slinton case O_CALLS: 6239668Slinton if (isnext) { 6249668Slinton addrstatus = SEQUENTIAL; 6259668Slinton } else { 6269668Slinton addrstatus = KNOWN; 6279668Slinton stepto(addr); 628*16612Ssam pstep(process, DEFSIG); 6299668Slinton addr = reg(PROGCTR); 6309668Slinton pc = addr; 631*16612Ssam setcurfunc(whatblock(pc)); 6329668Slinton if (not isbperr()) { 6339668Slinton printstatus(); 63411864Slinton /* NOTREACHED */ 63511864Slinton } 63611864Slinton bpact(); 63711864Slinton if (nosource(curfunc) and canskip(curfunc) and 63811864Slinton nlhdr.nlines != 0) { 63911864Slinton addrstatus = KNOWN; 64011864Slinton addr = return_addr(); 64111864Slinton stepto(addr); 64211874Slinton bpact(); 6439668Slinton } else { 64411864Slinton callnews(/* iscall = */ true); 6459668Slinton } 6469668Slinton } 6479668Slinton break; 6489668Slinton 6499668Slinton case O_RSB: 6509668Slinton case O_RET: 6519668Slinton addrstatus = KNOWN; 6529668Slinton callnews(/* iscall = */ false); 6539668Slinton addr = return_addr(); 654*16612Ssam if (addr == pc) { /* recursive ret to self */ 655*16612Ssam pstep(process, DEFSIG); 656*16612Ssam } else { 657*16612Ssam stepto(addr); 658*16612Ssam } 65911874Slinton bpact(); 6609668Slinton break; 6619668Slinton 662*16612Ssam case O_JMP: /* because it may be jmp (r1) */ 6639668Slinton case O_BNEQ: case O_BEQL: case O_BGTR: 6649668Slinton case O_BLEQ: case O_BGEQ: case O_BLSS: 6659668Slinton case O_BGTRU: case O_BLEQU: case O_BVC: 6669668Slinton case O_BVS: case O_BCC: case O_BCS: 6679668Slinton case O_CASEB: case O_CASEW: case O_CASEL: 6689668Slinton case O_BBS: case O_BBC: case O_BBSS: case O_BBCS: 6699668Slinton case O_BBSC: case O_BBCC: case O_BBSSI: 6709668Slinton case O_BBCCI: case O_BLBS: case O_BLBC: 6719668Slinton case O_ACBL: case O_AOBLSS: case O_AOBLEQ: 6729668Slinton case O_SOBGEQ: case O_SOBGTR: 6739668Slinton addrstatus = KNOWN; 6749668Slinton stepto(addr); 675*16612Ssam pstep(process, DEFSIG); 6769668Slinton addr = reg(PROGCTR); 6779668Slinton pc = addr; 6789668Slinton if (not isbperr()) { 6799668Slinton printstatus(); 6809668Slinton } 6819668Slinton break; 6829668Slinton 6839668Slinton default: 6849668Slinton addrstatus = SEQUENTIAL; 6859668Slinton break; 6869668Slinton } 6879668Slinton if (addrstatus != KNOWN) { 6889668Slinton addr += 1; 6899668Slinton op = optab[ins]; 6909668Slinton for (argno = 0; argno < op.numargs; argno++) { 6919668Slinton if (indexf == true) { 6929668Slinton indexf = false; 6939668Slinton } 6949668Slinton argtype = op.argtype[argno]; 6959668Slinton if (is_branch_disp(argtype)) { 6969668Slinton mode = 0xAF + (typelen(argtype) << 5); 6979668Slinton } else { 6989668Slinton iread(&mode, addr, sizeof(mode)); 6999668Slinton addr += 1; 7009668Slinton } 7019668Slinton r = regname[regnm(mode)]; 7029668Slinton amode = addrmode(mode); 7039668Slinton switch (amode) { 7049668Slinton case LITSHORT: 7059668Slinton case LITUPTO31: 7069668Slinton case LITUPTO47: 7079668Slinton case LITUPTO63: 7089668Slinton argval = mode; 7099668Slinton break; 7109668Slinton 7119668Slinton case INDEX: 7129668Slinton indexf = true; 7139668Slinton --argno; 7149668Slinton break; 7159668Slinton 7169668Slinton case REG: 7179668Slinton case REGDEF: 7189668Slinton case AUTODEC: 7199668Slinton break; 7209668Slinton 7219668Slinton case AUTOINC: 7229668Slinton if (r == regname[PROGCTR]) { 7239668Slinton switch (typelen(argtype)) { 7249668Slinton case TYPB: 7259668Slinton argval = getdisp(addr, 1, r, amode); 7269668Slinton addr += 1; 7279668Slinton break; 7289668Slinton 7299668Slinton case TYPW: 7309668Slinton argval = getdisp(addr, 2, r, amode); 7319668Slinton addr += 2; 7329668Slinton break; 7339668Slinton 7349668Slinton case TYPL: 7359668Slinton argval = getdisp(addr, 4, r, amode); 7369668Slinton addr += 4; 7379668Slinton break; 7389668Slinton 7399668Slinton case TYPF: 7409668Slinton iread(&argval, addr, sizeof(argval)); 7419668Slinton addr += 4; 7429668Slinton break; 7439668Slinton 7449668Slinton case TYPQ: 7459668Slinton case TYPD: 7469668Slinton iread(&argval, addr+4, sizeof(argval)); 7479668Slinton addr += 8; 7489668Slinton break; 7499668Slinton } 7509668Slinton } 7519668Slinton break; 7529668Slinton 7539668Slinton case AUTOINCDEF: 7549668Slinton if (r == regname[PROGCTR]) { 7559668Slinton argval = getdisp(addr, 4, r, amode); 7569668Slinton addr += 4; 7579668Slinton } 7589668Slinton break; 7599668Slinton 7609668Slinton case BYTEDISP: 7619668Slinton case BYTEDISPDEF: 7629668Slinton argval = getdisp(addr, 1, r, amode); 7639668Slinton addr += 1; 7649668Slinton break; 7659668Slinton 7669668Slinton case WORDDISP: 7679668Slinton case WORDDISPDEF: 7689668Slinton argval = getdisp(addr, 2, r, amode); 7699668Slinton addr += 2; 7709668Slinton break; 7719668Slinton 7729668Slinton case LONGDISP: 7739668Slinton case LONGDISPDEF: 7749668Slinton argval = getdisp(addr, 4, r, amode); 7759668Slinton addr += 4; 7769668Slinton break; 7779668Slinton } 7789668Slinton } 7799668Slinton if (ins == O_CALLS or ins == O_CALLG) { 7809668Slinton argval += 2; 7819668Slinton } 7829668Slinton if (addrstatus == BRANCH) { 7839668Slinton addr = argval; 7849668Slinton } 7859668Slinton } 7869668Slinton return addr; 7879668Slinton } 7889668Slinton 7899668Slinton /* 7909668Slinton * Get the displacement of an instruction that uses displacement addressing. 7919668Slinton */ 7929668Slinton 7939668Slinton private int getdisp(addr, nbytes, reg, mode) 7949668Slinton Address addr; 7959668Slinton int nbytes; 7969668Slinton String reg; 7979668Slinton int mode; 7989668Slinton { 7999668Slinton char byte; 8009668Slinton short hword; 8019668Slinton int argval; 8029668Slinton 8039668Slinton switch (nbytes) { 8049668Slinton case 1: 8059668Slinton iread(&byte, addr, sizeof(byte)); 8069668Slinton argval = byte; 8079668Slinton break; 8089668Slinton 8099668Slinton case 2: 8109668Slinton iread(&hword, addr, sizeof(hword)); 8119668Slinton argval = hword; 8129668Slinton break; 8139668Slinton 8149668Slinton case 4: 8159668Slinton iread(&argval, addr, sizeof(argval)); 8169668Slinton break; 8179668Slinton } 8189668Slinton if (reg == regname[PROGCTR] && mode >= BYTEDISP) { 8199668Slinton argval += addr + nbytes; 8209668Slinton } 8219668Slinton return argval; 8229668Slinton } 8239668Slinton 8249668Slinton #define BP_OP O_BPT /* breakpoint trap */ 8259668Slinton #define BP_ERRNO SIGTRAP /* signal received at a breakpoint */ 8269668Slinton 8279668Slinton /* 8289668Slinton * Setting a breakpoint at a location consists of saving 8299668Slinton * the word at the location and poking a BP_OP there. 8309668Slinton * 8319668Slinton * We save the locations and words on a list for use in unsetting. 8329668Slinton */ 8339668Slinton 8349668Slinton typedef struct Savelist *Savelist; 8359668Slinton 8369668Slinton struct Savelist { 8379668Slinton Address location; 8389668Slinton Byte save; 8399668Slinton Byte refcount; 8409668Slinton Savelist link; 8419668Slinton }; 8429668Slinton 8439668Slinton private Savelist savelist; 8449668Slinton 8459668Slinton /* 8469668Slinton * Set a breakpoint at the given address. Only save the word there 8479668Slinton * if it's not already a breakpoint. 8489668Slinton */ 8499668Slinton 8509668Slinton public setbp(addr) 8519668Slinton Address addr; 8529668Slinton { 8539668Slinton Byte w; 8549668Slinton Byte save; 8559668Slinton register Savelist newsave, s; 8569668Slinton 8579668Slinton for (s = savelist; s != nil; s = s->link) { 8589668Slinton if (s->location == addr) { 8599668Slinton s->refcount++; 8609668Slinton return; 8619668Slinton } 8629668Slinton } 86311174Slinton iread(&save, addr, sizeof(save)); 8649668Slinton newsave = new(Savelist); 8659668Slinton newsave->location = addr; 8669668Slinton newsave->save = save; 8679668Slinton newsave->refcount = 1; 8689668Slinton newsave->link = savelist; 8699668Slinton savelist = newsave; 8709668Slinton w = BP_OP; 8719668Slinton iwrite(&w, addr, sizeof(w)); 8729668Slinton } 8739668Slinton 8749668Slinton /* 8759668Slinton * Unset a breakpoint; unfortunately we have to search the SAVELIST 8769668Slinton * to find the saved value. The assumption is that the SAVELIST will 8779668Slinton * usually be quite small. 8789668Slinton */ 8799668Slinton 8809668Slinton public unsetbp(addr) 8819668Slinton Address addr; 8829668Slinton { 8839668Slinton register Savelist s, prev; 8849668Slinton 8859668Slinton prev = nil; 8869668Slinton for (s = savelist; s != nil; s = s->link) { 8879668Slinton if (s->location == addr) { 8889668Slinton iwrite(&s->save, addr, sizeof(s->save)); 8899668Slinton s->refcount--; 8909668Slinton if (s->refcount == 0) { 8919668Slinton if (prev == nil) { 8929668Slinton savelist = s->link; 8939668Slinton } else { 8949668Slinton prev->link = s->link; 8959668Slinton } 8969668Slinton dispose(s); 8979668Slinton } 8989668Slinton return; 8999668Slinton } 9009668Slinton prev = s; 9019668Slinton } 9029668Slinton panic("unsetbp: couldn't find address %d", addr); 9039668Slinton } 9049668Slinton 9059668Slinton /* 9069668Slinton * Predicate to test if the reason the process stopped was because 9079668Slinton * of a breakpoint. 9089668Slinton */ 9099668Slinton 9109668Slinton public Boolean isbperr() 9119668Slinton { 9129668Slinton return (Boolean) (not isfinished(process) and errnum(process) == SIGTRAP); 9139668Slinton } 9149668Slinton 9159668Slinton /* 9169668Slinton * Enter a procedure by creating and executing a call instruction. 9179668Slinton */ 9189668Slinton 9199668Slinton #define CALLSIZE 7 /* size of call instruction */ 9209668Slinton 9219668Slinton public beginproc(p, argc) 9229668Slinton Symbol p; 9239668Slinton Integer argc; 9249668Slinton { 9259668Slinton char save[CALLSIZE]; 9269668Slinton struct { 9279668Slinton VaxOpcode op; 9289668Slinton unsigned char numargs; 9299668Slinton unsigned char mode; 9309668Slinton char addr[sizeof(long)]; /* unaligned long */ 9319668Slinton } call; 9329668Slinton long dest; 9339668Slinton 9349668Slinton pc = 2; 9359668Slinton iread(save, pc, sizeof(save)); 9369668Slinton call.op = O_CALLS; 9379668Slinton call.numargs = argc; 9389668Slinton call.mode = 0xef; 9399668Slinton dest = codeloc(p) - 2 - (pc + 7); 9409668Slinton mov(&dest, call.addr, sizeof(call.addr)); 9419668Slinton iwrite(&call, pc, sizeof(call)); 9429668Slinton setreg(PROGCTR, pc); 943*16612Ssam pstep(process, DEFSIG); 9449668Slinton iwrite(save, pc, sizeof(save)); 9459668Slinton pc = reg(PROGCTR); 9469668Slinton if (not isbperr()) { 9479668Slinton printstatus(); 9489668Slinton } 9499668Slinton } 950