xref: /csrg-svn/old/dbx/vax.c (revision 21608)
1*21608Sdist /*
2*21608Sdist  * Copyright (c) 1983 Regents of the University of California.
3*21608Sdist  * All rights reserved.  The Berkeley software License Agreement
4*21608Sdist  * specifies the terms and conditions for redistribution.
5*21608Sdist  */
69668Slinton 
7*21608Sdist #ifndef lint
8*21608Sdist static char sccsid[] = "@(#)vax.c	5.1 (Berkeley) 05/31/85";
9*21608Sdist #endif not lint
109668Slinton 
1118222Slinton static char rcsid[] = "$Header: machine.c,v 1.5 84/12/26 10:40:05 linton Exp $";
1218222Slinton 
139668Slinton /*
149668Slinton  * Target machine dependent stuff.
159668Slinton  */
169668Slinton 
179668Slinton #include "defs.h"
189668Slinton #include "machine.h"
199668Slinton #include "process.h"
2016612Ssam #include "runtime.h"
219668Slinton #include "events.h"
229668Slinton #include "main.h"
239668Slinton #include "symbols.h"
249668Slinton #include "source.h"
259668Slinton #include "mappings.h"
269668Slinton #include "object.h"
2718222Slinton #include "keywords.h"
289693Slinton #include "ops.h"
299668Slinton #include <signal.h>
309668Slinton 
319668Slinton #ifndef public
329668Slinton typedef unsigned int Address;
339668Slinton typedef unsigned char Byte;
349668Slinton typedef unsigned int Word;
359668Slinton 
369668Slinton #define NREG 16
379668Slinton 
389668Slinton #define ARGP 12
399668Slinton #define FRP 13
409668Slinton #define STKP 14
419668Slinton #define PROGCTR 15
429668Slinton 
439668Slinton #define BITSPERBYTE 8
449668Slinton #define BITSPERWORD (BITSPERBYTE * sizeof(Word))
459668Slinton 
469668Slinton #define nargspassed(frame) argn(0, frame)
479668Slinton 
489668Slinton #include "source.h"
499668Slinton #include "symbols.h"
509668Slinton 
519668Slinton Address pc;
529668Slinton Address prtaddr;
539668Slinton 
549668Slinton #endif
559668Slinton 
569668Slinton private Address printop();
579668Slinton 
589668Slinton /*
599668Slinton  * Decode and print the instructions within the given address range.
609668Slinton  */
619668Slinton 
629668Slinton public printinst(lowaddr, highaddr)
639668Slinton Address lowaddr;
649668Slinton Address highaddr;
659668Slinton {
669668Slinton     register Address addr;
679668Slinton 
689668Slinton     for (addr = lowaddr; addr <= highaddr; ) {
699668Slinton 	addr = printop(addr);
709668Slinton     }
719668Slinton     prtaddr = addr;
729668Slinton }
739668Slinton 
749668Slinton /*
759668Slinton  * Another approach:  print n instructions starting at the given address.
769668Slinton  */
779668Slinton 
789668Slinton public printninst(count, addr)
799668Slinton int count;
809668Slinton Address addr;
819668Slinton {
829668Slinton     register Integer i;
839668Slinton     register Address newaddr;
849668Slinton 
859668Slinton     if (count <= 0) {
869668Slinton 	error("non-positive repetition count");
879668Slinton     } else {
889668Slinton 	newaddr = addr;
899668Slinton 	for (i = 0; i < count; i++) {
909668Slinton 	    newaddr = printop(newaddr);
919668Slinton 	}
929668Slinton 	prtaddr = newaddr;
939668Slinton     }
949668Slinton }
959668Slinton 
969668Slinton /*
979668Slinton  * Hacked version of adb's VAX instruction decoder.
989668Slinton  */
999668Slinton 
1009668Slinton private Address printop(addr)
1019668Slinton Address addr;
1029668Slinton {
1039668Slinton     Optab op;
1049668Slinton     VaxOpcode ins;
1059668Slinton     unsigned char mode;
1069668Slinton     int argtype, amode, argno, argval;
1079668Slinton     String reg;
1089668Slinton     Boolean indexf;
1099668Slinton     short offset;
1109668Slinton 
1119668Slinton     argval = 0;
1129668Slinton     indexf = false;
1139668Slinton     printf("%08x  ", addr);
1149668Slinton     iread(&ins, addr, sizeof(ins));
1159668Slinton     addr += 1;
1169668Slinton     op = optab[ins];
1179668Slinton     printf("%s", op.iname);
1189668Slinton     for (argno = 0; argno < op.numargs; argno++) {
1199668Slinton 	if (indexf == true) {
1209668Slinton 	    indexf = false;
1219668Slinton 	} else if (argno == 0) {
1229668Slinton 	    printf("\t");
1239668Slinton 	} else {
1249668Slinton 	    printf(",");
1259668Slinton 	}
1269668Slinton 	argtype = op.argtype[argno];
1279668Slinton 	if (is_branch_disp(argtype)) {
1289668Slinton 	    mode = 0xAF + (typelen(argtype) << 5);
1299668Slinton 	} else {
1309668Slinton 	    iread(&mode, addr, sizeof(mode));
1319668Slinton 	    addr += 1;
1329668Slinton 	}
1339668Slinton 	reg = regname[regnm(mode)];
1349668Slinton 	amode = addrmode(mode);
1359668Slinton 	switch (amode) {
1369668Slinton 	    case LITSHORT:
1379668Slinton 	    case LITUPTO31:
1389668Slinton 	    case LITUPTO47:
1399668Slinton 	    case LITUPTO63:
1409668Slinton 		if (typelen(argtype) == TYPF || typelen(argtype) ==TYPD)
1419668Slinton 		    printf("$%s", fltimm[mode]);
1429668Slinton 		else
1439668Slinton 		    printf("$%x", mode);
1449668Slinton 		argval = mode;
1459668Slinton 		break;
1469668Slinton 
1479668Slinton 	    case INDEX:
1489668Slinton 		printf("[%s]", reg);
1499668Slinton 		indexf = true;
1509668Slinton 		argno--;
1519668Slinton 		break;
1529668Slinton 
1539668Slinton 	    case REG:
1549668Slinton 		printf("%s", reg);
1559668Slinton 		break;
1569668Slinton 
1579668Slinton 	    case REGDEF:
1589668Slinton 		printf("(%s)", reg);
1599668Slinton 		break;
1609668Slinton 
1619668Slinton 	    case AUTODEC:
1629668Slinton 		printf("-(%s)", reg);
1639668Slinton 		break;
1649668Slinton 
1659668Slinton 	    case AUTOINC:
1669668Slinton 		if (reg != regname[PROGCTR]) {
1679668Slinton 		    printf("(%s)+", reg);
1689668Slinton 		} else {
1699668Slinton 		    printf("$");
1709668Slinton 		    switch (typelen(argtype)) {
1719668Slinton 			case TYPB:
1729668Slinton 			    argval = printdisp(addr, 1, reg, amode);
1739668Slinton 			    addr += 1;
1749668Slinton 			    break;
1759668Slinton 
1769668Slinton 			case TYPW:
1779668Slinton 			    argval = printdisp(addr, 2, reg, amode);
1789668Slinton 			    addr += 2;
1799668Slinton 			    break;
1809668Slinton 
1819668Slinton 			case TYPL:
1829668Slinton 			    argval = printdisp(addr, 4, reg, amode);
1839668Slinton 			    addr += 4;
1849668Slinton 			    break;
1859668Slinton 
1869668Slinton 			case TYPF:
1879668Slinton 			    iread(&argval, addr, sizeof(argval));
1889668Slinton 			    printf("%06x", argval);
1899668Slinton 			    addr += 4;
1909668Slinton 			    break;
1919668Slinton 
1929668Slinton 			case TYPQ:
1939668Slinton 			case TYPD:
1949668Slinton 			    iread(&argval, addr, sizeof(argval));
1959668Slinton 			    printf("%06x", argval);
1969668Slinton 			    iread(&argval, addr+4, sizeof(argval));
1979668Slinton 			    printf("%06x", argval);
1989668Slinton 			    addr += 8;
1999668Slinton 			    break;
2009668Slinton 		    }
2019668Slinton 		}
2029668Slinton 		break;
2039668Slinton 
2049668Slinton 	    case AUTOINCDEF:
2059668Slinton 		if (reg == regname[PROGCTR]) {
2069668Slinton 		    printf("*$");
2079668Slinton 		    argval = printdisp(addr, 4, reg, amode);
2089668Slinton 		    addr += 4;
2099668Slinton 		} else {
2109668Slinton 		    printf("*(%s)+", reg);
2119668Slinton 		}
2129668Slinton 		break;
2139668Slinton 
2149668Slinton 	    case BYTEDISP:
2159668Slinton 		argval = printdisp(addr, 1, reg, amode);
2169668Slinton 		addr += 1;
2179668Slinton 		break;
2189668Slinton 
2199668Slinton 	    case BYTEDISPDEF:
2209668Slinton 		printf("*");
2219668Slinton 		argval = printdisp(addr, 1, reg, amode);
2229668Slinton 		addr += 1;
2239668Slinton 		break;
2249668Slinton 
2259668Slinton 	    case WORDDISP:
2269668Slinton 		argval = printdisp(addr, 2, reg, amode);
2279668Slinton 		addr += 2;
2289668Slinton 		break;
2299668Slinton 
2309668Slinton 	    case WORDDISPDEF:
2319668Slinton 		printf("*");
2329668Slinton 		argval = printdisp(addr, 2, reg, amode);
2339668Slinton 		addr += 2;
2349668Slinton 		break;
2359668Slinton 
2369668Slinton 	    case LONGDISP:
2379668Slinton 		argval = printdisp(addr, 4, reg, amode);
2389668Slinton 		addr += 4;
2399668Slinton 		break;
2409668Slinton 
2419668Slinton 	    case LONGDISPDEF:
2429668Slinton 		printf("*");
2439668Slinton 		argval = printdisp(addr, 4, reg, amode);
2449668Slinton 		addr += 4;
2459668Slinton 		break;
2469668Slinton 	}
2479668Slinton     }
2489668Slinton     if (ins == O_CASEB || ins == O_CASEW || ins == O_CASEL) {
2499668Slinton 	for (argno = 0; argno <= argval; argno++) {
2509668Slinton 	    iread(&offset, addr, sizeof(offset));
2519668Slinton 	    printf("\n\t\t%d", offset);
2529668Slinton 	    addr += 2;
2539668Slinton 	}
2549668Slinton     }
2559668Slinton     printf("\n");
2569668Slinton     return addr;
2579668Slinton }
2589668Slinton 
2599668Slinton /*
2609668Slinton  * Print the displacement of an instruction that uses displacement
2619668Slinton  * addressing.
2629668Slinton  */
2639668Slinton 
2649668Slinton private int printdisp(addr, nbytes, reg, mode)
2659668Slinton Address addr;
2669668Slinton int nbytes;
2679668Slinton char *reg;
2689668Slinton int mode;
2699668Slinton {
2709668Slinton     char byte;
2719668Slinton     short hword;
2729668Slinton     int argval;
27314338Slinton     Symbol f;
2749668Slinton 
2759668Slinton     switch (nbytes) {
2769668Slinton 	case 1:
2779668Slinton 	    iread(&byte, addr, sizeof(byte));
2789668Slinton 	    argval = byte;
2799668Slinton 	    break;
2809668Slinton 
2819668Slinton 	case 2:
2829668Slinton 	    iread(&hword, addr, sizeof(hword));
2839668Slinton 	    argval = hword;
2849668Slinton 	    break;
2859668Slinton 
2869668Slinton 	case 4:
2879668Slinton 	    iread(&argval, addr, sizeof(argval));
2889668Slinton 	    break;
2899668Slinton     }
2909668Slinton     if (reg == regname[PROGCTR] && mode >= BYTEDISP) {
2919668Slinton 	argval += addr + nbytes;
2929668Slinton     }
2939668Slinton     if (reg == regname[PROGCTR]) {
29414338Slinton 	f = whatblock((Address) argval + 2);
29514338Slinton 	if (codeloc(f) == argval + 2) {
29614338Slinton 	    printf("%s", symname(f));
29714338Slinton 	} else {
29814338Slinton 	    printf("%x", argval);
29914338Slinton 	}
3009668Slinton     } else {
30118222Slinton 	if (varIsSet("$hexoffsets")) {
30218222Slinton 	    if (argval < 0) {
30318222Slinton 		printf("-%x(%s)", -(argval), reg);
30418222Slinton 	    } else {
30518222Slinton 		printf("%x(%s)", argval, reg);
30618222Slinton 	    }
30718222Slinton 	} else {
30818222Slinton 	    printf("%d(%s)", argval, reg);
30918222Slinton 	}
3109668Slinton     }
3119668Slinton     return argval;
3129668Slinton }
3139668Slinton 
3149668Slinton /*
3159668Slinton  * Print the contents of the addresses within the given range
3169668Slinton  * according to the given format.
3179668Slinton  */
3189668Slinton 
3199668Slinton typedef struct {
3209668Slinton     String name;
3219668Slinton     String printfstring;
3229668Slinton     int length;
3239668Slinton } Format;
3249668Slinton 
3259668Slinton private Format fmt[] = {
3269668Slinton     { "d", " %d", sizeof(short) },
3279668Slinton     { "D", " %ld", sizeof(long) },
3289668Slinton     { "o", " %o", sizeof(short) },
3299668Slinton     { "O", " %lo", sizeof(long) },
3309668Slinton     { "x", " %04x", sizeof(short) },
3319668Slinton     { "X", " %08x", sizeof(long) },
3329668Slinton     { "b", " \\%o", sizeof(char) },
3339668Slinton     { "c", " '%c'", sizeof(char) },
3349668Slinton     { "s", "%c", sizeof(char) },
33514338Slinton     { "f", " %f", sizeof(float) },
3369668Slinton     { "g", " %g", sizeof(double) },
3379668Slinton     { nil, nil, 0 }
3389668Slinton };
3399668Slinton 
34011174Slinton private Format *findformat(s)
34111174Slinton String s;
34211174Slinton {
34311174Slinton     register Format *f;
34411174Slinton 
34511174Slinton     f = &fmt[0];
34611174Slinton     while (f->name != nil and not streq(f->name, s)) {
34711174Slinton 	++f;
34811174Slinton     }
34911174Slinton     if (f->name == nil) {
35011174Slinton 	error("bad print format \"%s\"", s);
35111174Slinton     }
35211174Slinton     return f;
35311174Slinton }
35411174Slinton 
3559668Slinton public Address printdata(lowaddr, highaddr, format)
3569668Slinton Address lowaddr;
3579668Slinton Address highaddr;
3589668Slinton String format;
3599668Slinton {
3609668Slinton     register int n;
3619668Slinton     register Address addr;
3629668Slinton     register Format *f;
3639668Slinton     int value;
3649668Slinton 
3659668Slinton     if (lowaddr > highaddr) {
3669668Slinton 	error("first address larger than second");
3679668Slinton     }
36811174Slinton     f = findformat(format);
3699668Slinton     n = 0;
3709668Slinton     value = 0;
3719668Slinton     for (addr = lowaddr; addr <= highaddr; addr += f->length) {
3729668Slinton 	if (n == 0) {
3739668Slinton 	    printf("%08x: ", addr);
3749668Slinton 	}
3759668Slinton 	dread(&value, addr, f->length);
3769668Slinton 	printf(f->printfstring, value);
3779668Slinton 	++n;
3789668Slinton 	if (n >= (16 div f->length)) {
3799668Slinton 	    putchar('\n');
3809668Slinton 	    n = 0;
3819668Slinton 	}
3829668Slinton     }
3839668Slinton     if (n != 0) {
3849668Slinton 	putchar('\n');
3859668Slinton     }
3869668Slinton     prtaddr = addr;
3879668Slinton     return addr;
3889668Slinton }
3899668Slinton 
3909668Slinton /*
3919668Slinton  * The other approach is to print n items starting with a given address.
3929668Slinton  */
3939668Slinton 
3949668Slinton public printndata(count, startaddr, format)
3959668Slinton int count;
3969668Slinton Address startaddr;
3979668Slinton String format;
3989668Slinton {
3999668Slinton     register int i, n;
4009668Slinton     register Address addr;
4019668Slinton     register Format *f;
4029668Slinton     register Boolean isstring;
40314338Slinton     char c;
40414338Slinton     union {
40514338Slinton 	char charv;
40614338Slinton 	short shortv;
40714338Slinton 	int intv;
40814338Slinton 	float floatv;
40914338Slinton 	double doublev;
41014338Slinton     } value;
4119668Slinton 
4129668Slinton     if (count <= 0) {
4139668Slinton 	error("non-positive repetition count");
4149668Slinton     }
41511174Slinton     f = findformat(format);
4169668Slinton     isstring = (Boolean) streq(f->name, "s");
4179668Slinton     n = 0;
4189668Slinton     addr = startaddr;
41914338Slinton     value.intv = 0;
4209668Slinton     for (i = 0; i < count; i++) {
4219668Slinton 	if (n == 0) {
4229668Slinton 	    printf("%08x: ", addr);
4239668Slinton 	}
4249668Slinton 	if (isstring) {
4259668Slinton 	    putchar('"');
42614338Slinton 	    dread(&c, addr, sizeof(char));
42714338Slinton 	    while (c != '\0') {
42814338Slinton 		printchar(c);
4299668Slinton 		++addr;
43014338Slinton 		dread(&c, addr, sizeof(char));
4319668Slinton 	    }
4329668Slinton 	    putchar('"');
4339668Slinton 	    putchar('\n');
4349668Slinton 	    n = 0;
4359668Slinton 	    addr += sizeof(String);
4369668Slinton 	} else {
4379668Slinton 	    dread(&value, addr, f->length);
4389668Slinton 	    printf(f->printfstring, value);
4399668Slinton 	    ++n;
4409668Slinton 	    if (n >= (16 div f->length)) {
4419668Slinton 		putchar('\n');
4429668Slinton 		n = 0;
4439668Slinton 	    }
4449668Slinton 	    addr += f->length;
4459668Slinton 	}
4469668Slinton     }
4479668Slinton     if (n != 0) {
4489668Slinton 	putchar('\n');
4499668Slinton     }
4509668Slinton     prtaddr = addr;
4519668Slinton }
4529668Slinton 
4539668Slinton /*
45411174Slinton  * Print out a value according to the given format.
45511174Slinton  */
45611174Slinton 
45711174Slinton public printvalue(v, format)
45811174Slinton long v;
45911174Slinton String format;
46011174Slinton {
46111174Slinton     Format *f;
46211174Slinton     char *p, *q;
46311174Slinton 
46411174Slinton     f = findformat(format);
46511174Slinton     if (streq(f->name, "s")) {
46611174Slinton 	putchar('"');
46711174Slinton 	p = (char *) &v;
46811174Slinton 	q = p + sizeof(v);
46911174Slinton 	while (p < q) {
47011174Slinton 	    printchar(*p);
47111174Slinton 	    ++p;
47211174Slinton 	}
47311174Slinton 	putchar('"');
47411174Slinton     } else {
47511174Slinton 	printf(f->printfstring, v);
47611174Slinton     }
47711174Slinton     putchar('\n');
47811174Slinton }
47911174Slinton 
48011174Slinton /*
4819668Slinton  * Print out an execution time error.
4829842Slinton  * Assumes the source position of the error has been calculated.
4839668Slinton  *
4849668Slinton  * Have to check if the -r option was specified; if so then
4859668Slinton  * the object file information hasn't been read in yet.
4869668Slinton  */
4879668Slinton 
4889668Slinton public printerror()
4899668Slinton {
4909668Slinton     extern Integer sys_nsig;
4919668Slinton     extern String sys_siglist[];
49218222Slinton     integer err;
4939668Slinton 
4949668Slinton     if (isfinished(process)) {
49516932Ssam 	err = exitcode(process);
49618222Slinton 	if (err == 0) {
49718222Slinton 	    printf("\"%s\" terminated normally\n", objname);
49818222Slinton 	} else {
49918222Slinton 	    printf("\"%s\" terminated abnormally (exit code %d)\n",
50018222Slinton 		objname, err
50118222Slinton 	    );
50218222Slinton 	}
5039668Slinton 	erecover();
5049668Slinton     }
5059668Slinton     if (runfirst) {
50618222Slinton 	fprintf(stderr, "Entering debugger ...\n");
5079668Slinton 	init();
5089668Slinton     }
5099668Slinton     err = errnum(process);
5109668Slinton     putchar('\n');
51116932Ssam     printsig(err);
51218222Slinton     putchar(' ');
51316932Ssam     printloc();
51416932Ssam     putchar('\n');
5159668Slinton     if (curline > 0) {
5169668Slinton 	printlines(curline, curline);
5179668Slinton     } else {
5189668Slinton 	printinst(pc, pc);
5199668Slinton     }
5209668Slinton     erecover();
5219668Slinton }
5229668Slinton 
52318222Slinton /*
52418222Slinton  * Print out a signal.
52518222Slinton  */
52618222Slinton 
52716932Ssam private String illinames[] = {
52818222Slinton     "reserved addressing fault",
52918222Slinton     "priviliged instruction fault",
53018222Slinton     "reserved operand fault"
53116932Ssam };
53218222Slinton 
53316932Ssam private String fpenames[] = {
53418222Slinton     nil,
53518222Slinton     "integer overflow trap",
53618222Slinton     "integer divide by zero trap",
53718222Slinton     "floating overflow trap",
53818222Slinton     "floating/decimal divide by zero trap",
53918222Slinton     "floating underflow trap",
54018222Slinton     "decimal overflow trap",
54118222Slinton     "subscript out of range trap",
54218222Slinton     "floating overflow fault",
54318222Slinton     "floating divide by zero fault",
54418222Slinton     "floating undeflow fault"
54516932Ssam };
54616932Ssam 
54718222Slinton public printsig (signo)
54818222Slinton integer signo;
54916932Ssam {
55018222Slinton     integer code;
55116932Ssam 
55218222Slinton     if (signo < 0 or signo > sys_nsig) {
55318222Slinton 	printf("[signal %d]", signo);
55418222Slinton     } else {
55518222Slinton 	printf("%s", sys_siglist[signo]);
55616932Ssam     }
55718222Slinton     code = errcode(process);
55818222Slinton     if (signo == SIGILL) {
55918222Slinton 	if (code >= 0 and code < sizeof(illinames) / sizeof(illinames[0])) {
56018222Slinton 	    printf(" (%s)", illinames[code]);
56118222Slinton 	}
56218222Slinton     } else if (signo == SIGFPE) {
56318222Slinton 	if (code > 0 and code < sizeof(fpenames) / sizeof(fpenames[0])) {
56418222Slinton 	    printf(" (%s)", fpenames[code]);
56518222Slinton 	}
56618222Slinton     }
56716932Ssam }
56816932Ssam 
5699668Slinton /*
5709668Slinton  * Note the termination of the program.  We do this so as to avoid
5719668Slinton  * having the process exit, which would make the values of variables
5729668Slinton  * inaccessible.  We do want to flush all output buffers here,
5739668Slinton  * otherwise it'll never get done.
5749668Slinton  */
5759668Slinton 
5769668Slinton public endprogram()
5779668Slinton {
5789668Slinton     Integer exitcode;
5799668Slinton 
5809668Slinton     stepto(nextaddr(pc, true));
5819668Slinton     printnews();
5829668Slinton     exitcode = argn(1, nil);
58318222Slinton     if (exitcode != 0) {
58418222Slinton 	printf("\nexecution completed (exit code %d)\n", exitcode);
58518222Slinton     } else {
58618222Slinton 	printf("\nexecution completed\n");
58718222Slinton     }
5889668Slinton     getsrcpos();
5899668Slinton     erecover();
5909668Slinton }
5919668Slinton 
5929668Slinton /*
5939668Slinton  * Single step the machine a source line (or instruction if "inst_tracing"
59410621Slinton  * is true).  If "isnext" is true, skip over procedure calls.
5959668Slinton  */
5969668Slinton 
5979668Slinton private Address getcall();
5989668Slinton 
5999668Slinton public dostep(isnext)
6009668Slinton Boolean isnext;
6019668Slinton {
6029668Slinton     register Address addr;
6039668Slinton     register Lineno line;
6049668Slinton     String filename;
60518222Slinton     Address startaddr;
6069668Slinton 
60716612Ssam     startaddr = pc;
6089668Slinton     addr = nextaddr(pc, isnext);
60910621Slinton     if (not inst_tracing and nlhdr.nlines != 0) {
6109668Slinton 	line = linelookup(addr);
6119668Slinton 	while (line == 0) {
61218222Slinton 	    addr = nextaddr(addr, isnext);
6139668Slinton 	    line = linelookup(addr);
6149668Slinton 	}
61510621Slinton 	curline = line;
61610621Slinton     } else {
61710621Slinton 	curline = 0;
6189668Slinton     }
6199668Slinton     stepto(addr);
6209668Slinton     filename = srcfilename(addr);
6219668Slinton     setsource(filename);
6229668Slinton }
6239668Slinton 
6249668Slinton /*
6259668Slinton  * Compute the next address that will be executed from the given one.
6269668Slinton  * If "isnext" is true then consider a procedure call as straight line code.
6279668Slinton  *
6289668Slinton  * We must unfortunately do much of the same work that is necessary
6299668Slinton  * to print instructions.  In addition we have to deal with branches.
6309668Slinton  * Unconditional branches we just follow, for conditional branches
6319668Slinton  * we continue execution to the current location and then single step
6329668Slinton  * the machine.  We assume that the last argument in an instruction
6339668Slinton  * that branches is the branch address (or relative offset).
6349668Slinton  */
6359668Slinton 
63618222Slinton private Address findnextaddr();
63718222Slinton 
6389668Slinton public Address nextaddr(startaddr, isnext)
6399668Slinton Address startaddr;
64016612Ssam boolean isnext;
64116612Ssam {
64216612Ssam     Address addr;
64316612Ssam 
64416612Ssam     addr = usignal(process);
64516612Ssam     if (addr == 0 or addr == 1) {
64616612Ssam 	addr = findnextaddr(startaddr, isnext);
64716612Ssam     }
64816612Ssam     return addr;
64916612Ssam }
65016612Ssam 
65118222Slinton /*
65218222Slinton  * Determine if it's ok to skip function f entered by instruction ins.
65318222Slinton  * If so, we're going to compute the return address and step to it.
65418222Slinton  * Therefore we cannot skip over a function entered by a jsb or bsb,
65518222Slinton  * since the return address is not easily computed for them.
65618222Slinton  */
65718222Slinton 
65818222Slinton private boolean skipfunc (ins, f)
65918222Slinton VaxOpcode ins;
66018222Slinton Symbol f;
66118222Slinton {
66218222Slinton     boolean b;
66318222Slinton 
66418222Slinton     b = (boolean) (
66518222Slinton 	ins != O_JSB and ins != O_BSBB and ins != O_BSBW and
66618222Slinton 	not inst_tracing and nlhdr.nlines != 0 and
66718222Slinton 	nosource(curfunc) and canskip(curfunc)
66818222Slinton     );
66918222Slinton     return b;
67018222Slinton }
67118222Slinton 
67216612Ssam private Address findnextaddr(startaddr, isnext)
67316612Ssam Address startaddr;
6749668Slinton Boolean isnext;
6759668Slinton {
6769668Slinton     register Address addr;
6779668Slinton     Optab op;
6789668Slinton     VaxOpcode ins;
6799668Slinton     unsigned char mode;
6809668Slinton     int argtype, amode, argno, argval;
6819668Slinton     String r;
6829668Slinton     Boolean indexf;
6839668Slinton     enum { KNOWN, SEQUENTIAL, BRANCH } addrstatus;
6849668Slinton 
6859668Slinton     argval = 0;
6869668Slinton     indexf = false;
6879668Slinton     addr = startaddr;
6889668Slinton     iread(&ins, addr, sizeof(ins));
6899668Slinton     switch (ins) {
69018222Slinton 	/*
69118222Slinton 	 * It used to be that unconditional jumps and branches were handled
69218222Slinton 	 * by taking their destination address as the next address.  While
69318222Slinton 	 * saving the cost of starting up the process, this approach
69418222Slinton 	 * doesn't work when jumping indirect (since the value in the
69518222Slinton 	 * register might not yet have been set).
69618222Slinton 	 *
69718222Slinton 	 * So unconditional jumps and branches are now handled the same way
69818222Slinton 	 * as conditional jumps and branches.
69918222Slinton 	 *
7009668Slinton 	case O_BRB:
7019668Slinton 	case O_BRW:
7029668Slinton 	    addrstatus = BRANCH;
7039668Slinton 	    break;
70418222Slinton 	 *
70518222Slinton 	 */
7069668Slinton 
7079668Slinton 	case O_BSBB:
7089668Slinton 	case O_BSBW:
7099668Slinton 	case O_JSB:
7109668Slinton 	case O_CALLG:
7119668Slinton 	case O_CALLS:
71218222Slinton 	    addrstatus = KNOWN;
71318222Slinton 	    stepto(addr);
71418222Slinton 	    pstep(process, DEFSIG);
71518222Slinton 	    addr = reg(PROGCTR);
71618222Slinton 	    pc = addr;
71718222Slinton 	    setcurfunc(whatblock(pc));
71818222Slinton 	    if (not isbperr()) {
71918222Slinton 		printstatus();
72018222Slinton 		/* NOTREACHED */
72118222Slinton 	    }
72218222Slinton 	    bpact();
72318222Slinton 	    if (isnext or skipfunc(ins, curfunc)) {
7249668Slinton 		addrstatus = KNOWN;
72518222Slinton 		addr = return_addr();
7269668Slinton 		stepto(addr);
72711864Slinton 		bpact();
72818222Slinton 	    } else {
72918222Slinton 		callnews(/* iscall = */ true);
7309668Slinton 	    }
7319668Slinton 	    break;
7329668Slinton 
7339668Slinton 	case O_RSB:
7349668Slinton 	case O_RET:
7359668Slinton 	    addrstatus = KNOWN;
73618222Slinton 	    stepto(addr);
7379668Slinton 	    callnews(/* iscall = */ false);
73818222Slinton 	    pstep(process, DEFSIG);
73918222Slinton 	    addr = reg(PROGCTR);
74018222Slinton 	    pc = addr;
74118222Slinton 	    if (not isbperr()) {
74218222Slinton 		printstatus();
74316612Ssam 	    }
74411874Slinton 	    bpact();
7459668Slinton 	    break;
7469668Slinton 
74718222Slinton 	case O_BRB: case O_BRW:
74816612Ssam 	case O_JMP: /* because it may be jmp (r1) */
7499668Slinton 	case O_BNEQ: case O_BEQL: case O_BGTR:
7509668Slinton 	case O_BLEQ: case O_BGEQ: case O_BLSS:
7519668Slinton 	case O_BGTRU: case O_BLEQU: case O_BVC:
7529668Slinton 	case O_BVS: case O_BCC: case O_BCS:
7539668Slinton 	case O_CASEB: case O_CASEW: case O_CASEL:
7549668Slinton 	case O_BBS: case O_BBC: case O_BBSS: case O_BBCS:
7559668Slinton 	case O_BBSC: case O_BBCC: case O_BBSSI:
7569668Slinton 	case O_BBCCI: case O_BLBS: case O_BLBC:
7579668Slinton 	case O_ACBL: case O_AOBLSS: case O_AOBLEQ:
7589668Slinton 	case O_SOBGEQ: case O_SOBGTR:
7599668Slinton 	    addrstatus = KNOWN;
7609668Slinton 	    stepto(addr);
76116612Ssam 	    pstep(process, DEFSIG);
7629668Slinton 	    addr = reg(PROGCTR);
7639668Slinton 	    pc = addr;
7649668Slinton 	    if (not isbperr()) {
7659668Slinton 		printstatus();
7669668Slinton 	    }
7679668Slinton 	    break;
7689668Slinton 
7699668Slinton 	default:
7709668Slinton 	    addrstatus = SEQUENTIAL;
7719668Slinton 	    break;
7729668Slinton     }
7739668Slinton     if (addrstatus != KNOWN) {
7749668Slinton 	addr += 1;
7759668Slinton 	op = optab[ins];
7769668Slinton 	for (argno = 0; argno < op.numargs; argno++) {
7779668Slinton 	    if (indexf == true) {
7789668Slinton 		indexf = false;
7799668Slinton 	    }
7809668Slinton 	    argtype = op.argtype[argno];
7819668Slinton 	    if (is_branch_disp(argtype)) {
7829668Slinton 		mode = 0xAF + (typelen(argtype) << 5);
7839668Slinton 	    } else {
7849668Slinton 		iread(&mode, addr, sizeof(mode));
7859668Slinton 		addr += 1;
7869668Slinton 	    }
7879668Slinton 	    r = regname[regnm(mode)];
7889668Slinton 	    amode = addrmode(mode);
7899668Slinton 	    switch (amode) {
7909668Slinton 		case LITSHORT:
7919668Slinton 		case LITUPTO31:
7929668Slinton 		case LITUPTO47:
7939668Slinton 		case LITUPTO63:
7949668Slinton 		    argval = mode;
7959668Slinton 		    break;
7969668Slinton 
7979668Slinton 		case INDEX:
7989668Slinton 		    indexf = true;
7999668Slinton 		    --argno;
8009668Slinton 		    break;
8019668Slinton 
8029668Slinton 		case REG:
8039668Slinton 		case REGDEF:
8049668Slinton 		case AUTODEC:
8059668Slinton 		    break;
8069668Slinton 
8079668Slinton 		case AUTOINC:
8089668Slinton 		    if (r == regname[PROGCTR]) {
8099668Slinton 			switch (typelen(argtype)) {
8109668Slinton 			    case TYPB:
8119668Slinton 				argval = getdisp(addr, 1, r, amode);
8129668Slinton 				addr += 1;
8139668Slinton 				break;
8149668Slinton 
8159668Slinton 			    case TYPW:
8169668Slinton 				argval = getdisp(addr, 2, r, amode);
8179668Slinton 				addr += 2;
8189668Slinton 				break;
8199668Slinton 
8209668Slinton 			    case TYPL:
8219668Slinton 				argval = getdisp(addr, 4, r, amode);
8229668Slinton 				addr += 4;
8239668Slinton 				break;
8249668Slinton 
8259668Slinton 			    case TYPF:
8269668Slinton 				iread(&argval, addr, sizeof(argval));
8279668Slinton 				addr += 4;
8289668Slinton 				break;
8299668Slinton 
8309668Slinton 			    case TYPQ:
8319668Slinton 			    case TYPD:
8329668Slinton 				iread(&argval, addr+4, sizeof(argval));
8339668Slinton 				addr += 8;
8349668Slinton 				break;
8359668Slinton 			}
8369668Slinton 		    }
8379668Slinton 		    break;
8389668Slinton 
8399668Slinton 		case AUTOINCDEF:
8409668Slinton 		    if (r == regname[PROGCTR]) {
8419668Slinton 			argval = getdisp(addr, 4, r, amode);
8429668Slinton 			addr += 4;
8439668Slinton 		    }
8449668Slinton 		    break;
8459668Slinton 
8469668Slinton 		case BYTEDISP:
8479668Slinton 		case BYTEDISPDEF:
8489668Slinton 		    argval = getdisp(addr, 1, r, amode);
8499668Slinton 		    addr += 1;
8509668Slinton 		    break;
8519668Slinton 
8529668Slinton 		case WORDDISP:
8539668Slinton 		case WORDDISPDEF:
8549668Slinton 		    argval = getdisp(addr, 2, r, amode);
8559668Slinton 		    addr += 2;
8569668Slinton 		    break;
8579668Slinton 
8589668Slinton 		case LONGDISP:
8599668Slinton 		case LONGDISPDEF:
8609668Slinton 		    argval = getdisp(addr, 4, r, amode);
8619668Slinton 		    addr += 4;
8629668Slinton 		    break;
8639668Slinton 	    }
8649668Slinton 	}
8659668Slinton 	if (ins == O_CALLS or ins == O_CALLG) {
8669668Slinton 	    argval += 2;
8679668Slinton 	}
8689668Slinton 	if (addrstatus == BRANCH) {
8699668Slinton 	    addr = argval;
8709668Slinton 	}
8719668Slinton     }
8729668Slinton     return addr;
8739668Slinton }
8749668Slinton 
8759668Slinton /*
8769668Slinton  * Get the displacement of an instruction that uses displacement addressing.
8779668Slinton  */
8789668Slinton 
8799668Slinton private int getdisp(addr, nbytes, reg, mode)
8809668Slinton Address addr;
8819668Slinton int nbytes;
8829668Slinton String reg;
8839668Slinton int mode;
8849668Slinton {
8859668Slinton     char byte;
8869668Slinton     short hword;
8879668Slinton     int argval;
8889668Slinton 
8899668Slinton     switch (nbytes) {
8909668Slinton 	case 1:
8919668Slinton 	    iread(&byte, addr, sizeof(byte));
8929668Slinton 	    argval = byte;
8939668Slinton 	    break;
8949668Slinton 
8959668Slinton 	case 2:
8969668Slinton 	    iread(&hword, addr, sizeof(hword));
8979668Slinton 	    argval = hword;
8989668Slinton 	    break;
8999668Slinton 
9009668Slinton 	case 4:
9019668Slinton 	    iread(&argval, addr, sizeof(argval));
9029668Slinton 	    break;
9039668Slinton     }
9049668Slinton     if (reg == regname[PROGCTR] && mode >= BYTEDISP) {
9059668Slinton 	argval += addr + nbytes;
9069668Slinton     }
9079668Slinton     return argval;
9089668Slinton }
9099668Slinton 
9109668Slinton #define BP_OP       O_BPT       /* breakpoint trap */
9119668Slinton #define BP_ERRNO    SIGTRAP     /* signal received at a breakpoint */
9129668Slinton 
9139668Slinton /*
9149668Slinton  * Setting a breakpoint at a location consists of saving
9159668Slinton  * the word at the location and poking a BP_OP there.
9169668Slinton  *
9179668Slinton  * We save the locations and words on a list for use in unsetting.
9189668Slinton  */
9199668Slinton 
9209668Slinton typedef struct Savelist *Savelist;
9219668Slinton 
9229668Slinton struct Savelist {
9239668Slinton     Address location;
9249668Slinton     Byte save;
9259668Slinton     Byte refcount;
9269668Slinton     Savelist link;
9279668Slinton };
9289668Slinton 
9299668Slinton private Savelist savelist;
9309668Slinton 
9319668Slinton /*
9329668Slinton  * Set a breakpoint at the given address.  Only save the word there
9339668Slinton  * if it's not already a breakpoint.
9349668Slinton  */
9359668Slinton 
9369668Slinton public setbp(addr)
9379668Slinton Address addr;
9389668Slinton {
9399668Slinton     Byte w;
9409668Slinton     Byte save;
9419668Slinton     register Savelist newsave, s;
9429668Slinton 
9439668Slinton     for (s = savelist; s != nil; s = s->link) {
9449668Slinton 	if (s->location == addr) {
9459668Slinton 	    s->refcount++;
9469668Slinton 	    return;
9479668Slinton 	}
9489668Slinton     }
94911174Slinton     iread(&save, addr, sizeof(save));
9509668Slinton     newsave = new(Savelist);
9519668Slinton     newsave->location = addr;
9529668Slinton     newsave->save = save;
9539668Slinton     newsave->refcount = 1;
9549668Slinton     newsave->link = savelist;
9559668Slinton     savelist = newsave;
9569668Slinton     w = BP_OP;
9579668Slinton     iwrite(&w, addr, sizeof(w));
9589668Slinton }
9599668Slinton 
9609668Slinton /*
9619668Slinton  * Unset a breakpoint; unfortunately we have to search the SAVELIST
9629668Slinton  * to find the saved value.  The assumption is that the SAVELIST will
9639668Slinton  * usually be quite small.
9649668Slinton  */
9659668Slinton 
9669668Slinton public unsetbp(addr)
9679668Slinton Address addr;
9689668Slinton {
9699668Slinton     register Savelist s, prev;
9709668Slinton 
9719668Slinton     prev = nil;
9729668Slinton     for (s = savelist; s != nil; s = s->link) {
9739668Slinton 	if (s->location == addr) {
9749668Slinton 	    iwrite(&s->save, addr, sizeof(s->save));
9759668Slinton 	    s->refcount--;
9769668Slinton 	    if (s->refcount == 0) {
9779668Slinton 		if (prev == nil) {
9789668Slinton 		    savelist = s->link;
9799668Slinton 		} else {
9809668Slinton 		    prev->link = s->link;
9819668Slinton 		}
9829668Slinton 		dispose(s);
9839668Slinton 	    }
9849668Slinton 	    return;
9859668Slinton 	}
9869668Slinton 	prev = s;
9879668Slinton     }
9889668Slinton     panic("unsetbp: couldn't find address %d", addr);
9899668Slinton }
9909668Slinton 
9919668Slinton /*
9929668Slinton  * Enter a procedure by creating and executing a call instruction.
9939668Slinton  */
9949668Slinton 
9959668Slinton #define CALLSIZE 7	/* size of call instruction */
9969668Slinton 
9979668Slinton public beginproc(p, argc)
9989668Slinton Symbol p;
9999668Slinton Integer argc;
10009668Slinton {
10019668Slinton     char save[CALLSIZE];
10029668Slinton     struct {
10039668Slinton 	VaxOpcode op;
10049668Slinton 	unsigned char numargs;
10059668Slinton 	unsigned char mode;
10069668Slinton 	char addr[sizeof(long)];	/* unaligned long */
10079668Slinton     } call;
10089668Slinton     long dest;
10099668Slinton 
10109668Slinton     pc = 2;
10119668Slinton     iread(save, pc, sizeof(save));
10129668Slinton     call.op = O_CALLS;
10139668Slinton     call.numargs = argc;
10149668Slinton     call.mode = 0xef;
10159668Slinton     dest = codeloc(p) - 2 - (pc + 7);
10169668Slinton     mov(&dest, call.addr, sizeof(call.addr));
10179668Slinton     iwrite(&call, pc, sizeof(call));
10189668Slinton     setreg(PROGCTR, pc);
101916612Ssam     pstep(process, DEFSIG);
10209668Slinton     iwrite(save, pc, sizeof(save));
10219668Slinton     pc = reg(PROGCTR);
10229668Slinton     if (not isbperr()) {
10239668Slinton 	printstatus();
10249668Slinton     }
10259668Slinton }
1026