19668Slinton /* Copyright (c) 1982 Regents of the University of California */ 29668Slinton 3*9842Slinton static char sccsid[] = "@(#)vax.c 1.4 12/18/82"; 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; 2639668Slinton 2649668Slinton switch (nbytes) { 2659668Slinton case 1: 2669668Slinton iread(&byte, addr, sizeof(byte)); 2679668Slinton argval = byte; 2689668Slinton break; 2699668Slinton 2709668Slinton case 2: 2719668Slinton iread(&hword, addr, sizeof(hword)); 2729668Slinton argval = hword; 2739668Slinton break; 2749668Slinton 2759668Slinton case 4: 2769668Slinton iread(&argval, addr, sizeof(argval)); 2779668Slinton break; 2789668Slinton } 2799668Slinton if (reg == regname[PROGCTR] && mode >= BYTEDISP) { 2809668Slinton argval += addr + nbytes; 2819668Slinton } 2829668Slinton if (reg == regname[PROGCTR]) { 2839668Slinton printf("%x", argval); 2849668Slinton } else { 2859668Slinton printf("%d(%s)", argval, reg); 2869668Slinton } 2879668Slinton return argval; 2889668Slinton } 2899668Slinton 2909668Slinton /* 2919668Slinton * Print the contents of the addresses within the given range 2929668Slinton * according to the given format. 2939668Slinton */ 2949668Slinton 2959668Slinton typedef struct { 2969668Slinton String name; 2979668Slinton String printfstring; 2989668Slinton int length; 2999668Slinton } Format; 3009668Slinton 3019668Slinton private Format fmt[] = { 3029668Slinton { "d", " %d", sizeof(short) }, 3039668Slinton { "D", " %ld", sizeof(long) }, 3049668Slinton { "o", " %o", sizeof(short) }, 3059668Slinton { "O", " %lo", sizeof(long) }, 3069668Slinton { "x", " %04x", sizeof(short) }, 3079668Slinton { "X", " %08x", sizeof(long) }, 3089668Slinton { "b", " \\%o", sizeof(char) }, 3099668Slinton { "c", " '%c'", sizeof(char) }, 3109668Slinton { "s", "%c", sizeof(char) }, 3119668Slinton { "f", " %f", sizeof(double) }, 3129668Slinton { "g", " %g", sizeof(double) }, 3139668Slinton { nil, nil, 0 } 3149668Slinton }; 3159668Slinton 3169668Slinton public Address printdata(lowaddr, highaddr, format) 3179668Slinton Address lowaddr; 3189668Slinton Address highaddr; 3199668Slinton String format; 3209668Slinton { 3219668Slinton register int n; 3229668Slinton register Address addr; 3239668Slinton register Format *f; 3249668Slinton int value; 3259668Slinton 3269668Slinton if (lowaddr > highaddr) { 3279668Slinton error("first address larger than second"); 3289668Slinton } 3299668Slinton f = &fmt[0]; 3309668Slinton while (f->name != nil and not streq(f->name, format)) { 3319668Slinton ++f; 3329668Slinton } 3339668Slinton if (f->name == nil) { 3349668Slinton error("bad print format \"%s\"", format); 3359668Slinton } 3369668Slinton n = 0; 3379668Slinton value = 0; 3389668Slinton for (addr = lowaddr; addr <= highaddr; addr += f->length) { 3399668Slinton if (n == 0) { 3409668Slinton printf("%08x: ", addr); 3419668Slinton } 3429668Slinton dread(&value, addr, f->length); 3439668Slinton printf(f->printfstring, value); 3449668Slinton ++n; 3459668Slinton if (n >= (16 div f->length)) { 3469668Slinton putchar('\n'); 3479668Slinton n = 0; 3489668Slinton } 3499668Slinton } 3509668Slinton if (n != 0) { 3519668Slinton putchar('\n'); 3529668Slinton } 3539668Slinton prtaddr = addr; 3549668Slinton return addr; 3559668Slinton } 3569668Slinton 3579668Slinton /* 3589668Slinton * The other approach is to print n items starting with a given address. 3599668Slinton */ 3609668Slinton 3619668Slinton public printndata(count, startaddr, format) 3629668Slinton int count; 3639668Slinton Address startaddr; 3649668Slinton String format; 3659668Slinton { 3669668Slinton register int i, n; 3679668Slinton register Address addr; 3689668Slinton register Format *f; 3699668Slinton register Boolean isstring; 3709668Slinton int value; 3719668Slinton 3729668Slinton if (count <= 0) { 3739668Slinton error("non-positive repetition count"); 3749668Slinton } 3759668Slinton f = &fmt[0]; 3769668Slinton while (f->name != nil and not streq(f->name, format)) { 3779668Slinton ++f; 3789668Slinton } 3799668Slinton if (f->name == nil) { 3809668Slinton error("bad print format \"%s\"", format); 3819668Slinton } 3829668Slinton isstring = (Boolean) streq(f->name, "s"); 3839668Slinton n = 0; 3849668Slinton addr = startaddr; 3859668Slinton value = 0; 3869668Slinton for (i = 0; i < count; i++) { 3879668Slinton if (n == 0) { 3889668Slinton printf("%08x: ", addr); 3899668Slinton } 3909668Slinton if (isstring) { 3919668Slinton putchar('"'); 3929668Slinton dread(&value, addr, sizeof(char)); 3939668Slinton while (value != '\0') { 3949668Slinton printchar((char) value); 3959668Slinton ++addr; 3969668Slinton dread(&value, addr, sizeof(char)); 3979668Slinton } 3989668Slinton putchar('"'); 3999668Slinton putchar('\n'); 4009668Slinton n = 0; 4019668Slinton addr += sizeof(String); 4029668Slinton } else { 4039668Slinton dread(&value, addr, f->length); 4049668Slinton printf(f->printfstring, value); 4059668Slinton ++n; 4069668Slinton if (n >= (16 div f->length)) { 4079668Slinton putchar('\n'); 4089668Slinton n = 0; 4099668Slinton } 4109668Slinton addr += f->length; 4119668Slinton } 4129668Slinton } 4139668Slinton if (n != 0) { 4149668Slinton putchar('\n'); 4159668Slinton } 4169668Slinton prtaddr = addr; 4179668Slinton } 4189668Slinton 4199668Slinton /* 4209668Slinton * Print out an execution time error. 421*9842Slinton * Assumes the source position of the error has been calculated. 4229668Slinton * 4239668Slinton * Have to check if the -r option was specified; if so then 4249668Slinton * the object file information hasn't been read in yet. 4259668Slinton */ 4269668Slinton 4279668Slinton public printerror() 4289668Slinton { 4299668Slinton extern Integer sys_nsig; 4309668Slinton extern String sys_siglist[]; 4319668Slinton Integer err; 4329668Slinton 4339668Slinton if (isfinished(process)) { 4349668Slinton printf("\"%s\" exits with code %d\n", objname, exitcode(process)); 4359668Slinton erecover(); 4369668Slinton } 4379668Slinton if (runfirst) { 4389668Slinton fprintf(stderr, "Entering debugger ..."); 4399668Slinton init(); 4409668Slinton fprintf(stderr, " type 'help' for help\n"); 4419668Slinton } 4429668Slinton err = errnum(process); 4439668Slinton if (err == SIGINT) { 4449668Slinton printf("\n\ninterrupt "); 4459668Slinton printloc(); 4469668Slinton } else if (err == SIGTRAP) { 4479668Slinton printf("\nerror "); 4489668Slinton printloc(); 4499668Slinton } else { 4509668Slinton if (err < 0 or err > sys_nsig) { 4519668Slinton printf("\nsignal %d ", err); 4529668Slinton } else { 4539668Slinton printf("\n%s ", sys_siglist[err]); 4549668Slinton } 4559668Slinton printloc(); 4569668Slinton } 4579668Slinton putchar('\n'); 4589668Slinton if (curline > 0) { 4599668Slinton printlines(curline, curline); 4609668Slinton } else { 4619668Slinton printinst(pc, pc); 4629668Slinton } 4639668Slinton erecover(); 4649668Slinton } 4659668Slinton 4669668Slinton private printloc() 4679668Slinton { 4689668Slinton if (curline > 0) { 4699668Slinton if (nlhdr.nfiles > 1) { 4709668Slinton printf("at line %d in file %s", curline, cursource); 4719668Slinton } else { 4729668Slinton printf("at line %d", curline); 4739668Slinton } 4749668Slinton } else { 4759668Slinton printf("in "); 4769668Slinton printname(stdout, curfunc); 4779668Slinton printf(" at 0x%x", pc); 4789668Slinton } 4799668Slinton } 4809668Slinton 4819668Slinton /* 4829668Slinton * Note the termination of the program. We do this so as to avoid 4839668Slinton * having the process exit, which would make the values of variables 4849668Slinton * inaccessible. We do want to flush all output buffers here, 4859668Slinton * otherwise it'll never get done. 4869668Slinton */ 4879668Slinton 4889668Slinton public endprogram() 4899668Slinton { 4909668Slinton Integer exitcode; 4919668Slinton 4929668Slinton stepto(nextaddr(pc, true)); 4939668Slinton printnews(); 4949668Slinton exitcode = argn(1, nil); 4959668Slinton printf("\nexecution completed, exit code is %d\n", exitcode); 4969668Slinton getsrcpos(); 4979668Slinton erecover(); 4989668Slinton } 4999668Slinton 5009668Slinton /* 5019668Slinton * Single step the machine a source line (or instruction if "inst_tracing" 5029668Slinton * is true. If "isnext" is true, skip over procedure calls. 5039668Slinton */ 5049668Slinton 5059668Slinton private Address getcall(); 5069668Slinton 5079668Slinton public dostep(isnext) 5089668Slinton Boolean isnext; 5099668Slinton { 5109668Slinton register Address addr; 5119668Slinton register Lineno line; 5129668Slinton String filename; 5139668Slinton 5149668Slinton addr = nextaddr(pc, isnext); 5159668Slinton if (not inst_tracing) { 5169668Slinton line = linelookup(addr); 5179668Slinton while (line == 0) { 5189668Slinton addr = nextaddr(addr, isnext); 5199668Slinton line = linelookup(addr); 5209668Slinton } 5219668Slinton } 5229668Slinton stepto(addr); 5239668Slinton curline = line; 5249668Slinton filename = srcfilename(addr); 5259668Slinton setsource(filename); 5269668Slinton } 5279668Slinton 5289668Slinton /* 5299668Slinton * Compute the next address that will be executed from the given one. 5309668Slinton * If "isnext" is true then consider a procedure call as straight line code. 5319668Slinton * 5329668Slinton * We must unfortunately do much of the same work that is necessary 5339668Slinton * to print instructions. In addition we have to deal with branches. 5349668Slinton * Unconditional branches we just follow, for conditional branches 5359668Slinton * we continue execution to the current location and then single step 5369668Slinton * the machine. We assume that the last argument in an instruction 5379668Slinton * that branches is the branch address (or relative offset). 5389668Slinton */ 5399668Slinton 5409668Slinton public Address nextaddr(startaddr, isnext) 5419668Slinton Address startaddr; 5429668Slinton Boolean isnext; 5439668Slinton { 5449668Slinton register Address addr; 5459668Slinton Optab op; 5469668Slinton VaxOpcode ins; 5479668Slinton unsigned char mode; 5489668Slinton int argtype, amode, argno, argval; 5499668Slinton String r; 5509668Slinton Boolean indexf; 5519668Slinton enum { KNOWN, SEQUENTIAL, BRANCH } addrstatus; 5529668Slinton 5539668Slinton argval = 0; 5549668Slinton indexf = false; 5559668Slinton addr = startaddr; 5569668Slinton iread(&ins, addr, sizeof(ins)); 5579668Slinton switch (ins) { 5589668Slinton case O_BRB: 5599668Slinton case O_BRW: 5609668Slinton case O_JMP: 5619668Slinton addrstatus = BRANCH; 5629668Slinton break; 5639668Slinton 5649668Slinton case O_BSBB: 5659668Slinton case O_BSBW: 5669668Slinton case O_JSB: 5679668Slinton case O_CALLG: 5689668Slinton case O_CALLS: 5699668Slinton if (isnext) { 5709668Slinton addrstatus = SEQUENTIAL; 5719668Slinton } else { 5729668Slinton addrstatus = KNOWN; 5739668Slinton stepto(addr); 5749668Slinton pstep(process); 5759668Slinton addr = reg(PROGCTR); 5769668Slinton pc = addr; 5779668Slinton callnews(/* iscall = */ true); 5789668Slinton if (not isbperr()) { 5799668Slinton printstatus(); 5809668Slinton } else { 5819668Slinton bpact(); 5829668Slinton } 5839668Slinton } 5849668Slinton break; 5859668Slinton 5869668Slinton case O_RSB: 5879668Slinton case O_RET: 5889668Slinton addrstatus = KNOWN; 5899668Slinton callnews(/* iscall = */ false); 5909668Slinton addr = return_addr(); 5919668Slinton stepto(addr); 5929668Slinton break; 5939668Slinton 5949668Slinton case O_BNEQ: case O_BEQL: case O_BGTR: 5959668Slinton case O_BLEQ: case O_BGEQ: case O_BLSS: 5969668Slinton case O_BGTRU: case O_BLEQU: case O_BVC: 5979668Slinton case O_BVS: case O_BCC: case O_BCS: 5989668Slinton case O_CASEB: case O_CASEW: case O_CASEL: 5999668Slinton case O_BBS: case O_BBC: case O_BBSS: case O_BBCS: 6009668Slinton case O_BBSC: case O_BBCC: case O_BBSSI: 6019668Slinton case O_BBCCI: case O_BLBS: case O_BLBC: 6029668Slinton case O_ACBL: case O_AOBLSS: case O_AOBLEQ: 6039668Slinton case O_SOBGEQ: case O_SOBGTR: 6049668Slinton addrstatus = KNOWN; 6059668Slinton stepto(addr); 6069668Slinton pstep(process); 6079668Slinton addr = reg(PROGCTR); 6089668Slinton pc = addr; 6099668Slinton if (not isbperr()) { 6109668Slinton printstatus(); 6119668Slinton } 6129668Slinton break; 6139668Slinton 6149668Slinton default: 6159668Slinton addrstatus = SEQUENTIAL; 6169668Slinton break; 6179668Slinton } 6189668Slinton if (addrstatus != KNOWN) { 6199668Slinton addr += 1; 6209668Slinton op = optab[ins]; 6219668Slinton for (argno = 0; argno < op.numargs; argno++) { 6229668Slinton if (indexf == true) { 6239668Slinton indexf = false; 6249668Slinton } 6259668Slinton argtype = op.argtype[argno]; 6269668Slinton if (is_branch_disp(argtype)) { 6279668Slinton mode = 0xAF + (typelen(argtype) << 5); 6289668Slinton } else { 6299668Slinton iread(&mode, addr, sizeof(mode)); 6309668Slinton addr += 1; 6319668Slinton } 6329668Slinton r = regname[regnm(mode)]; 6339668Slinton amode = addrmode(mode); 6349668Slinton switch (amode) { 6359668Slinton case LITSHORT: 6369668Slinton case LITUPTO31: 6379668Slinton case LITUPTO47: 6389668Slinton case LITUPTO63: 6399668Slinton argval = mode; 6409668Slinton break; 6419668Slinton 6429668Slinton case INDEX: 6439668Slinton indexf = true; 6449668Slinton --argno; 6459668Slinton break; 6469668Slinton 6479668Slinton case REG: 6489668Slinton case REGDEF: 6499668Slinton case AUTODEC: 6509668Slinton break; 6519668Slinton 6529668Slinton case AUTOINC: 6539668Slinton if (r == regname[PROGCTR]) { 6549668Slinton switch (typelen(argtype)) { 6559668Slinton case TYPB: 6569668Slinton argval = getdisp(addr, 1, r, amode); 6579668Slinton addr += 1; 6589668Slinton break; 6599668Slinton 6609668Slinton case TYPW: 6619668Slinton argval = getdisp(addr, 2, r, amode); 6629668Slinton addr += 2; 6639668Slinton break; 6649668Slinton 6659668Slinton case TYPL: 6669668Slinton argval = getdisp(addr, 4, r, amode); 6679668Slinton addr += 4; 6689668Slinton break; 6699668Slinton 6709668Slinton case TYPF: 6719668Slinton iread(&argval, addr, sizeof(argval)); 6729668Slinton addr += 4; 6739668Slinton break; 6749668Slinton 6759668Slinton case TYPQ: 6769668Slinton case TYPD: 6779668Slinton iread(&argval, addr+4, sizeof(argval)); 6789668Slinton addr += 8; 6799668Slinton break; 6809668Slinton } 6819668Slinton } 6829668Slinton break; 6839668Slinton 6849668Slinton case AUTOINCDEF: 6859668Slinton if (r == regname[PROGCTR]) { 6869668Slinton argval = getdisp(addr, 4, r, amode); 6879668Slinton addr += 4; 6889668Slinton } 6899668Slinton break; 6909668Slinton 6919668Slinton case BYTEDISP: 6929668Slinton case BYTEDISPDEF: 6939668Slinton argval = getdisp(addr, 1, r, amode); 6949668Slinton addr += 1; 6959668Slinton break; 6969668Slinton 6979668Slinton case WORDDISP: 6989668Slinton case WORDDISPDEF: 6999668Slinton argval = getdisp(addr, 2, r, amode); 7009668Slinton addr += 2; 7019668Slinton break; 7029668Slinton 7039668Slinton case LONGDISP: 7049668Slinton case LONGDISPDEF: 7059668Slinton argval = getdisp(addr, 4, r, amode); 7069668Slinton addr += 4; 7079668Slinton break; 7089668Slinton } 7099668Slinton } 7109668Slinton if (ins == O_CALLS or ins == O_CALLG) { 7119668Slinton argval += 2; 7129668Slinton } 7139668Slinton if (addrstatus == BRANCH) { 7149668Slinton addr = argval; 7159668Slinton } 7169668Slinton } 7179668Slinton return addr; 7189668Slinton } 7199668Slinton 7209668Slinton /* 7219668Slinton * Get the displacement of an instruction that uses displacement addressing. 7229668Slinton */ 7239668Slinton 7249668Slinton private int getdisp(addr, nbytes, reg, mode) 7259668Slinton Address addr; 7269668Slinton int nbytes; 7279668Slinton String reg; 7289668Slinton int mode; 7299668Slinton { 7309668Slinton char byte; 7319668Slinton short hword; 7329668Slinton int argval; 7339668Slinton 7349668Slinton switch (nbytes) { 7359668Slinton case 1: 7369668Slinton iread(&byte, addr, sizeof(byte)); 7379668Slinton argval = byte; 7389668Slinton break; 7399668Slinton 7409668Slinton case 2: 7419668Slinton iread(&hword, addr, sizeof(hword)); 7429668Slinton argval = hword; 7439668Slinton break; 7449668Slinton 7459668Slinton case 4: 7469668Slinton iread(&argval, addr, sizeof(argval)); 7479668Slinton break; 7489668Slinton } 7499668Slinton if (reg == regname[PROGCTR] && mode >= BYTEDISP) { 7509668Slinton argval += addr + nbytes; 7519668Slinton } 7529668Slinton return argval; 7539668Slinton } 7549668Slinton 7559668Slinton #define BP_OP O_BPT /* breakpoint trap */ 7569668Slinton #define BP_ERRNO SIGTRAP /* signal received at a breakpoint */ 7579668Slinton 7589668Slinton /* 7599668Slinton * Setting a breakpoint at a location consists of saving 7609668Slinton * the word at the location and poking a BP_OP there. 7619668Slinton * 7629668Slinton * We save the locations and words on a list for use in unsetting. 7639668Slinton */ 7649668Slinton 7659668Slinton typedef struct Savelist *Savelist; 7669668Slinton 7679668Slinton struct Savelist { 7689668Slinton Address location; 7699668Slinton Byte save; 7709668Slinton Byte refcount; 7719668Slinton Savelist link; 7729668Slinton }; 7739668Slinton 7749668Slinton private Savelist savelist; 7759668Slinton 7769668Slinton /* 7779668Slinton * Set a breakpoint at the given address. Only save the word there 7789668Slinton * if it's not already a breakpoint. 7799668Slinton */ 7809668Slinton 7819668Slinton public setbp(addr) 7829668Slinton Address addr; 7839668Slinton { 7849668Slinton Byte w; 7859668Slinton Byte save; 7869668Slinton register Savelist newsave, s; 7879668Slinton 7889668Slinton for (s = savelist; s != nil; s = s->link) { 7899668Slinton if (s->location == addr) { 7909668Slinton s->refcount++; 7919668Slinton return; 7929668Slinton } 7939668Slinton } 7949668Slinton iread(&save, addr, sizeof(addr)); 7959668Slinton newsave = new(Savelist); 7969668Slinton newsave->location = addr; 7979668Slinton newsave->save = save; 7989668Slinton newsave->refcount = 1; 7999668Slinton newsave->link = savelist; 8009668Slinton savelist = newsave; 8019668Slinton w = BP_OP; 8029668Slinton iwrite(&w, addr, sizeof(w)); 8039668Slinton } 8049668Slinton 8059668Slinton /* 8069668Slinton * Unset a breakpoint; unfortunately we have to search the SAVELIST 8079668Slinton * to find the saved value. The assumption is that the SAVELIST will 8089668Slinton * usually be quite small. 8099668Slinton */ 8109668Slinton 8119668Slinton public unsetbp(addr) 8129668Slinton Address addr; 8139668Slinton { 8149668Slinton register Savelist s, prev; 8159668Slinton 8169668Slinton prev = nil; 8179668Slinton for (s = savelist; s != nil; s = s->link) { 8189668Slinton if (s->location == addr) { 8199668Slinton iwrite(&s->save, addr, sizeof(s->save)); 8209668Slinton s->refcount--; 8219668Slinton if (s->refcount == 0) { 8229668Slinton if (prev == nil) { 8239668Slinton savelist = s->link; 8249668Slinton } else { 8259668Slinton prev->link = s->link; 8269668Slinton } 8279668Slinton dispose(s); 8289668Slinton } 8299668Slinton return; 8309668Slinton } 8319668Slinton prev = s; 8329668Slinton } 8339668Slinton panic("unsetbp: couldn't find address %d", addr); 8349668Slinton } 8359668Slinton 8369668Slinton /* 8379668Slinton * Predicate to test if the reason the process stopped was because 8389668Slinton * of a breakpoint. 8399668Slinton */ 8409668Slinton 8419668Slinton public Boolean isbperr() 8429668Slinton { 8439668Slinton return (Boolean) (not isfinished(process) and errnum(process) == SIGTRAP); 8449668Slinton } 8459668Slinton 8469668Slinton /* 8479668Slinton * Enter a procedure by creating and executing a call instruction. 8489668Slinton */ 8499668Slinton 8509668Slinton #define CALLSIZE 7 /* size of call instruction */ 8519668Slinton 8529668Slinton public beginproc(p, argc) 8539668Slinton Symbol p; 8549668Slinton Integer argc; 8559668Slinton { 8569668Slinton char save[CALLSIZE]; 8579668Slinton struct { 8589668Slinton VaxOpcode op; 8599668Slinton unsigned char numargs; 8609668Slinton unsigned char mode; 8619668Slinton char addr[sizeof(long)]; /* unaligned long */ 8629668Slinton } call; 8639668Slinton long dest; 8649668Slinton 8659668Slinton pc = 2; 8669668Slinton iread(save, pc, sizeof(save)); 8679668Slinton call.op = O_CALLS; 8689668Slinton call.numargs = argc; 8699668Slinton call.mode = 0xef; 8709668Slinton dest = codeloc(p) - 2 - (pc + 7); 8719668Slinton mov(&dest, call.addr, sizeof(call.addr)); 8729668Slinton iwrite(&call, pc, sizeof(call)); 8739668Slinton setreg(PROGCTR, pc); 8749668Slinton pstep(process); 8759668Slinton iwrite(save, pc, sizeof(save)); 8769668Slinton pc = reg(PROGCTR); 8779668Slinton if (not isbperr()) { 8789668Slinton printstatus(); 8799668Slinton } 8809668Slinton } 881