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