19668Slinton /* Copyright (c) 1982 Regents of the University of California */ 29668Slinton 3*11174Slinton static char sccsid[] = "@(#)vax.c 1.6 02/20/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 316*11174Slinton private Format *findformat(s) 317*11174Slinton String s; 318*11174Slinton { 319*11174Slinton register Format *f; 320*11174Slinton 321*11174Slinton f = &fmt[0]; 322*11174Slinton while (f->name != nil and not streq(f->name, s)) { 323*11174Slinton ++f; 324*11174Slinton } 325*11174Slinton if (f->name == nil) { 326*11174Slinton error("bad print format \"%s\"", s); 327*11174Slinton } 328*11174Slinton return f; 329*11174Slinton } 330*11174Slinton 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 } 344*11174Slinton 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 } 384*11174Slinton 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 /* 423*11174Slinton * Print out a value according to the given format. 424*11174Slinton */ 425*11174Slinton 426*11174Slinton public printvalue(v, format) 427*11174Slinton long v; 428*11174Slinton String format; 429*11174Slinton { 430*11174Slinton Format *f; 431*11174Slinton char *p, *q; 432*11174Slinton 433*11174Slinton f = findformat(format); 434*11174Slinton if (streq(f->name, "s")) { 435*11174Slinton putchar('"'); 436*11174Slinton p = (char *) &v; 437*11174Slinton q = p + sizeof(v); 438*11174Slinton while (p < q) { 439*11174Slinton printchar(*p); 440*11174Slinton ++p; 441*11174Slinton } 442*11174Slinton putchar('"'); 443*11174Slinton } else { 444*11174Slinton printf(f->printfstring, v); 445*11174Slinton } 446*11174Slinton putchar('\n'); 447*11174Slinton } 448*11174Slinton 449*11174Slinton /* 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; 5949668Slinton callnews(/* iscall = */ true); 5959668Slinton if (not isbperr()) { 5969668Slinton printstatus(); 5979668Slinton } else { 5989668Slinton bpact(); 5999668Slinton } 6009668Slinton } 6019668Slinton break; 6029668Slinton 6039668Slinton case O_RSB: 6049668Slinton case O_RET: 6059668Slinton addrstatus = KNOWN; 6069668Slinton callnews(/* iscall = */ false); 6079668Slinton addr = return_addr(); 6089668Slinton stepto(addr); 6099668Slinton break; 6109668Slinton 6119668Slinton case O_BNEQ: case O_BEQL: case O_BGTR: 6129668Slinton case O_BLEQ: case O_BGEQ: case O_BLSS: 6139668Slinton case O_BGTRU: case O_BLEQU: case O_BVC: 6149668Slinton case O_BVS: case O_BCC: case O_BCS: 6159668Slinton case O_CASEB: case O_CASEW: case O_CASEL: 6169668Slinton case O_BBS: case O_BBC: case O_BBSS: case O_BBCS: 6179668Slinton case O_BBSC: case O_BBCC: case O_BBSSI: 6189668Slinton case O_BBCCI: case O_BLBS: case O_BLBC: 6199668Slinton case O_ACBL: case O_AOBLSS: case O_AOBLEQ: 6209668Slinton case O_SOBGEQ: case O_SOBGTR: 6219668Slinton addrstatus = KNOWN; 6229668Slinton stepto(addr); 6239668Slinton pstep(process); 6249668Slinton addr = reg(PROGCTR); 6259668Slinton pc = addr; 6269668Slinton if (not isbperr()) { 6279668Slinton printstatus(); 6289668Slinton } 6299668Slinton break; 6309668Slinton 6319668Slinton default: 6329668Slinton addrstatus = SEQUENTIAL; 6339668Slinton break; 6349668Slinton } 6359668Slinton if (addrstatus != KNOWN) { 6369668Slinton addr += 1; 6379668Slinton op = optab[ins]; 6389668Slinton for (argno = 0; argno < op.numargs; argno++) { 6399668Slinton if (indexf == true) { 6409668Slinton indexf = false; 6419668Slinton } 6429668Slinton argtype = op.argtype[argno]; 6439668Slinton if (is_branch_disp(argtype)) { 6449668Slinton mode = 0xAF + (typelen(argtype) << 5); 6459668Slinton } else { 6469668Slinton iread(&mode, addr, sizeof(mode)); 6479668Slinton addr += 1; 6489668Slinton } 6499668Slinton r = regname[regnm(mode)]; 6509668Slinton amode = addrmode(mode); 6519668Slinton switch (amode) { 6529668Slinton case LITSHORT: 6539668Slinton case LITUPTO31: 6549668Slinton case LITUPTO47: 6559668Slinton case LITUPTO63: 6569668Slinton argval = mode; 6579668Slinton break; 6589668Slinton 6599668Slinton case INDEX: 6609668Slinton indexf = true; 6619668Slinton --argno; 6629668Slinton break; 6639668Slinton 6649668Slinton case REG: 6659668Slinton case REGDEF: 6669668Slinton case AUTODEC: 6679668Slinton break; 6689668Slinton 6699668Slinton case AUTOINC: 6709668Slinton if (r == regname[PROGCTR]) { 6719668Slinton switch (typelen(argtype)) { 6729668Slinton case TYPB: 6739668Slinton argval = getdisp(addr, 1, r, amode); 6749668Slinton addr += 1; 6759668Slinton break; 6769668Slinton 6779668Slinton case TYPW: 6789668Slinton argval = getdisp(addr, 2, r, amode); 6799668Slinton addr += 2; 6809668Slinton break; 6819668Slinton 6829668Slinton case TYPL: 6839668Slinton argval = getdisp(addr, 4, r, amode); 6849668Slinton addr += 4; 6859668Slinton break; 6869668Slinton 6879668Slinton case TYPF: 6889668Slinton iread(&argval, addr, sizeof(argval)); 6899668Slinton addr += 4; 6909668Slinton break; 6919668Slinton 6929668Slinton case TYPQ: 6939668Slinton case TYPD: 6949668Slinton iread(&argval, addr+4, sizeof(argval)); 6959668Slinton addr += 8; 6969668Slinton break; 6979668Slinton } 6989668Slinton } 6999668Slinton break; 7009668Slinton 7019668Slinton case AUTOINCDEF: 7029668Slinton if (r == regname[PROGCTR]) { 7039668Slinton argval = getdisp(addr, 4, r, amode); 7049668Slinton addr += 4; 7059668Slinton } 7069668Slinton break; 7079668Slinton 7089668Slinton case BYTEDISP: 7099668Slinton case BYTEDISPDEF: 7109668Slinton argval = getdisp(addr, 1, r, amode); 7119668Slinton addr += 1; 7129668Slinton break; 7139668Slinton 7149668Slinton case WORDDISP: 7159668Slinton case WORDDISPDEF: 7169668Slinton argval = getdisp(addr, 2, r, amode); 7179668Slinton addr += 2; 7189668Slinton break; 7199668Slinton 7209668Slinton case LONGDISP: 7219668Slinton case LONGDISPDEF: 7229668Slinton argval = getdisp(addr, 4, r, amode); 7239668Slinton addr += 4; 7249668Slinton break; 7259668Slinton } 7269668Slinton } 7279668Slinton if (ins == O_CALLS or ins == O_CALLG) { 7289668Slinton argval += 2; 7299668Slinton } 7309668Slinton if (addrstatus == BRANCH) { 7319668Slinton addr = argval; 7329668Slinton } 7339668Slinton } 7349668Slinton return addr; 7359668Slinton } 7369668Slinton 7379668Slinton /* 7389668Slinton * Get the displacement of an instruction that uses displacement addressing. 7399668Slinton */ 7409668Slinton 7419668Slinton private int getdisp(addr, nbytes, reg, mode) 7429668Slinton Address addr; 7439668Slinton int nbytes; 7449668Slinton String reg; 7459668Slinton int mode; 7469668Slinton { 7479668Slinton char byte; 7489668Slinton short hword; 7499668Slinton int argval; 7509668Slinton 7519668Slinton switch (nbytes) { 7529668Slinton case 1: 7539668Slinton iread(&byte, addr, sizeof(byte)); 7549668Slinton argval = byte; 7559668Slinton break; 7569668Slinton 7579668Slinton case 2: 7589668Slinton iread(&hword, addr, sizeof(hword)); 7599668Slinton argval = hword; 7609668Slinton break; 7619668Slinton 7629668Slinton case 4: 7639668Slinton iread(&argval, addr, sizeof(argval)); 7649668Slinton break; 7659668Slinton } 7669668Slinton if (reg == regname[PROGCTR] && mode >= BYTEDISP) { 7679668Slinton argval += addr + nbytes; 7689668Slinton } 7699668Slinton return argval; 7709668Slinton } 7719668Slinton 7729668Slinton #define BP_OP O_BPT /* breakpoint trap */ 7739668Slinton #define BP_ERRNO SIGTRAP /* signal received at a breakpoint */ 7749668Slinton 7759668Slinton /* 7769668Slinton * Setting a breakpoint at a location consists of saving 7779668Slinton * the word at the location and poking a BP_OP there. 7789668Slinton * 7799668Slinton * We save the locations and words on a list for use in unsetting. 7809668Slinton */ 7819668Slinton 7829668Slinton typedef struct Savelist *Savelist; 7839668Slinton 7849668Slinton struct Savelist { 7859668Slinton Address location; 7869668Slinton Byte save; 7879668Slinton Byte refcount; 7889668Slinton Savelist link; 7899668Slinton }; 7909668Slinton 7919668Slinton private Savelist savelist; 7929668Slinton 7939668Slinton /* 7949668Slinton * Set a breakpoint at the given address. Only save the word there 7959668Slinton * if it's not already a breakpoint. 7969668Slinton */ 7979668Slinton 7989668Slinton public setbp(addr) 7999668Slinton Address addr; 8009668Slinton { 8019668Slinton Byte w; 8029668Slinton Byte save; 8039668Slinton register Savelist newsave, s; 8049668Slinton 8059668Slinton for (s = savelist; s != nil; s = s->link) { 8069668Slinton if (s->location == addr) { 8079668Slinton s->refcount++; 8089668Slinton return; 8099668Slinton } 8109668Slinton } 811*11174Slinton iread(&save, addr, sizeof(save)); 8129668Slinton newsave = new(Savelist); 8139668Slinton newsave->location = addr; 8149668Slinton newsave->save = save; 8159668Slinton newsave->refcount = 1; 8169668Slinton newsave->link = savelist; 8179668Slinton savelist = newsave; 8189668Slinton w = BP_OP; 8199668Slinton iwrite(&w, addr, sizeof(w)); 8209668Slinton } 8219668Slinton 8229668Slinton /* 8239668Slinton * Unset a breakpoint; unfortunately we have to search the SAVELIST 8249668Slinton * to find the saved value. The assumption is that the SAVELIST will 8259668Slinton * usually be quite small. 8269668Slinton */ 8279668Slinton 8289668Slinton public unsetbp(addr) 8299668Slinton Address addr; 8309668Slinton { 8319668Slinton register Savelist s, prev; 8329668Slinton 8339668Slinton prev = nil; 8349668Slinton for (s = savelist; s != nil; s = s->link) { 8359668Slinton if (s->location == addr) { 8369668Slinton iwrite(&s->save, addr, sizeof(s->save)); 8379668Slinton s->refcount--; 8389668Slinton if (s->refcount == 0) { 8399668Slinton if (prev == nil) { 8409668Slinton savelist = s->link; 8419668Slinton } else { 8429668Slinton prev->link = s->link; 8439668Slinton } 8449668Slinton dispose(s); 8459668Slinton } 8469668Slinton return; 8479668Slinton } 8489668Slinton prev = s; 8499668Slinton } 8509668Slinton panic("unsetbp: couldn't find address %d", addr); 8519668Slinton } 8529668Slinton 8539668Slinton /* 8549668Slinton * Predicate to test if the reason the process stopped was because 8559668Slinton * of a breakpoint. 8569668Slinton */ 8579668Slinton 8589668Slinton public Boolean isbperr() 8599668Slinton { 8609668Slinton return (Boolean) (not isfinished(process) and errnum(process) == SIGTRAP); 8619668Slinton } 8629668Slinton 8639668Slinton /* 8649668Slinton * Enter a procedure by creating and executing a call instruction. 8659668Slinton */ 8669668Slinton 8679668Slinton #define CALLSIZE 7 /* size of call instruction */ 8689668Slinton 8699668Slinton public beginproc(p, argc) 8709668Slinton Symbol p; 8719668Slinton Integer argc; 8729668Slinton { 8739668Slinton char save[CALLSIZE]; 8749668Slinton struct { 8759668Slinton VaxOpcode op; 8769668Slinton unsigned char numargs; 8779668Slinton unsigned char mode; 8789668Slinton char addr[sizeof(long)]; /* unaligned long */ 8799668Slinton } call; 8809668Slinton long dest; 8819668Slinton 8829668Slinton pc = 2; 8839668Slinton iread(save, pc, sizeof(save)); 8849668Slinton call.op = O_CALLS; 8859668Slinton call.numargs = argc; 8869668Slinton call.mode = 0xef; 8879668Slinton dest = codeloc(p) - 2 - (pc + 7); 8889668Slinton mov(&dest, call.addr, sizeof(call.addr)); 8899668Slinton iwrite(&call, pc, sizeof(call)); 8909668Slinton setreg(PROGCTR, pc); 8919668Slinton pstep(process); 8929668Slinton iwrite(save, pc, sizeof(save)); 8939668Slinton pc = reg(PROGCTR); 8949668Slinton if (not isbperr()) { 8959668Slinton printstatus(); 8969668Slinton } 8979668Slinton } 898