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