xref: /csrg-svn/old/dbx/vax.c (revision 10621)
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