xref: /csrg-svn/old/dbx/vax.c (revision 16612)
19668Slinton /* Copyright (c) 1982 Regents of the University of California */
29668Slinton 
3*16612Ssam static char sccsid[] = "@(#)machine.c 1.9 8/5/83";
49668Slinton 
5*16612Ssam static char rcsid[] = "$Header: machine.c,v 1.3 84/03/27 10:21:26 linton Exp $";
6*16612Ssam 
79668Slinton /*
89668Slinton  * Target machine dependent stuff.
99668Slinton  */
109668Slinton 
119668Slinton #include "defs.h"
129668Slinton #include "machine.h"
139668Slinton #include "process.h"
14*16612Ssam #include "runtime.h"
159668Slinton #include "events.h"
169668Slinton #include "main.h"
179668Slinton #include "symbols.h"
189668Slinton #include "source.h"
199668Slinton #include "mappings.h"
209668Slinton #include "object.h"
219693Slinton #include "ops.h"
229668Slinton #include <signal.h>
239668Slinton 
249668Slinton #ifndef public
259668Slinton typedef unsigned int Address;
269668Slinton typedef unsigned char Byte;
279668Slinton typedef unsigned int Word;
289668Slinton 
299668Slinton #define NREG 16
309668Slinton 
319668Slinton #define ARGP 12
329668Slinton #define FRP 13
339668Slinton #define STKP 14
349668Slinton #define PROGCTR 15
359668Slinton 
369668Slinton #define BITSPERBYTE 8
379668Slinton #define BITSPERWORD (BITSPERBYTE * sizeof(Word))
389668Slinton 
399668Slinton #define nargspassed(frame) argn(0, frame)
409668Slinton 
419668Slinton #include "source.h"
429668Slinton #include "symbols.h"
439668Slinton 
449668Slinton Address pc;
459668Slinton Address prtaddr;
469668Slinton 
479668Slinton #endif
489668Slinton 
499668Slinton private Address printop();
509668Slinton 
519668Slinton /*
529668Slinton  * Decode and print the instructions within the given address range.
539668Slinton  */
549668Slinton 
559668Slinton public printinst(lowaddr, highaddr)
569668Slinton Address lowaddr;
579668Slinton Address highaddr;
589668Slinton {
599668Slinton     register Address addr;
609668Slinton 
619668Slinton     for (addr = lowaddr; addr <= highaddr; ) {
629668Slinton 	addr = printop(addr);
639668Slinton     }
649668Slinton     prtaddr = addr;
659668Slinton }
669668Slinton 
679668Slinton /*
689668Slinton  * Another approach:  print n instructions starting at the given address.
699668Slinton  */
709668Slinton 
719668Slinton public printninst(count, addr)
729668Slinton int count;
739668Slinton Address addr;
749668Slinton {
759668Slinton     register Integer i;
769668Slinton     register Address newaddr;
779668Slinton 
789668Slinton     if (count <= 0) {
799668Slinton 	error("non-positive repetition count");
809668Slinton     } else {
819668Slinton 	newaddr = addr;
829668Slinton 	for (i = 0; i < count; i++) {
839668Slinton 	    newaddr = printop(newaddr);
849668Slinton 	}
859668Slinton 	prtaddr = newaddr;
869668Slinton     }
879668Slinton }
889668Slinton 
899668Slinton /*
909668Slinton  * Hacked version of adb's VAX instruction decoder.
919668Slinton  */
929668Slinton 
939668Slinton private Address printop(addr)
949668Slinton Address addr;
959668Slinton {
969668Slinton     Optab op;
979668Slinton     VaxOpcode ins;
989668Slinton     unsigned char mode;
999668Slinton     int argtype, amode, argno, argval;
1009668Slinton     String reg;
1019668Slinton     Boolean indexf;
1029668Slinton     short offset;
1039668Slinton 
1049668Slinton     argval = 0;
1059668Slinton     indexf = false;
1069668Slinton     printf("%08x  ", addr);
1079668Slinton     iread(&ins, addr, sizeof(ins));
1089668Slinton     addr += 1;
1099668Slinton     op = optab[ins];
1109668Slinton     printf("%s", op.iname);
1119668Slinton     for (argno = 0; argno < op.numargs; argno++) {
1129668Slinton 	if (indexf == true) {
1139668Slinton 	    indexf = false;
1149668Slinton 	} else if (argno == 0) {
1159668Slinton 	    printf("\t");
1169668Slinton 	} else {
1179668Slinton 	    printf(",");
1189668Slinton 	}
1199668Slinton 	argtype = op.argtype[argno];
1209668Slinton 	if (is_branch_disp(argtype)) {
1219668Slinton 	    mode = 0xAF + (typelen(argtype) << 5);
1229668Slinton 	} else {
1239668Slinton 	    iread(&mode, addr, sizeof(mode));
1249668Slinton 	    addr += 1;
1259668Slinton 	}
1269668Slinton 	reg = regname[regnm(mode)];
1279668Slinton 	amode = addrmode(mode);
1289668Slinton 	switch (amode) {
1299668Slinton 	    case LITSHORT:
1309668Slinton 	    case LITUPTO31:
1319668Slinton 	    case LITUPTO47:
1329668Slinton 	    case LITUPTO63:
1339668Slinton 		if (typelen(argtype) == TYPF || typelen(argtype) ==TYPD)
1349668Slinton 		    printf("$%s", fltimm[mode]);
1359668Slinton 		else
1369668Slinton 		    printf("$%x", mode);
1379668Slinton 		argval = mode;
1389668Slinton 		break;
1399668Slinton 
1409668Slinton 	    case INDEX:
1419668Slinton 		printf("[%s]", reg);
1429668Slinton 		indexf = true;
1439668Slinton 		argno--;
1449668Slinton 		break;
1459668Slinton 
1469668Slinton 	    case REG:
1479668Slinton 		printf("%s", reg);
1489668Slinton 		break;
1499668Slinton 
1509668Slinton 	    case REGDEF:
1519668Slinton 		printf("(%s)", reg);
1529668Slinton 		break;
1539668Slinton 
1549668Slinton 	    case AUTODEC:
1559668Slinton 		printf("-(%s)", reg);
1569668Slinton 		break;
1579668Slinton 
1589668Slinton 	    case AUTOINC:
1599668Slinton 		if (reg != regname[PROGCTR]) {
1609668Slinton 		    printf("(%s)+", reg);
1619668Slinton 		} else {
1629668Slinton 		    printf("$");
1639668Slinton 		    switch (typelen(argtype)) {
1649668Slinton 			case TYPB:
1659668Slinton 			    argval = printdisp(addr, 1, reg, amode);
1669668Slinton 			    addr += 1;
1679668Slinton 			    break;
1689668Slinton 
1699668Slinton 			case TYPW:
1709668Slinton 			    argval = printdisp(addr, 2, reg, amode);
1719668Slinton 			    addr += 2;
1729668Slinton 			    break;
1739668Slinton 
1749668Slinton 			case TYPL:
1759668Slinton 			    argval = printdisp(addr, 4, reg, amode);
1769668Slinton 			    addr += 4;
1779668Slinton 			    break;
1789668Slinton 
1799668Slinton 			case TYPF:
1809668Slinton 			    iread(&argval, addr, sizeof(argval));
1819668Slinton 			    printf("%06x", argval);
1829668Slinton 			    addr += 4;
1839668Slinton 			    break;
1849668Slinton 
1859668Slinton 			case TYPQ:
1869668Slinton 			case TYPD:
1879668Slinton 			    iread(&argval, addr, sizeof(argval));
1889668Slinton 			    printf("%06x", argval);
1899668Slinton 			    iread(&argval, addr+4, sizeof(argval));
1909668Slinton 			    printf("%06x", argval);
1919668Slinton 			    addr += 8;
1929668Slinton 			    break;
1939668Slinton 		    }
1949668Slinton 		}
1959668Slinton 		break;
1969668Slinton 
1979668Slinton 	    case AUTOINCDEF:
1989668Slinton 		if (reg == regname[PROGCTR]) {
1999668Slinton 		    printf("*$");
2009668Slinton 		    argval = printdisp(addr, 4, reg, amode);
2019668Slinton 		    addr += 4;
2029668Slinton 		} else {
2039668Slinton 		    printf("*(%s)+", reg);
2049668Slinton 		}
2059668Slinton 		break;
2069668Slinton 
2079668Slinton 	    case BYTEDISP:
2089668Slinton 		argval = printdisp(addr, 1, reg, amode);
2099668Slinton 		addr += 1;
2109668Slinton 		break;
2119668Slinton 
2129668Slinton 	    case BYTEDISPDEF:
2139668Slinton 		printf("*");
2149668Slinton 		argval = printdisp(addr, 1, reg, amode);
2159668Slinton 		addr += 1;
2169668Slinton 		break;
2179668Slinton 
2189668Slinton 	    case WORDDISP:
2199668Slinton 		argval = printdisp(addr, 2, reg, amode);
2209668Slinton 		addr += 2;
2219668Slinton 		break;
2229668Slinton 
2239668Slinton 	    case WORDDISPDEF:
2249668Slinton 		printf("*");
2259668Slinton 		argval = printdisp(addr, 2, reg, amode);
2269668Slinton 		addr += 2;
2279668Slinton 		break;
2289668Slinton 
2299668Slinton 	    case LONGDISP:
2309668Slinton 		argval = printdisp(addr, 4, reg, amode);
2319668Slinton 		addr += 4;
2329668Slinton 		break;
2339668Slinton 
2349668Slinton 	    case LONGDISPDEF:
2359668Slinton 		printf("*");
2369668Slinton 		argval = printdisp(addr, 4, reg, amode);
2379668Slinton 		addr += 4;
2389668Slinton 		break;
2399668Slinton 	}
2409668Slinton     }
2419668Slinton     if (ins == O_CASEB || ins == O_CASEW || ins == O_CASEL) {
2429668Slinton 	for (argno = 0; argno <= argval; argno++) {
2439668Slinton 	    iread(&offset, addr, sizeof(offset));
2449668Slinton 	    printf("\n\t\t%d", offset);
2459668Slinton 	    addr += 2;
2469668Slinton 	}
2479668Slinton     }
2489668Slinton     printf("\n");
2499668Slinton     return addr;
2509668Slinton }
2519668Slinton 
2529668Slinton /*
2539668Slinton  * Print the displacement of an instruction that uses displacement
2549668Slinton  * addressing.
2559668Slinton  */
2569668Slinton 
2579668Slinton private int printdisp(addr, nbytes, reg, mode)
2589668Slinton Address addr;
2599668Slinton int nbytes;
2609668Slinton char *reg;
2619668Slinton int mode;
2629668Slinton {
2639668Slinton     char byte;
2649668Slinton     short hword;
2659668Slinton     int argval;
26614338Slinton     Symbol f;
2679668Slinton 
2689668Slinton     switch (nbytes) {
2699668Slinton 	case 1:
2709668Slinton 	    iread(&byte, addr, sizeof(byte));
2719668Slinton 	    argval = byte;
2729668Slinton 	    break;
2739668Slinton 
2749668Slinton 	case 2:
2759668Slinton 	    iread(&hword, addr, sizeof(hword));
2769668Slinton 	    argval = hword;
2779668Slinton 	    break;
2789668Slinton 
2799668Slinton 	case 4:
2809668Slinton 	    iread(&argval, addr, sizeof(argval));
2819668Slinton 	    break;
2829668Slinton     }
2839668Slinton     if (reg == regname[PROGCTR] && mode >= BYTEDISP) {
2849668Slinton 	argval += addr + nbytes;
2859668Slinton     }
2869668Slinton     if (reg == regname[PROGCTR]) {
28714338Slinton 	f = whatblock((Address) argval + 2);
28814338Slinton 	if (codeloc(f) == argval + 2) {
28914338Slinton 	    printf("%s", symname(f));
29014338Slinton 	} else {
29114338Slinton 	    printf("%x", argval);
29214338Slinton 	}
2939668Slinton     } else {
2949668Slinton 	printf("%d(%s)", argval, reg);
2959668Slinton     }
2969668Slinton     return argval;
2979668Slinton }
2989668Slinton 
2999668Slinton /*
3009668Slinton  * Print the contents of the addresses within the given range
3019668Slinton  * according to the given format.
3029668Slinton  */
3039668Slinton 
3049668Slinton typedef struct {
3059668Slinton     String name;
3069668Slinton     String printfstring;
3079668Slinton     int length;
3089668Slinton } Format;
3099668Slinton 
3109668Slinton private Format fmt[] = {
3119668Slinton     { "d", " %d", sizeof(short) },
3129668Slinton     { "D", " %ld", sizeof(long) },
3139668Slinton     { "o", " %o", sizeof(short) },
3149668Slinton     { "O", " %lo", sizeof(long) },
3159668Slinton     { "x", " %04x", sizeof(short) },
3169668Slinton     { "X", " %08x", sizeof(long) },
3179668Slinton     { "b", " \\%o", sizeof(char) },
3189668Slinton     { "c", " '%c'", sizeof(char) },
3199668Slinton     { "s", "%c", sizeof(char) },
32014338Slinton     { "f", " %f", sizeof(float) },
3219668Slinton     { "g", " %g", sizeof(double) },
3229668Slinton     { nil, nil, 0 }
3239668Slinton };
3249668Slinton 
32511174Slinton private Format *findformat(s)
32611174Slinton String s;
32711174Slinton {
32811174Slinton     register Format *f;
32911174Slinton 
33011174Slinton     f = &fmt[0];
33111174Slinton     while (f->name != nil and not streq(f->name, s)) {
33211174Slinton 	++f;
33311174Slinton     }
33411174Slinton     if (f->name == nil) {
33511174Slinton 	error("bad print format \"%s\"", s);
33611174Slinton     }
33711174Slinton     return f;
33811174Slinton }
33911174Slinton 
3409668Slinton public Address printdata(lowaddr, highaddr, format)
3419668Slinton Address lowaddr;
3429668Slinton Address highaddr;
3439668Slinton String format;
3449668Slinton {
3459668Slinton     register int n;
3469668Slinton     register Address addr;
3479668Slinton     register Format *f;
3489668Slinton     int value;
3499668Slinton 
3509668Slinton     if (lowaddr > highaddr) {
3519668Slinton 	error("first address larger than second");
3529668Slinton     }
35311174Slinton     f = findformat(format);
3549668Slinton     n = 0;
3559668Slinton     value = 0;
3569668Slinton     for (addr = lowaddr; addr <= highaddr; addr += f->length) {
3579668Slinton 	if (n == 0) {
3589668Slinton 	    printf("%08x: ", addr);
3599668Slinton 	}
3609668Slinton 	dread(&value, addr, f->length);
3619668Slinton 	printf(f->printfstring, value);
3629668Slinton 	++n;
3639668Slinton 	if (n >= (16 div f->length)) {
3649668Slinton 	    putchar('\n');
3659668Slinton 	    n = 0;
3669668Slinton 	}
3679668Slinton     }
3689668Slinton     if (n != 0) {
3699668Slinton 	putchar('\n');
3709668Slinton     }
3719668Slinton     prtaddr = addr;
3729668Slinton     return addr;
3739668Slinton }
3749668Slinton 
3759668Slinton /*
3769668Slinton  * The other approach is to print n items starting with a given address.
3779668Slinton  */
3789668Slinton 
3799668Slinton public printndata(count, startaddr, format)
3809668Slinton int count;
3819668Slinton Address startaddr;
3829668Slinton String format;
3839668Slinton {
3849668Slinton     register int i, n;
3859668Slinton     register Address addr;
3869668Slinton     register Format *f;
3879668Slinton     register Boolean isstring;
38814338Slinton     char c;
38914338Slinton     union {
39014338Slinton 	char charv;
39114338Slinton 	short shortv;
39214338Slinton 	int intv;
39314338Slinton 	float floatv;
39414338Slinton 	double doublev;
39514338Slinton     } value;
3969668Slinton 
3979668Slinton     if (count <= 0) {
3989668Slinton 	error("non-positive repetition count");
3999668Slinton     }
40011174Slinton     f = findformat(format);
4019668Slinton     isstring = (Boolean) streq(f->name, "s");
4029668Slinton     n = 0;
4039668Slinton     addr = startaddr;
40414338Slinton     value.intv = 0;
4059668Slinton     for (i = 0; i < count; i++) {
4069668Slinton 	if (n == 0) {
4079668Slinton 	    printf("%08x: ", addr);
4089668Slinton 	}
4099668Slinton 	if (isstring) {
4109668Slinton 	    putchar('"');
41114338Slinton 	    dread(&c, addr, sizeof(char));
41214338Slinton 	    while (c != '\0') {
41314338Slinton 		printchar(c);
4149668Slinton 		++addr;
41514338Slinton 		dread(&c, addr, sizeof(char));
4169668Slinton 	    }
4179668Slinton 	    putchar('"');
4189668Slinton 	    putchar('\n');
4199668Slinton 	    n = 0;
4209668Slinton 	    addr += sizeof(String);
4219668Slinton 	} else {
4229668Slinton 	    dread(&value, addr, f->length);
4239668Slinton 	    printf(f->printfstring, value);
4249668Slinton 	    ++n;
4259668Slinton 	    if (n >= (16 div f->length)) {
4269668Slinton 		putchar('\n');
4279668Slinton 		n = 0;
4289668Slinton 	    }
4299668Slinton 	    addr += f->length;
4309668Slinton 	}
4319668Slinton     }
4329668Slinton     if (n != 0) {
4339668Slinton 	putchar('\n');
4349668Slinton     }
4359668Slinton     prtaddr = addr;
4369668Slinton }
4379668Slinton 
4389668Slinton /*
43911174Slinton  * Print out a value according to the given format.
44011174Slinton  */
44111174Slinton 
44211174Slinton public printvalue(v, format)
44311174Slinton long v;
44411174Slinton String format;
44511174Slinton {
44611174Slinton     Format *f;
44711174Slinton     char *p, *q;
44811174Slinton 
44911174Slinton     f = findformat(format);
45011174Slinton     if (streq(f->name, "s")) {
45111174Slinton 	putchar('"');
45211174Slinton 	p = (char *) &v;
45311174Slinton 	q = p + sizeof(v);
45411174Slinton 	while (p < q) {
45511174Slinton 	    printchar(*p);
45611174Slinton 	    ++p;
45711174Slinton 	}
45811174Slinton 	putchar('"');
45911174Slinton     } else {
46011174Slinton 	printf(f->printfstring, v);
46111174Slinton     }
46211174Slinton     putchar('\n');
46311174Slinton }
46411174Slinton 
46511174Slinton /*
4669668Slinton  * Print out an execution time error.
4679842Slinton  * Assumes the source position of the error has been calculated.
4689668Slinton  *
4699668Slinton  * Have to check if the -r option was specified; if so then
4709668Slinton  * the object file information hasn't been read in yet.
4719668Slinton  */
4729668Slinton 
4739668Slinton public printerror()
4749668Slinton {
4759668Slinton     extern Integer sys_nsig;
4769668Slinton     extern String sys_siglist[];
4779668Slinton     Integer err;
4789668Slinton 
4799668Slinton     if (isfinished(process)) {
4809668Slinton 	printf("\"%s\" exits with code %d\n", objname, exitcode(process));
4819668Slinton 	erecover();
4829668Slinton     }
4839668Slinton     if (runfirst) {
4849668Slinton 	fprintf(stderr, "Entering debugger ...");
4859668Slinton 	init();
4869668Slinton 	fprintf(stderr, " type 'help' for help\n");
4879668Slinton     }
4889668Slinton     err = errnum(process);
4899668Slinton     if (err == SIGINT) {
4909668Slinton 	printf("\n\ninterrupt ");
4919668Slinton 	printloc();
4929668Slinton     } else if (err == SIGTRAP) {
4939668Slinton 	printf("\nerror ");
4949668Slinton 	printloc();
4959668Slinton     } else {
4969668Slinton 	if (err < 0 or err > sys_nsig) {
4979668Slinton 	    printf("\nsignal %d ", err);
4989668Slinton 	} else {
4999668Slinton 	    printf("\n%s ", sys_siglist[err]);
5009668Slinton 	}
5019668Slinton 	printloc();
5029668Slinton     }
5039668Slinton     putchar('\n');
5049668Slinton     if (curline > 0) {
5059668Slinton 	printlines(curline, curline);
5069668Slinton     } else {
5079668Slinton 	printinst(pc, pc);
5089668Slinton     }
5099668Slinton     erecover();
5109668Slinton }
5119668Slinton 
5129668Slinton /*
5139668Slinton  * Note the termination of the program.  We do this so as to avoid
5149668Slinton  * having the process exit, which would make the values of variables
5159668Slinton  * inaccessible.  We do want to flush all output buffers here,
5169668Slinton  * otherwise it'll never get done.
5179668Slinton  */
5189668Slinton 
5199668Slinton public endprogram()
5209668Slinton {
5219668Slinton     Integer exitcode;
5229668Slinton 
5239668Slinton     stepto(nextaddr(pc, true));
5249668Slinton     printnews();
5259668Slinton     exitcode = argn(1, nil);
5269668Slinton     printf("\nexecution completed, exit code is %d\n", exitcode);
5279668Slinton     getsrcpos();
5289668Slinton     erecover();
5299668Slinton }
5309668Slinton 
5319668Slinton /*
5329668Slinton  * Single step the machine a source line (or instruction if "inst_tracing"
53310621Slinton  * is true).  If "isnext" is true, skip over procedure calls.
5349668Slinton  */
5359668Slinton 
5369668Slinton private Address getcall();
5379668Slinton 
5389668Slinton public dostep(isnext)
5399668Slinton Boolean isnext;
5409668Slinton {
5419668Slinton     register Address addr;
5429668Slinton     register Lineno line;
5439668Slinton     String filename;
544*16612Ssam     Address startaddr, prevaddr;
5459668Slinton 
546*16612Ssam     startaddr = pc;
547*16612Ssam     prevaddr = startaddr;
5489668Slinton     addr = nextaddr(pc, isnext);
54910621Slinton     if (not inst_tracing and nlhdr.nlines != 0) {
5509668Slinton 	line = linelookup(addr);
5519668Slinton 	while (line == 0) {
552*16612Ssam 	    prevaddr = addr;
5539668Slinton 	    addr = nextaddr(addr, isnext);
5549668Slinton 	    line = linelookup(addr);
5559668Slinton 	}
55610621Slinton 	curline = line;
55710621Slinton     } else {
55810621Slinton 	curline = 0;
5599668Slinton     }
560*16612Ssam     if (addr == startaddr) {
561*16612Ssam 	stepto(prevaddr);
562*16612Ssam     }
5639668Slinton     stepto(addr);
5649668Slinton     filename = srcfilename(addr);
5659668Slinton     setsource(filename);
5669668Slinton }
5679668Slinton 
5689668Slinton /*
5699668Slinton  * Compute the next address that will be executed from the given one.
5709668Slinton  * If "isnext" is true then consider a procedure call as straight line code.
5719668Slinton  *
5729668Slinton  * We must unfortunately do much of the same work that is necessary
5739668Slinton  * to print instructions.  In addition we have to deal with branches.
5749668Slinton  * Unconditional branches we just follow, for conditional branches
5759668Slinton  * we continue execution to the current location and then single step
5769668Slinton  * the machine.  We assume that the last argument in an instruction
5779668Slinton  * that branches is the branch address (or relative offset).
5789668Slinton  */
5799668Slinton 
580*16612Ssam private Address findnextaddr();
581*16612Ssam 
5829668Slinton public Address nextaddr(startaddr, isnext)
5839668Slinton Address startaddr;
584*16612Ssam boolean isnext;
585*16612Ssam {
586*16612Ssam     Address addr;
587*16612Ssam 
588*16612Ssam     addr = usignal(process);
589*16612Ssam     if (addr == 0 or addr == 1) {
590*16612Ssam 	addr = findnextaddr(startaddr, isnext);
591*16612Ssam     }
592*16612Ssam     return addr;
593*16612Ssam }
594*16612Ssam 
595*16612Ssam private Address findnextaddr(startaddr, isnext)
596*16612Ssam Address startaddr;
5979668Slinton Boolean isnext;
5989668Slinton {
5999668Slinton     register Address addr;
6009668Slinton     Optab op;
6019668Slinton     VaxOpcode ins;
6029668Slinton     unsigned char mode;
6039668Slinton     int argtype, amode, argno, argval;
6049668Slinton     String r;
6059668Slinton     Boolean indexf;
6069668Slinton     enum { KNOWN, SEQUENTIAL, BRANCH } addrstatus;
6079668Slinton 
6089668Slinton     argval = 0;
6099668Slinton     indexf = false;
6109668Slinton     addr = startaddr;
6119668Slinton     iread(&ins, addr, sizeof(ins));
6129668Slinton     switch (ins) {
6139668Slinton 	case O_BRB:
6149668Slinton 	case O_BRW:
6159668Slinton 	    addrstatus = BRANCH;
6169668Slinton 	    break;
6179668Slinton 
6189668Slinton 	case O_BSBB:
6199668Slinton 	case O_BSBW:
6209668Slinton 	case O_JSB:
6219668Slinton 	case O_CALLG:
6229668Slinton 	case O_CALLS:
6239668Slinton 	    if (isnext) {
6249668Slinton 		addrstatus = SEQUENTIAL;
6259668Slinton 	    } else {
6269668Slinton 		addrstatus = KNOWN;
6279668Slinton 		stepto(addr);
628*16612Ssam 		pstep(process, DEFSIG);
6299668Slinton 		addr = reg(PROGCTR);
6309668Slinton 		pc = addr;
631*16612Ssam 		setcurfunc(whatblock(pc));
6329668Slinton 		if (not isbperr()) {
6339668Slinton 		    printstatus();
63411864Slinton 		    /* NOTREACHED */
63511864Slinton 		}
63611864Slinton 		bpact();
63711864Slinton 		if (nosource(curfunc) and canskip(curfunc) and
63811864Slinton 		  nlhdr.nlines != 0) {
63911864Slinton 		    addrstatus = KNOWN;
64011864Slinton 		    addr = return_addr();
64111864Slinton 		    stepto(addr);
64211874Slinton 		    bpact();
6439668Slinton 		} else {
64411864Slinton 		    callnews(/* iscall = */ true);
6459668Slinton 		}
6469668Slinton 	    }
6479668Slinton 	    break;
6489668Slinton 
6499668Slinton 	case O_RSB:
6509668Slinton 	case O_RET:
6519668Slinton 	    addrstatus = KNOWN;
6529668Slinton 	    callnews(/* iscall = */ false);
6539668Slinton 	    addr = return_addr();
654*16612Ssam 	    if (addr == pc) {	/* recursive ret to self */
655*16612Ssam 		pstep(process, DEFSIG);
656*16612Ssam 	    } else {
657*16612Ssam 		stepto(addr);
658*16612Ssam 	    }
65911874Slinton 	    bpact();
6609668Slinton 	    break;
6619668Slinton 
662*16612Ssam 	case O_JMP: /* because it may be jmp (r1) */
6639668Slinton 	case O_BNEQ: case O_BEQL: case O_BGTR:
6649668Slinton 	case O_BLEQ: case O_BGEQ: case O_BLSS:
6659668Slinton 	case O_BGTRU: case O_BLEQU: case O_BVC:
6669668Slinton 	case O_BVS: case O_BCC: case O_BCS:
6679668Slinton 	case O_CASEB: case O_CASEW: case O_CASEL:
6689668Slinton 	case O_BBS: case O_BBC: case O_BBSS: case O_BBCS:
6699668Slinton 	case O_BBSC: case O_BBCC: case O_BBSSI:
6709668Slinton 	case O_BBCCI: case O_BLBS: case O_BLBC:
6719668Slinton 	case O_ACBL: case O_AOBLSS: case O_AOBLEQ:
6729668Slinton 	case O_SOBGEQ: case O_SOBGTR:
6739668Slinton 	    addrstatus = KNOWN;
6749668Slinton 	    stepto(addr);
675*16612Ssam 	    pstep(process, DEFSIG);
6769668Slinton 	    addr = reg(PROGCTR);
6779668Slinton 	    pc = addr;
6789668Slinton 	    if (not isbperr()) {
6799668Slinton 		printstatus();
6809668Slinton 	    }
6819668Slinton 	    break;
6829668Slinton 
6839668Slinton 	default:
6849668Slinton 	    addrstatus = SEQUENTIAL;
6859668Slinton 	    break;
6869668Slinton     }
6879668Slinton     if (addrstatus != KNOWN) {
6889668Slinton 	addr += 1;
6899668Slinton 	op = optab[ins];
6909668Slinton 	for (argno = 0; argno < op.numargs; argno++) {
6919668Slinton 	    if (indexf == true) {
6929668Slinton 		indexf = false;
6939668Slinton 	    }
6949668Slinton 	    argtype = op.argtype[argno];
6959668Slinton 	    if (is_branch_disp(argtype)) {
6969668Slinton 		mode = 0xAF + (typelen(argtype) << 5);
6979668Slinton 	    } else {
6989668Slinton 		iread(&mode, addr, sizeof(mode));
6999668Slinton 		addr += 1;
7009668Slinton 	    }
7019668Slinton 	    r = regname[regnm(mode)];
7029668Slinton 	    amode = addrmode(mode);
7039668Slinton 	    switch (amode) {
7049668Slinton 		case LITSHORT:
7059668Slinton 		case LITUPTO31:
7069668Slinton 		case LITUPTO47:
7079668Slinton 		case LITUPTO63:
7089668Slinton 		    argval = mode;
7099668Slinton 		    break;
7109668Slinton 
7119668Slinton 		case INDEX:
7129668Slinton 		    indexf = true;
7139668Slinton 		    --argno;
7149668Slinton 		    break;
7159668Slinton 
7169668Slinton 		case REG:
7179668Slinton 		case REGDEF:
7189668Slinton 		case AUTODEC:
7199668Slinton 		    break;
7209668Slinton 
7219668Slinton 		case AUTOINC:
7229668Slinton 		    if (r == regname[PROGCTR]) {
7239668Slinton 			switch (typelen(argtype)) {
7249668Slinton 			    case TYPB:
7259668Slinton 				argval = getdisp(addr, 1, r, amode);
7269668Slinton 				addr += 1;
7279668Slinton 				break;
7289668Slinton 
7299668Slinton 			    case TYPW:
7309668Slinton 				argval = getdisp(addr, 2, r, amode);
7319668Slinton 				addr += 2;
7329668Slinton 				break;
7339668Slinton 
7349668Slinton 			    case TYPL:
7359668Slinton 				argval = getdisp(addr, 4, r, amode);
7369668Slinton 				addr += 4;
7379668Slinton 				break;
7389668Slinton 
7399668Slinton 			    case TYPF:
7409668Slinton 				iread(&argval, addr, sizeof(argval));
7419668Slinton 				addr += 4;
7429668Slinton 				break;
7439668Slinton 
7449668Slinton 			    case TYPQ:
7459668Slinton 			    case TYPD:
7469668Slinton 				iread(&argval, addr+4, sizeof(argval));
7479668Slinton 				addr += 8;
7489668Slinton 				break;
7499668Slinton 			}
7509668Slinton 		    }
7519668Slinton 		    break;
7529668Slinton 
7539668Slinton 		case AUTOINCDEF:
7549668Slinton 		    if (r == regname[PROGCTR]) {
7559668Slinton 			argval = getdisp(addr, 4, r, amode);
7569668Slinton 			addr += 4;
7579668Slinton 		    }
7589668Slinton 		    break;
7599668Slinton 
7609668Slinton 		case BYTEDISP:
7619668Slinton 		case BYTEDISPDEF:
7629668Slinton 		    argval = getdisp(addr, 1, r, amode);
7639668Slinton 		    addr += 1;
7649668Slinton 		    break;
7659668Slinton 
7669668Slinton 		case WORDDISP:
7679668Slinton 		case WORDDISPDEF:
7689668Slinton 		    argval = getdisp(addr, 2, r, amode);
7699668Slinton 		    addr += 2;
7709668Slinton 		    break;
7719668Slinton 
7729668Slinton 		case LONGDISP:
7739668Slinton 		case LONGDISPDEF:
7749668Slinton 		    argval = getdisp(addr, 4, r, amode);
7759668Slinton 		    addr += 4;
7769668Slinton 		    break;
7779668Slinton 	    }
7789668Slinton 	}
7799668Slinton 	if (ins == O_CALLS or ins == O_CALLG) {
7809668Slinton 	    argval += 2;
7819668Slinton 	}
7829668Slinton 	if (addrstatus == BRANCH) {
7839668Slinton 	    addr = argval;
7849668Slinton 	}
7859668Slinton     }
7869668Slinton     return addr;
7879668Slinton }
7889668Slinton 
7899668Slinton /*
7909668Slinton  * Get the displacement of an instruction that uses displacement addressing.
7919668Slinton  */
7929668Slinton 
7939668Slinton private int getdisp(addr, nbytes, reg, mode)
7949668Slinton Address addr;
7959668Slinton int nbytes;
7969668Slinton String reg;
7979668Slinton int mode;
7989668Slinton {
7999668Slinton     char byte;
8009668Slinton     short hword;
8019668Slinton     int argval;
8029668Slinton 
8039668Slinton     switch (nbytes) {
8049668Slinton 	case 1:
8059668Slinton 	    iread(&byte, addr, sizeof(byte));
8069668Slinton 	    argval = byte;
8079668Slinton 	    break;
8089668Slinton 
8099668Slinton 	case 2:
8109668Slinton 	    iread(&hword, addr, sizeof(hword));
8119668Slinton 	    argval = hword;
8129668Slinton 	    break;
8139668Slinton 
8149668Slinton 	case 4:
8159668Slinton 	    iread(&argval, addr, sizeof(argval));
8169668Slinton 	    break;
8179668Slinton     }
8189668Slinton     if (reg == regname[PROGCTR] && mode >= BYTEDISP) {
8199668Slinton 	argval += addr + nbytes;
8209668Slinton     }
8219668Slinton     return argval;
8229668Slinton }
8239668Slinton 
8249668Slinton #define BP_OP       O_BPT       /* breakpoint trap */
8259668Slinton #define BP_ERRNO    SIGTRAP     /* signal received at a breakpoint */
8269668Slinton 
8279668Slinton /*
8289668Slinton  * Setting a breakpoint at a location consists of saving
8299668Slinton  * the word at the location and poking a BP_OP there.
8309668Slinton  *
8319668Slinton  * We save the locations and words on a list for use in unsetting.
8329668Slinton  */
8339668Slinton 
8349668Slinton typedef struct Savelist *Savelist;
8359668Slinton 
8369668Slinton struct Savelist {
8379668Slinton     Address location;
8389668Slinton     Byte save;
8399668Slinton     Byte refcount;
8409668Slinton     Savelist link;
8419668Slinton };
8429668Slinton 
8439668Slinton private Savelist savelist;
8449668Slinton 
8459668Slinton /*
8469668Slinton  * Set a breakpoint at the given address.  Only save the word there
8479668Slinton  * if it's not already a breakpoint.
8489668Slinton  */
8499668Slinton 
8509668Slinton public setbp(addr)
8519668Slinton Address addr;
8529668Slinton {
8539668Slinton     Byte w;
8549668Slinton     Byte save;
8559668Slinton     register Savelist newsave, s;
8569668Slinton 
8579668Slinton     for (s = savelist; s != nil; s = s->link) {
8589668Slinton 	if (s->location == addr) {
8599668Slinton 	    s->refcount++;
8609668Slinton 	    return;
8619668Slinton 	}
8629668Slinton     }
86311174Slinton     iread(&save, addr, sizeof(save));
8649668Slinton     newsave = new(Savelist);
8659668Slinton     newsave->location = addr;
8669668Slinton     newsave->save = save;
8679668Slinton     newsave->refcount = 1;
8689668Slinton     newsave->link = savelist;
8699668Slinton     savelist = newsave;
8709668Slinton     w = BP_OP;
8719668Slinton     iwrite(&w, addr, sizeof(w));
8729668Slinton }
8739668Slinton 
8749668Slinton /*
8759668Slinton  * Unset a breakpoint; unfortunately we have to search the SAVELIST
8769668Slinton  * to find the saved value.  The assumption is that the SAVELIST will
8779668Slinton  * usually be quite small.
8789668Slinton  */
8799668Slinton 
8809668Slinton public unsetbp(addr)
8819668Slinton Address addr;
8829668Slinton {
8839668Slinton     register Savelist s, prev;
8849668Slinton 
8859668Slinton     prev = nil;
8869668Slinton     for (s = savelist; s != nil; s = s->link) {
8879668Slinton 	if (s->location == addr) {
8889668Slinton 	    iwrite(&s->save, addr, sizeof(s->save));
8899668Slinton 	    s->refcount--;
8909668Slinton 	    if (s->refcount == 0) {
8919668Slinton 		if (prev == nil) {
8929668Slinton 		    savelist = s->link;
8939668Slinton 		} else {
8949668Slinton 		    prev->link = s->link;
8959668Slinton 		}
8969668Slinton 		dispose(s);
8979668Slinton 	    }
8989668Slinton 	    return;
8999668Slinton 	}
9009668Slinton 	prev = s;
9019668Slinton     }
9029668Slinton     panic("unsetbp: couldn't find address %d", addr);
9039668Slinton }
9049668Slinton 
9059668Slinton /*
9069668Slinton  * Predicate to test if the reason the process stopped was because
9079668Slinton  * of a breakpoint.
9089668Slinton  */
9099668Slinton 
9109668Slinton public Boolean isbperr()
9119668Slinton {
9129668Slinton     return (Boolean) (not isfinished(process) and errnum(process) == SIGTRAP);
9139668Slinton }
9149668Slinton 
9159668Slinton /*
9169668Slinton  * Enter a procedure by creating and executing a call instruction.
9179668Slinton  */
9189668Slinton 
9199668Slinton #define CALLSIZE 7	/* size of call instruction */
9209668Slinton 
9219668Slinton public beginproc(p, argc)
9229668Slinton Symbol p;
9239668Slinton Integer argc;
9249668Slinton {
9259668Slinton     char save[CALLSIZE];
9269668Slinton     struct {
9279668Slinton 	VaxOpcode op;
9289668Slinton 	unsigned char numargs;
9299668Slinton 	unsigned char mode;
9309668Slinton 	char addr[sizeof(long)];	/* unaligned long */
9319668Slinton     } call;
9329668Slinton     long dest;
9339668Slinton 
9349668Slinton     pc = 2;
9359668Slinton     iread(save, pc, sizeof(save));
9369668Slinton     call.op = O_CALLS;
9379668Slinton     call.numargs = argc;
9389668Slinton     call.mode = 0xef;
9399668Slinton     dest = codeloc(p) - 2 - (pc + 7);
9409668Slinton     mov(&dest, call.addr, sizeof(call.addr));
9419668Slinton     iwrite(&call, pc, sizeof(call));
9429668Slinton     setreg(PROGCTR, pc);
943*16612Ssam     pstep(process, DEFSIG);
9449668Slinton     iwrite(save, pc, sizeof(save));
9459668Slinton     pc = reg(PROGCTR);
9469668Slinton     if (not isbperr()) {
9479668Slinton 	printstatus();
9489668Slinton     }
9499668Slinton }
950