19668Slinton /* Copyright (c) 1982 Regents of the University of California */ 29668Slinton 3*10621Slinton static char sccsid[] = "@(#)vax.c 1.5 01/25/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; 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. 4219842Slinton * 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" 502*10621Slinton * 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); 515*10621Slinton if (not inst_tracing and nlhdr.nlines != 0) { 5169668Slinton line = linelookup(addr); 5179668Slinton while (line == 0) { 5189668Slinton addr = nextaddr(addr, isnext); 5199668Slinton line = linelookup(addr); 5209668Slinton } 521*10621Slinton curline = line; 522*10621Slinton } else { 523*10621Slinton curline = 0; 5249668Slinton } 5259668Slinton stepto(addr); 5269668Slinton filename = srcfilename(addr); 5279668Slinton setsource(filename); 5289668Slinton } 5299668Slinton 5309668Slinton /* 5319668Slinton * Compute the next address that will be executed from the given one. 5329668Slinton * If "isnext" is true then consider a procedure call as straight line code. 5339668Slinton * 5349668Slinton * We must unfortunately do much of the same work that is necessary 5359668Slinton * to print instructions. In addition we have to deal with branches. 5369668Slinton * Unconditional branches we just follow, for conditional branches 5379668Slinton * we continue execution to the current location and then single step 5389668Slinton * the machine. We assume that the last argument in an instruction 5399668Slinton * that branches is the branch address (or relative offset). 5409668Slinton */ 5419668Slinton 5429668Slinton public Address nextaddr(startaddr, isnext) 5439668Slinton Address startaddr; 5449668Slinton Boolean isnext; 5459668Slinton { 5469668Slinton register Address addr; 5479668Slinton Optab op; 5489668Slinton VaxOpcode ins; 5499668Slinton unsigned char mode; 5509668Slinton int argtype, amode, argno, argval; 5519668Slinton String r; 5529668Slinton Boolean indexf; 5539668Slinton enum { KNOWN, SEQUENTIAL, BRANCH } addrstatus; 5549668Slinton 5559668Slinton argval = 0; 5569668Slinton indexf = false; 5579668Slinton addr = startaddr; 5589668Slinton iread(&ins, addr, sizeof(ins)); 5599668Slinton switch (ins) { 5609668Slinton case O_BRB: 5619668Slinton case O_BRW: 5629668Slinton case O_JMP: 5639668Slinton addrstatus = BRANCH; 5649668Slinton break; 5659668Slinton 5669668Slinton case O_BSBB: 5679668Slinton case O_BSBW: 5689668Slinton case O_JSB: 5699668Slinton case O_CALLG: 5709668Slinton case O_CALLS: 5719668Slinton if (isnext) { 5729668Slinton addrstatus = SEQUENTIAL; 5739668Slinton } else { 5749668Slinton addrstatus = KNOWN; 5759668Slinton stepto(addr); 5769668Slinton pstep(process); 5779668Slinton addr = reg(PROGCTR); 5789668Slinton pc = addr; 5799668Slinton callnews(/* iscall = */ true); 5809668Slinton if (not isbperr()) { 5819668Slinton printstatus(); 5829668Slinton } else { 5839668Slinton bpact(); 5849668Slinton } 5859668Slinton } 5869668Slinton break; 5879668Slinton 5889668Slinton case O_RSB: 5899668Slinton case O_RET: 5909668Slinton addrstatus = KNOWN; 5919668Slinton callnews(/* iscall = */ false); 5929668Slinton addr = return_addr(); 5939668Slinton stepto(addr); 5949668Slinton break; 5959668Slinton 5969668Slinton case O_BNEQ: case O_BEQL: case O_BGTR: 5979668Slinton case O_BLEQ: case O_BGEQ: case O_BLSS: 5989668Slinton case O_BGTRU: case O_BLEQU: case O_BVC: 5999668Slinton case O_BVS: case O_BCC: case O_BCS: 6009668Slinton case O_CASEB: case O_CASEW: case O_CASEL: 6019668Slinton case O_BBS: case O_BBC: case O_BBSS: case O_BBCS: 6029668Slinton case O_BBSC: case O_BBCC: case O_BBSSI: 6039668Slinton case O_BBCCI: case O_BLBS: case O_BLBC: 6049668Slinton case O_ACBL: case O_AOBLSS: case O_AOBLEQ: 6059668Slinton case O_SOBGEQ: case O_SOBGTR: 6069668Slinton addrstatus = KNOWN; 6079668Slinton stepto(addr); 6089668Slinton pstep(process); 6099668Slinton addr = reg(PROGCTR); 6109668Slinton pc = addr; 6119668Slinton if (not isbperr()) { 6129668Slinton printstatus(); 6139668Slinton } 6149668Slinton break; 6159668Slinton 6169668Slinton default: 6179668Slinton addrstatus = SEQUENTIAL; 6189668Slinton break; 6199668Slinton } 6209668Slinton if (addrstatus != KNOWN) { 6219668Slinton addr += 1; 6229668Slinton op = optab[ins]; 6239668Slinton for (argno = 0; argno < op.numargs; argno++) { 6249668Slinton if (indexf == true) { 6259668Slinton indexf = false; 6269668Slinton } 6279668Slinton argtype = op.argtype[argno]; 6289668Slinton if (is_branch_disp(argtype)) { 6299668Slinton mode = 0xAF + (typelen(argtype) << 5); 6309668Slinton } else { 6319668Slinton iread(&mode, addr, sizeof(mode)); 6329668Slinton addr += 1; 6339668Slinton } 6349668Slinton r = regname[regnm(mode)]; 6359668Slinton amode = addrmode(mode); 6369668Slinton switch (amode) { 6379668Slinton case LITSHORT: 6389668Slinton case LITUPTO31: 6399668Slinton case LITUPTO47: 6409668Slinton case LITUPTO63: 6419668Slinton argval = mode; 6429668Slinton break; 6439668Slinton 6449668Slinton case INDEX: 6459668Slinton indexf = true; 6469668Slinton --argno; 6479668Slinton break; 6489668Slinton 6499668Slinton case REG: 6509668Slinton case REGDEF: 6519668Slinton case AUTODEC: 6529668Slinton break; 6539668Slinton 6549668Slinton case AUTOINC: 6559668Slinton if (r == regname[PROGCTR]) { 6569668Slinton switch (typelen(argtype)) { 6579668Slinton case TYPB: 6589668Slinton argval = getdisp(addr, 1, r, amode); 6599668Slinton addr += 1; 6609668Slinton break; 6619668Slinton 6629668Slinton case TYPW: 6639668Slinton argval = getdisp(addr, 2, r, amode); 6649668Slinton addr += 2; 6659668Slinton break; 6669668Slinton 6679668Slinton case TYPL: 6689668Slinton argval = getdisp(addr, 4, r, amode); 6699668Slinton addr += 4; 6709668Slinton break; 6719668Slinton 6729668Slinton case TYPF: 6739668Slinton iread(&argval, addr, sizeof(argval)); 6749668Slinton addr += 4; 6759668Slinton break; 6769668Slinton 6779668Slinton case TYPQ: 6789668Slinton case TYPD: 6799668Slinton iread(&argval, addr+4, sizeof(argval)); 6809668Slinton addr += 8; 6819668Slinton break; 6829668Slinton } 6839668Slinton } 6849668Slinton break; 6859668Slinton 6869668Slinton case AUTOINCDEF: 6879668Slinton if (r == regname[PROGCTR]) { 6889668Slinton argval = getdisp(addr, 4, r, amode); 6899668Slinton addr += 4; 6909668Slinton } 6919668Slinton break; 6929668Slinton 6939668Slinton case BYTEDISP: 6949668Slinton case BYTEDISPDEF: 6959668Slinton argval = getdisp(addr, 1, r, amode); 6969668Slinton addr += 1; 6979668Slinton break; 6989668Slinton 6999668Slinton case WORDDISP: 7009668Slinton case WORDDISPDEF: 7019668Slinton argval = getdisp(addr, 2, r, amode); 7029668Slinton addr += 2; 7039668Slinton break; 7049668Slinton 7059668Slinton case LONGDISP: 7069668Slinton case LONGDISPDEF: 7079668Slinton argval = getdisp(addr, 4, r, amode); 7089668Slinton addr += 4; 7099668Slinton break; 7109668Slinton } 7119668Slinton } 7129668Slinton if (ins == O_CALLS or ins == O_CALLG) { 7139668Slinton argval += 2; 7149668Slinton } 7159668Slinton if (addrstatus == BRANCH) { 7169668Slinton addr = argval; 7179668Slinton } 7189668Slinton } 7199668Slinton return addr; 7209668Slinton } 7219668Slinton 7229668Slinton /* 7239668Slinton * Get the displacement of an instruction that uses displacement addressing. 7249668Slinton */ 7259668Slinton 7269668Slinton private int getdisp(addr, nbytes, reg, mode) 7279668Slinton Address addr; 7289668Slinton int nbytes; 7299668Slinton String reg; 7309668Slinton int mode; 7319668Slinton { 7329668Slinton char byte; 7339668Slinton short hword; 7349668Slinton int argval; 7359668Slinton 7369668Slinton switch (nbytes) { 7379668Slinton case 1: 7389668Slinton iread(&byte, addr, sizeof(byte)); 7399668Slinton argval = byte; 7409668Slinton break; 7419668Slinton 7429668Slinton case 2: 7439668Slinton iread(&hword, addr, sizeof(hword)); 7449668Slinton argval = hword; 7459668Slinton break; 7469668Slinton 7479668Slinton case 4: 7489668Slinton iread(&argval, addr, sizeof(argval)); 7499668Slinton break; 7509668Slinton } 7519668Slinton if (reg == regname[PROGCTR] && mode >= BYTEDISP) { 7529668Slinton argval += addr + nbytes; 7539668Slinton } 7549668Slinton return argval; 7559668Slinton } 7569668Slinton 7579668Slinton #define BP_OP O_BPT /* breakpoint trap */ 7589668Slinton #define BP_ERRNO SIGTRAP /* signal received at a breakpoint */ 7599668Slinton 7609668Slinton /* 7619668Slinton * Setting a breakpoint at a location consists of saving 7629668Slinton * the word at the location and poking a BP_OP there. 7639668Slinton * 7649668Slinton * We save the locations and words on a list for use in unsetting. 7659668Slinton */ 7669668Slinton 7679668Slinton typedef struct Savelist *Savelist; 7689668Slinton 7699668Slinton struct Savelist { 7709668Slinton Address location; 7719668Slinton Byte save; 7729668Slinton Byte refcount; 7739668Slinton Savelist link; 7749668Slinton }; 7759668Slinton 7769668Slinton private Savelist savelist; 7779668Slinton 7789668Slinton /* 7799668Slinton * Set a breakpoint at the given address. Only save the word there 7809668Slinton * if it's not already a breakpoint. 7819668Slinton */ 7829668Slinton 7839668Slinton public setbp(addr) 7849668Slinton Address addr; 7859668Slinton { 7869668Slinton Byte w; 7879668Slinton Byte save; 7889668Slinton register Savelist newsave, s; 7899668Slinton 7909668Slinton for (s = savelist; s != nil; s = s->link) { 7919668Slinton if (s->location == addr) { 7929668Slinton s->refcount++; 7939668Slinton return; 7949668Slinton } 7959668Slinton } 7969668Slinton iread(&save, addr, sizeof(addr)); 7979668Slinton newsave = new(Savelist); 7989668Slinton newsave->location = addr; 7999668Slinton newsave->save = save; 8009668Slinton newsave->refcount = 1; 8019668Slinton newsave->link = savelist; 8029668Slinton savelist = newsave; 8039668Slinton w = BP_OP; 8049668Slinton iwrite(&w, addr, sizeof(w)); 8059668Slinton } 8069668Slinton 8079668Slinton /* 8089668Slinton * Unset a breakpoint; unfortunately we have to search the SAVELIST 8099668Slinton * to find the saved value. The assumption is that the SAVELIST will 8109668Slinton * usually be quite small. 8119668Slinton */ 8129668Slinton 8139668Slinton public unsetbp(addr) 8149668Slinton Address addr; 8159668Slinton { 8169668Slinton register Savelist s, prev; 8179668Slinton 8189668Slinton prev = nil; 8199668Slinton for (s = savelist; s != nil; s = s->link) { 8209668Slinton if (s->location == addr) { 8219668Slinton iwrite(&s->save, addr, sizeof(s->save)); 8229668Slinton s->refcount--; 8239668Slinton if (s->refcount == 0) { 8249668Slinton if (prev == nil) { 8259668Slinton savelist = s->link; 8269668Slinton } else { 8279668Slinton prev->link = s->link; 8289668Slinton } 8299668Slinton dispose(s); 8309668Slinton } 8319668Slinton return; 8329668Slinton } 8339668Slinton prev = s; 8349668Slinton } 8359668Slinton panic("unsetbp: couldn't find address %d", addr); 8369668Slinton } 8379668Slinton 8389668Slinton /* 8399668Slinton * Predicate to test if the reason the process stopped was because 8409668Slinton * of a breakpoint. 8419668Slinton */ 8429668Slinton 8439668Slinton public Boolean isbperr() 8449668Slinton { 8459668Slinton return (Boolean) (not isfinished(process) and errnum(process) == SIGTRAP); 8469668Slinton } 8479668Slinton 8489668Slinton /* 8499668Slinton * Enter a procedure by creating and executing a call instruction. 8509668Slinton */ 8519668Slinton 8529668Slinton #define CALLSIZE 7 /* size of call instruction */ 8539668Slinton 8549668Slinton public beginproc(p, argc) 8559668Slinton Symbol p; 8569668Slinton Integer argc; 8579668Slinton { 8589668Slinton char save[CALLSIZE]; 8599668Slinton struct { 8609668Slinton VaxOpcode op; 8619668Slinton unsigned char numargs; 8629668Slinton unsigned char mode; 8639668Slinton char addr[sizeof(long)]; /* unaligned long */ 8649668Slinton } call; 8659668Slinton long dest; 8669668Slinton 8679668Slinton pc = 2; 8689668Slinton iread(save, pc, sizeof(save)); 8699668Slinton call.op = O_CALLS; 8709668Slinton call.numargs = argc; 8719668Slinton call.mode = 0xef; 8729668Slinton dest = codeloc(p) - 2 - (pc + 7); 8739668Slinton mov(&dest, call.addr, sizeof(call.addr)); 8749668Slinton iwrite(&call, pc, sizeof(call)); 8759668Slinton setreg(PROGCTR, pc); 8769668Slinton pstep(process); 8779668Slinton iwrite(save, pc, sizeof(save)); 8789668Slinton pc = reg(PROGCTR); 8799668Slinton if (not isbperr()) { 8809668Slinton printstatus(); 8819668Slinton } 8829668Slinton } 883