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