xref: /csrg-svn/old/dbx/vax.c (revision 26344)
121608Sdist /*
221608Sdist  * Copyright (c) 1983 Regents of the University of California.
321608Sdist  * All rights reserved.  The Berkeley software License Agreement
421608Sdist  * specifies the terms and conditions for redistribution.
521608Sdist  */
69668Slinton 
721608Sdist #ifndef lint
8*26344Ssam static char sccsid[] = "@(#)vax.c	5.3 (Berkeley) 02/23/86";
921608Sdist #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)
4726336Ssam /*
4826336Ssam  * Extract a field's value from the integer i.  The value
4926336Ssam  * is placed in i in such as way as the first bit of the
5026336Ssam  * field is contained in the first byte of the integer.
5126336Ssam  */
5226336Ssam #define	extractfield(i, s) \
5326336Ssam 	((i >> ((s)->symvalue.field.offset mod BITSPERBYTE)) & \
5426336Ssam 	 ((1 << (s)->symvalue.field.length) - 1))
5526336Ssam /*
5626336Ssam  * Expand/contract the expression stack to reflect a type
5726336Ssam  * rename operation.  We pad with zeros when expanding,
5826336Ssam  * otherwise we just pull the stack pointer back.
5926336Ssam  */
6026336Ssam #define	typerename(oldsize, newsize) { \
6126336Ssam 	int len = newsize - oldsize; \
6226336Ssam 	if (len > 0) \
6326336Ssam 		bzero(sp, len); \
6426336Ssam 	sp += len; \
6526336Ssam }
669668Slinton 
6726336Ssam #define	SYSBASE	0x80000000		/* base of system address space */
6826336Ssam #define	physaddr(a)	((a) & 0x7fffffff)
6926336Ssam 
709668Slinton #include "source.h"
719668Slinton #include "symbols.h"
72*26344Ssam #include <sys/param.h>
73*26344Ssam #include <sys/dir.h>
74*26344Ssam #include <machine/psl.h>
75*26344Ssam #include <machine/pte.h>
76*26344Ssam #include <sys/user.h>
77*26344Ssam #include <sys/vm.h>
78*26344Ssam #include <machine/reg.h>
799668Slinton 
809668Slinton Address pc;
819668Slinton Address prtaddr;
829668Slinton 
839668Slinton #endif
849668Slinton 
859668Slinton private Address printop();
869668Slinton 
879668Slinton /*
88*26344Ssam  * Indices into u. for use in collecting registers values.
89*26344Ssam  */
90*26344Ssam public int rloc[] =
91*26344Ssam     { R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, AP, FP, SP, PC };
92*26344Ssam 
93*26344Ssam /*
949668Slinton  * Decode and print the instructions within the given address range.
959668Slinton  */
969668Slinton 
979668Slinton public printinst(lowaddr, highaddr)
989668Slinton Address lowaddr;
999668Slinton Address highaddr;
1009668Slinton {
1019668Slinton     register Address addr;
1029668Slinton 
1039668Slinton     for (addr = lowaddr; addr <= highaddr; ) {
1049668Slinton 	addr = printop(addr);
1059668Slinton     }
1069668Slinton     prtaddr = addr;
1079668Slinton }
1089668Slinton 
1099668Slinton /*
1109668Slinton  * Another approach:  print n instructions starting at the given address.
1119668Slinton  */
1129668Slinton 
1139668Slinton public printninst(count, addr)
1149668Slinton int count;
1159668Slinton Address addr;
1169668Slinton {
1179668Slinton     register Integer i;
1189668Slinton     register Address newaddr;
1199668Slinton 
1209668Slinton     if (count <= 0) {
1219668Slinton 	error("non-positive repetition count");
1229668Slinton     } else {
1239668Slinton 	newaddr = addr;
1249668Slinton 	for (i = 0; i < count; i++) {
1259668Slinton 	    newaddr = printop(newaddr);
1269668Slinton 	}
1279668Slinton 	prtaddr = newaddr;
1289668Slinton     }
1299668Slinton }
1309668Slinton 
13126336Ssam optab_init()
13226336Ssam {
13326336Ssam 
13426336Ssam }
13526336Ssam 
1369668Slinton /*
1379668Slinton  * Hacked version of adb's VAX instruction decoder.
1389668Slinton  */
1399668Slinton 
1409668Slinton private Address printop(addr)
1419668Slinton Address addr;
1429668Slinton {
1439668Slinton     Optab op;
1449668Slinton     VaxOpcode ins;
1459668Slinton     unsigned char mode;
1469668Slinton     int argtype, amode, argno, argval;
1479668Slinton     String reg;
1489668Slinton     Boolean indexf;
1499668Slinton     short offset;
1509668Slinton 
1519668Slinton     argval = 0;
1529668Slinton     indexf = false;
1539668Slinton     printf("%08x  ", addr);
1549668Slinton     iread(&ins, addr, sizeof(ins));
1559668Slinton     addr += 1;
1569668Slinton     op = optab[ins];
1579668Slinton     printf("%s", op.iname);
1589668Slinton     for (argno = 0; argno < op.numargs; argno++) {
1599668Slinton 	if (indexf == true) {
1609668Slinton 	    indexf = false;
1619668Slinton 	} else if (argno == 0) {
1629668Slinton 	    printf("\t");
1639668Slinton 	} else {
1649668Slinton 	    printf(",");
1659668Slinton 	}
1669668Slinton 	argtype = op.argtype[argno];
1679668Slinton 	if (is_branch_disp(argtype)) {
1689668Slinton 	    mode = 0xAF + (typelen(argtype) << 5);
1699668Slinton 	} else {
1709668Slinton 	    iread(&mode, addr, sizeof(mode));
1719668Slinton 	    addr += 1;
1729668Slinton 	}
1739668Slinton 	reg = regname[regnm(mode)];
1749668Slinton 	amode = addrmode(mode);
1759668Slinton 	switch (amode) {
1769668Slinton 	    case LITSHORT:
1779668Slinton 	    case LITUPTO31:
1789668Slinton 	    case LITUPTO47:
1799668Slinton 	    case LITUPTO63:
1809668Slinton 		if (typelen(argtype) == TYPF || typelen(argtype) ==TYPD)
1819668Slinton 		    printf("$%s", fltimm[mode]);
1829668Slinton 		else
1839668Slinton 		    printf("$%x", mode);
1849668Slinton 		argval = mode;
1859668Slinton 		break;
1869668Slinton 
1879668Slinton 	    case INDEX:
1889668Slinton 		printf("[%s]", reg);
1899668Slinton 		indexf = true;
1909668Slinton 		argno--;
1919668Slinton 		break;
1929668Slinton 
1939668Slinton 	    case REG:
1949668Slinton 		printf("%s", reg);
1959668Slinton 		break;
1969668Slinton 
1979668Slinton 	    case REGDEF:
1989668Slinton 		printf("(%s)", reg);
1999668Slinton 		break;
2009668Slinton 
2019668Slinton 	    case AUTODEC:
2029668Slinton 		printf("-(%s)", reg);
2039668Slinton 		break;
2049668Slinton 
2059668Slinton 	    case AUTOINC:
2069668Slinton 		if (reg != regname[PROGCTR]) {
2079668Slinton 		    printf("(%s)+", reg);
2089668Slinton 		} else {
2099668Slinton 		    printf("$");
2109668Slinton 		    switch (typelen(argtype)) {
2119668Slinton 			case TYPB:
2129668Slinton 			    argval = printdisp(addr, 1, reg, amode);
2139668Slinton 			    addr += 1;
2149668Slinton 			    break;
2159668Slinton 
2169668Slinton 			case TYPW:
2179668Slinton 			    argval = printdisp(addr, 2, reg, amode);
2189668Slinton 			    addr += 2;
2199668Slinton 			    break;
2209668Slinton 
2219668Slinton 			case TYPL:
2229668Slinton 			    argval = printdisp(addr, 4, reg, amode);
2239668Slinton 			    addr += 4;
2249668Slinton 			    break;
2259668Slinton 
2269668Slinton 			case TYPF:
2279668Slinton 			    iread(&argval, addr, sizeof(argval));
2289668Slinton 			    printf("%06x", argval);
2299668Slinton 			    addr += 4;
2309668Slinton 			    break;
2319668Slinton 
2329668Slinton 			case TYPQ:
2339668Slinton 			case TYPD:
2349668Slinton 			    iread(&argval, addr, sizeof(argval));
2359668Slinton 			    printf("%06x", argval);
2369668Slinton 			    iread(&argval, addr+4, sizeof(argval));
2379668Slinton 			    printf("%06x", argval);
2389668Slinton 			    addr += 8;
2399668Slinton 			    break;
2409668Slinton 		    }
2419668Slinton 		}
2429668Slinton 		break;
2439668Slinton 
2449668Slinton 	    case AUTOINCDEF:
2459668Slinton 		if (reg == regname[PROGCTR]) {
2469668Slinton 		    printf("*$");
2479668Slinton 		    argval = printdisp(addr, 4, reg, amode);
2489668Slinton 		    addr += 4;
2499668Slinton 		} else {
2509668Slinton 		    printf("*(%s)+", reg);
2519668Slinton 		}
2529668Slinton 		break;
2539668Slinton 
2549668Slinton 	    case BYTEDISP:
2559668Slinton 		argval = printdisp(addr, 1, reg, amode);
2569668Slinton 		addr += 1;
2579668Slinton 		break;
2589668Slinton 
2599668Slinton 	    case BYTEDISPDEF:
2609668Slinton 		printf("*");
2619668Slinton 		argval = printdisp(addr, 1, reg, amode);
2629668Slinton 		addr += 1;
2639668Slinton 		break;
2649668Slinton 
2659668Slinton 	    case WORDDISP:
2669668Slinton 		argval = printdisp(addr, 2, reg, amode);
2679668Slinton 		addr += 2;
2689668Slinton 		break;
2699668Slinton 
2709668Slinton 	    case WORDDISPDEF:
2719668Slinton 		printf("*");
2729668Slinton 		argval = printdisp(addr, 2, reg, amode);
2739668Slinton 		addr += 2;
2749668Slinton 		break;
2759668Slinton 
2769668Slinton 	    case LONGDISP:
2779668Slinton 		argval = printdisp(addr, 4, reg, amode);
2789668Slinton 		addr += 4;
2799668Slinton 		break;
2809668Slinton 
2819668Slinton 	    case LONGDISPDEF:
2829668Slinton 		printf("*");
2839668Slinton 		argval = printdisp(addr, 4, reg, amode);
2849668Slinton 		addr += 4;
2859668Slinton 		break;
2869668Slinton 	}
2879668Slinton     }
2889668Slinton     if (ins == O_CASEB || ins == O_CASEW || ins == O_CASEL) {
2899668Slinton 	for (argno = 0; argno <= argval; argno++) {
2909668Slinton 	    iread(&offset, addr, sizeof(offset));
2919668Slinton 	    printf("\n\t\t%d", offset);
2929668Slinton 	    addr += 2;
2939668Slinton 	}
2949668Slinton     }
2959668Slinton     printf("\n");
2969668Slinton     return addr;
2979668Slinton }
2989668Slinton 
2999668Slinton /*
3009668Slinton  * Print the displacement of an instruction that uses displacement
3019668Slinton  * addressing.
3029668Slinton  */
3039668Slinton 
3049668Slinton private int printdisp(addr, nbytes, reg, mode)
3059668Slinton Address addr;
3069668Slinton int nbytes;
3079668Slinton char *reg;
3089668Slinton int mode;
3099668Slinton {
3109668Slinton     char byte;
3119668Slinton     short hword;
3129668Slinton     int argval;
31314338Slinton     Symbol f;
3149668Slinton 
3159668Slinton     switch (nbytes) {
3169668Slinton 	case 1:
3179668Slinton 	    iread(&byte, addr, sizeof(byte));
3189668Slinton 	    argval = byte;
3199668Slinton 	    break;
3209668Slinton 
3219668Slinton 	case 2:
3229668Slinton 	    iread(&hword, addr, sizeof(hword));
3239668Slinton 	    argval = hword;
3249668Slinton 	    break;
3259668Slinton 
3269668Slinton 	case 4:
3279668Slinton 	    iread(&argval, addr, sizeof(argval));
3289668Slinton 	    break;
3299668Slinton     }
3309668Slinton     if (reg == regname[PROGCTR] && mode >= BYTEDISP) {
3319668Slinton 	argval += addr + nbytes;
3329668Slinton     }
3339668Slinton     if (reg == regname[PROGCTR]) {
33414338Slinton 	f = whatblock((Address) argval + 2);
33514338Slinton 	if (codeloc(f) == argval + 2) {
33614338Slinton 	    printf("%s", symname(f));
33714338Slinton 	} else {
33814338Slinton 	    printf("%x", argval);
33914338Slinton 	}
3409668Slinton     } else {
34118222Slinton 	if (varIsSet("$hexoffsets")) {
34218222Slinton 	    if (argval < 0) {
34318222Slinton 		printf("-%x(%s)", -(argval), reg);
34418222Slinton 	    } else {
34518222Slinton 		printf("%x(%s)", argval, reg);
34618222Slinton 	    }
34718222Slinton 	} else {
34818222Slinton 	    printf("%d(%s)", argval, reg);
34918222Slinton 	}
3509668Slinton     }
3519668Slinton     return argval;
3529668Slinton }
3539668Slinton 
3549668Slinton /*
3559668Slinton  * Print the contents of the addresses within the given range
3569668Slinton  * according to the given format.
3579668Slinton  */
3589668Slinton 
3599668Slinton typedef struct {
3609668Slinton     String name;
3619668Slinton     String printfstring;
3629668Slinton     int length;
3639668Slinton } Format;
3649668Slinton 
3659668Slinton private Format fmt[] = {
3669668Slinton     { "d", " %d", sizeof(short) },
3679668Slinton     { "D", " %ld", sizeof(long) },
3689668Slinton     { "o", " %o", sizeof(short) },
3699668Slinton     { "O", " %lo", sizeof(long) },
3709668Slinton     { "x", " %04x", sizeof(short) },
3719668Slinton     { "X", " %08x", sizeof(long) },
3729668Slinton     { "b", " \\%o", sizeof(char) },
3739668Slinton     { "c", " '%c'", sizeof(char) },
3749668Slinton     { "s", "%c", sizeof(char) },
37514338Slinton     { "f", " %f", sizeof(float) },
3769668Slinton     { "g", " %g", sizeof(double) },
3779668Slinton     { nil, nil, 0 }
3789668Slinton };
3799668Slinton 
38011174Slinton private Format *findformat(s)
38111174Slinton String s;
38211174Slinton {
38311174Slinton     register Format *f;
38411174Slinton 
38511174Slinton     f = &fmt[0];
38611174Slinton     while (f->name != nil and not streq(f->name, s)) {
38711174Slinton 	++f;
38811174Slinton     }
38911174Slinton     if (f->name == nil) {
39011174Slinton 	error("bad print format \"%s\"", s);
39111174Slinton     }
39211174Slinton     return f;
39311174Slinton }
39411174Slinton 
3959668Slinton public Address printdata(lowaddr, highaddr, format)
3969668Slinton Address lowaddr;
3979668Slinton Address highaddr;
3989668Slinton String format;
3999668Slinton {
4009668Slinton     register int n;
4019668Slinton     register Address addr;
4029668Slinton     register Format *f;
4039668Slinton     int value;
4049668Slinton 
4059668Slinton     if (lowaddr > highaddr) {
4069668Slinton 	error("first address larger than second");
4079668Slinton     }
40811174Slinton     f = findformat(format);
4099668Slinton     n = 0;
4109668Slinton     value = 0;
4119668Slinton     for (addr = lowaddr; addr <= highaddr; addr += f->length) {
4129668Slinton 	if (n == 0) {
4139668Slinton 	    printf("%08x: ", addr);
4149668Slinton 	}
4159668Slinton 	dread(&value, addr, f->length);
4169668Slinton 	printf(f->printfstring, value);
4179668Slinton 	++n;
4189668Slinton 	if (n >= (16 div f->length)) {
4199668Slinton 	    putchar('\n');
4209668Slinton 	    n = 0;
4219668Slinton 	}
4229668Slinton     }
4239668Slinton     if (n != 0) {
4249668Slinton 	putchar('\n');
4259668Slinton     }
4269668Slinton     prtaddr = addr;
4279668Slinton     return addr;
4289668Slinton }
4299668Slinton 
4309668Slinton /*
4319668Slinton  * The other approach is to print n items starting with a given address.
4329668Slinton  */
4339668Slinton 
4349668Slinton public printndata(count, startaddr, format)
4359668Slinton int count;
4369668Slinton Address startaddr;
4379668Slinton String format;
4389668Slinton {
4399668Slinton     register int i, n;
4409668Slinton     register Address addr;
4419668Slinton     register Format *f;
4429668Slinton     register Boolean isstring;
44314338Slinton     char c;
44414338Slinton     union {
44514338Slinton 	char charv;
44614338Slinton 	short shortv;
44714338Slinton 	int intv;
44814338Slinton 	float floatv;
44914338Slinton 	double doublev;
45014338Slinton     } value;
4519668Slinton 
4529668Slinton     if (count <= 0) {
4539668Slinton 	error("non-positive repetition count");
4549668Slinton     }
45511174Slinton     f = findformat(format);
4569668Slinton     isstring = (Boolean) streq(f->name, "s");
4579668Slinton     n = 0;
4589668Slinton     addr = startaddr;
45914338Slinton     value.intv = 0;
4609668Slinton     for (i = 0; i < count; i++) {
4619668Slinton 	if (n == 0) {
4629668Slinton 	    printf("%08x: ", addr);
4639668Slinton 	}
4649668Slinton 	if (isstring) {
4659668Slinton 	    putchar('"');
46614338Slinton 	    dread(&c, addr, sizeof(char));
46714338Slinton 	    while (c != '\0') {
46814338Slinton 		printchar(c);
4699668Slinton 		++addr;
47014338Slinton 		dread(&c, addr, sizeof(char));
4719668Slinton 	    }
4729668Slinton 	    putchar('"');
4739668Slinton 	    putchar('\n');
4749668Slinton 	    n = 0;
4759668Slinton 	    addr += sizeof(String);
4769668Slinton 	} else {
4779668Slinton 	    dread(&value, addr, f->length);
4789668Slinton 	    printf(f->printfstring, value);
4799668Slinton 	    ++n;
4809668Slinton 	    if (n >= (16 div f->length)) {
4819668Slinton 		putchar('\n');
4829668Slinton 		n = 0;
4839668Slinton 	    }
4849668Slinton 	    addr += f->length;
4859668Slinton 	}
4869668Slinton     }
4879668Slinton     if (n != 0) {
4889668Slinton 	putchar('\n');
4899668Slinton     }
4909668Slinton     prtaddr = addr;
4919668Slinton }
4929668Slinton 
4939668Slinton /*
49411174Slinton  * Print out a value according to the given format.
49511174Slinton  */
49611174Slinton 
49711174Slinton public printvalue(v, format)
49811174Slinton long v;
49911174Slinton String format;
50011174Slinton {
50111174Slinton     Format *f;
50211174Slinton     char *p, *q;
50311174Slinton 
50411174Slinton     f = findformat(format);
50511174Slinton     if (streq(f->name, "s")) {
50611174Slinton 	putchar('"');
50711174Slinton 	p = (char *) &v;
50811174Slinton 	q = p + sizeof(v);
50911174Slinton 	while (p < q) {
51011174Slinton 	    printchar(*p);
51111174Slinton 	    ++p;
51211174Slinton 	}
51311174Slinton 	putchar('"');
51411174Slinton     } else {
51511174Slinton 	printf(f->printfstring, v);
51611174Slinton     }
51711174Slinton     putchar('\n');
51811174Slinton }
51911174Slinton 
52011174Slinton /*
5219668Slinton  * Print out an execution time error.
5229842Slinton  * Assumes the source position of the error has been calculated.
5239668Slinton  *
5249668Slinton  * Have to check if the -r option was specified; if so then
5259668Slinton  * the object file information hasn't been read in yet.
5269668Slinton  */
5279668Slinton 
5289668Slinton public printerror()
5299668Slinton {
5309668Slinton     extern Integer sys_nsig;
5319668Slinton     extern String sys_siglist[];
53218222Slinton     integer err;
5339668Slinton 
5349668Slinton     if (isfinished(process)) {
53516932Ssam 	err = exitcode(process);
53618222Slinton 	if (err == 0) {
53718222Slinton 	    printf("\"%s\" terminated normally\n", objname);
53818222Slinton 	} else {
53918222Slinton 	    printf("\"%s\" terminated abnormally (exit code %d)\n",
54018222Slinton 		objname, err
54118222Slinton 	    );
54218222Slinton 	}
5439668Slinton 	erecover();
5449668Slinton     }
5459668Slinton     if (runfirst) {
54618222Slinton 	fprintf(stderr, "Entering debugger ...\n");
5479668Slinton 	init();
5489668Slinton     }
5499668Slinton     err = errnum(process);
5509668Slinton     putchar('\n');
55116932Ssam     printsig(err);
55218222Slinton     putchar(' ');
55316932Ssam     printloc();
55416932Ssam     putchar('\n');
5559668Slinton     if (curline > 0) {
5569668Slinton 	printlines(curline, curline);
5579668Slinton     } else {
5589668Slinton 	printinst(pc, pc);
5599668Slinton     }
5609668Slinton     erecover();
5619668Slinton }
5629668Slinton 
56318222Slinton /*
56418222Slinton  * Print out a signal.
56518222Slinton  */
56618222Slinton 
56716932Ssam private String illinames[] = {
56818222Slinton     "reserved addressing fault",
56918222Slinton     "priviliged instruction fault",
57018222Slinton     "reserved operand fault"
57116932Ssam };
57218222Slinton 
57316932Ssam private String fpenames[] = {
57418222Slinton     nil,
57518222Slinton     "integer overflow trap",
57618222Slinton     "integer divide by zero trap",
57718222Slinton     "floating overflow trap",
57818222Slinton     "floating/decimal divide by zero trap",
57918222Slinton     "floating underflow trap",
58018222Slinton     "decimal overflow trap",
58118222Slinton     "subscript out of range trap",
58218222Slinton     "floating overflow fault",
58318222Slinton     "floating divide by zero fault",
58418222Slinton     "floating undeflow fault"
58516932Ssam };
58616932Ssam 
58718222Slinton public printsig (signo)
58818222Slinton integer signo;
58916932Ssam {
59018222Slinton     integer code;
59116932Ssam 
59218222Slinton     if (signo < 0 or signo > sys_nsig) {
59318222Slinton 	printf("[signal %d]", signo);
59418222Slinton     } else {
59518222Slinton 	printf("%s", sys_siglist[signo]);
59616932Ssam     }
59718222Slinton     code = errcode(process);
59818222Slinton     if (signo == SIGILL) {
59918222Slinton 	if (code >= 0 and code < sizeof(illinames) / sizeof(illinames[0])) {
60018222Slinton 	    printf(" (%s)", illinames[code]);
60118222Slinton 	}
60218222Slinton     } else if (signo == SIGFPE) {
60318222Slinton 	if (code > 0 and code < sizeof(fpenames) / sizeof(fpenames[0])) {
60418222Slinton 	    printf(" (%s)", fpenames[code]);
60518222Slinton 	}
60618222Slinton     }
60716932Ssam }
60816932Ssam 
6099668Slinton /*
6109668Slinton  * Note the termination of the program.  We do this so as to avoid
6119668Slinton  * having the process exit, which would make the values of variables
6129668Slinton  * inaccessible.  We do want to flush all output buffers here,
6139668Slinton  * otherwise it'll never get done.
6149668Slinton  */
6159668Slinton 
6169668Slinton public endprogram()
6179668Slinton {
6189668Slinton     Integer exitcode;
6199668Slinton 
6209668Slinton     stepto(nextaddr(pc, true));
6219668Slinton     printnews();
6229668Slinton     exitcode = argn(1, nil);
62318222Slinton     if (exitcode != 0) {
62418222Slinton 	printf("\nexecution completed (exit code %d)\n", exitcode);
62518222Slinton     } else {
62618222Slinton 	printf("\nexecution completed\n");
62718222Slinton     }
6289668Slinton     getsrcpos();
6299668Slinton     erecover();
6309668Slinton }
6319668Slinton 
6329668Slinton /*
6339668Slinton  * Single step the machine a source line (or instruction if "inst_tracing"
63410621Slinton  * is true).  If "isnext" is true, skip over procedure calls.
6359668Slinton  */
6369668Slinton 
6379668Slinton private Address getcall();
6389668Slinton 
6399668Slinton public dostep(isnext)
6409668Slinton Boolean isnext;
6419668Slinton {
6429668Slinton     register Address addr;
6439668Slinton     register Lineno line;
6449668Slinton     String filename;
64518222Slinton     Address startaddr;
6469668Slinton 
64716612Ssam     startaddr = pc;
6489668Slinton     addr = nextaddr(pc, isnext);
64910621Slinton     if (not inst_tracing and nlhdr.nlines != 0) {
6509668Slinton 	line = linelookup(addr);
6519668Slinton 	while (line == 0) {
65218222Slinton 	    addr = nextaddr(addr, isnext);
6539668Slinton 	    line = linelookup(addr);
6549668Slinton 	}
65510621Slinton 	curline = line;
65610621Slinton     } else {
65710621Slinton 	curline = 0;
6589668Slinton     }
6599668Slinton     stepto(addr);
6609668Slinton     filename = srcfilename(addr);
6619668Slinton     setsource(filename);
6629668Slinton }
6639668Slinton 
6649668Slinton /*
6659668Slinton  * Compute the next address that will be executed from the given one.
6669668Slinton  * If "isnext" is true then consider a procedure call as straight line code.
6679668Slinton  *
6689668Slinton  * We must unfortunately do much of the same work that is necessary
6699668Slinton  * to print instructions.  In addition we have to deal with branches.
6709668Slinton  * Unconditional branches we just follow, for conditional branches
6719668Slinton  * we continue execution to the current location and then single step
6729668Slinton  * the machine.  We assume that the last argument in an instruction
6739668Slinton  * that branches is the branch address (or relative offset).
6749668Slinton  */
6759668Slinton 
67618222Slinton private Address findnextaddr();
67718222Slinton 
6789668Slinton public Address nextaddr(startaddr, isnext)
6799668Slinton Address startaddr;
68016612Ssam boolean isnext;
68116612Ssam {
68216612Ssam     Address addr;
68316612Ssam 
68416612Ssam     addr = usignal(process);
68516612Ssam     if (addr == 0 or addr == 1) {
68616612Ssam 	addr = findnextaddr(startaddr, isnext);
68716612Ssam     }
68816612Ssam     return addr;
68916612Ssam }
69016612Ssam 
69118222Slinton /*
69218222Slinton  * Determine if it's ok to skip function f entered by instruction ins.
69318222Slinton  * If so, we're going to compute the return address and step to it.
69418222Slinton  * Therefore we cannot skip over a function entered by a jsb or bsb,
69518222Slinton  * since the return address is not easily computed for them.
69618222Slinton  */
69718222Slinton 
69818222Slinton private boolean skipfunc (ins, f)
69918222Slinton VaxOpcode ins;
70018222Slinton Symbol f;
70118222Slinton {
70218222Slinton     boolean b;
70318222Slinton 
70418222Slinton     b = (boolean) (
70518222Slinton 	ins != O_JSB and ins != O_BSBB and ins != O_BSBW and
70618222Slinton 	not inst_tracing and nlhdr.nlines != 0 and
70718222Slinton 	nosource(curfunc) and canskip(curfunc)
70818222Slinton     );
70918222Slinton     return b;
71018222Slinton }
71118222Slinton 
71216612Ssam private Address findnextaddr(startaddr, isnext)
71316612Ssam Address startaddr;
7149668Slinton Boolean isnext;
7159668Slinton {
7169668Slinton     register Address addr;
7179668Slinton     Optab op;
7189668Slinton     VaxOpcode ins;
7199668Slinton     unsigned char mode;
7209668Slinton     int argtype, amode, argno, argval;
7219668Slinton     String r;
7229668Slinton     Boolean indexf;
7239668Slinton     enum { KNOWN, SEQUENTIAL, BRANCH } addrstatus;
7249668Slinton 
7259668Slinton     argval = 0;
7269668Slinton     indexf = false;
7279668Slinton     addr = startaddr;
7289668Slinton     iread(&ins, addr, sizeof(ins));
7299668Slinton     switch (ins) {
73018222Slinton 	/*
73118222Slinton 	 * It used to be that unconditional jumps and branches were handled
73218222Slinton 	 * by taking their destination address as the next address.  While
73318222Slinton 	 * saving the cost of starting up the process, this approach
73418222Slinton 	 * doesn't work when jumping indirect (since the value in the
73518222Slinton 	 * register might not yet have been set).
73618222Slinton 	 *
73718222Slinton 	 * So unconditional jumps and branches are now handled the same way
73818222Slinton 	 * as conditional jumps and branches.
73918222Slinton 	 *
7409668Slinton 	case O_BRB:
7419668Slinton 	case O_BRW:
7429668Slinton 	    addrstatus = BRANCH;
7439668Slinton 	    break;
74418222Slinton 	 *
74518222Slinton 	 */
7469668Slinton 
7479668Slinton 	case O_BSBB:
7489668Slinton 	case O_BSBW:
7499668Slinton 	case O_JSB:
7509668Slinton 	case O_CALLG:
7519668Slinton 	case O_CALLS:
75218222Slinton 	    addrstatus = KNOWN;
75318222Slinton 	    stepto(addr);
75418222Slinton 	    pstep(process, DEFSIG);
75518222Slinton 	    addr = reg(PROGCTR);
75618222Slinton 	    pc = addr;
75718222Slinton 	    setcurfunc(whatblock(pc));
75818222Slinton 	    if (not isbperr()) {
75918222Slinton 		printstatus();
76018222Slinton 		/* NOTREACHED */
76118222Slinton 	    }
76218222Slinton 	    bpact();
76318222Slinton 	    if (isnext or skipfunc(ins, curfunc)) {
7649668Slinton 		addrstatus = KNOWN;
76518222Slinton 		addr = return_addr();
7669668Slinton 		stepto(addr);
76711864Slinton 		bpact();
76818222Slinton 	    } else {
76918222Slinton 		callnews(/* iscall = */ true);
7709668Slinton 	    }
7719668Slinton 	    break;
7729668Slinton 
7739668Slinton 	case O_RSB:
7749668Slinton 	case O_RET:
7759668Slinton 	    addrstatus = KNOWN;
77618222Slinton 	    stepto(addr);
7779668Slinton 	    callnews(/* iscall = */ false);
77818222Slinton 	    pstep(process, DEFSIG);
77918222Slinton 	    addr = reg(PROGCTR);
78018222Slinton 	    pc = addr;
78118222Slinton 	    if (not isbperr()) {
78218222Slinton 		printstatus();
78316612Ssam 	    }
78411874Slinton 	    bpact();
7859668Slinton 	    break;
7869668Slinton 
78718222Slinton 	case O_BRB: case O_BRW:
78816612Ssam 	case O_JMP: /* because it may be jmp (r1) */
7899668Slinton 	case O_BNEQ: case O_BEQL: case O_BGTR:
7909668Slinton 	case O_BLEQ: case O_BGEQ: case O_BLSS:
7919668Slinton 	case O_BGTRU: case O_BLEQU: case O_BVC:
7929668Slinton 	case O_BVS: case O_BCC: case O_BCS:
7939668Slinton 	case O_CASEB: case O_CASEW: case O_CASEL:
7949668Slinton 	case O_BBS: case O_BBC: case O_BBSS: case O_BBCS:
7959668Slinton 	case O_BBSC: case O_BBCC: case O_BBSSI:
7969668Slinton 	case O_BBCCI: case O_BLBS: case O_BLBC:
7979668Slinton 	case O_ACBL: case O_AOBLSS: case O_AOBLEQ:
7989668Slinton 	case O_SOBGEQ: case O_SOBGTR:
7999668Slinton 	    addrstatus = KNOWN;
8009668Slinton 	    stepto(addr);
80116612Ssam 	    pstep(process, DEFSIG);
8029668Slinton 	    addr = reg(PROGCTR);
8039668Slinton 	    pc = addr;
8049668Slinton 	    if (not isbperr()) {
8059668Slinton 		printstatus();
8069668Slinton 	    }
8079668Slinton 	    break;
8089668Slinton 
8099668Slinton 	default:
8109668Slinton 	    addrstatus = SEQUENTIAL;
8119668Slinton 	    break;
8129668Slinton     }
8139668Slinton     if (addrstatus != KNOWN) {
8149668Slinton 	addr += 1;
8159668Slinton 	op = optab[ins];
8169668Slinton 	for (argno = 0; argno < op.numargs; argno++) {
8179668Slinton 	    if (indexf == true) {
8189668Slinton 		indexf = false;
8199668Slinton 	    }
8209668Slinton 	    argtype = op.argtype[argno];
8219668Slinton 	    if (is_branch_disp(argtype)) {
8229668Slinton 		mode = 0xAF + (typelen(argtype) << 5);
8239668Slinton 	    } else {
8249668Slinton 		iread(&mode, addr, sizeof(mode));
8259668Slinton 		addr += 1;
8269668Slinton 	    }
8279668Slinton 	    r = regname[regnm(mode)];
8289668Slinton 	    amode = addrmode(mode);
8299668Slinton 	    switch (amode) {
8309668Slinton 		case LITSHORT:
8319668Slinton 		case LITUPTO31:
8329668Slinton 		case LITUPTO47:
8339668Slinton 		case LITUPTO63:
8349668Slinton 		    argval = mode;
8359668Slinton 		    break;
8369668Slinton 
8379668Slinton 		case INDEX:
8389668Slinton 		    indexf = true;
8399668Slinton 		    --argno;
8409668Slinton 		    break;
8419668Slinton 
8429668Slinton 		case REG:
8439668Slinton 		case REGDEF:
8449668Slinton 		case AUTODEC:
8459668Slinton 		    break;
8469668Slinton 
8479668Slinton 		case AUTOINC:
8489668Slinton 		    if (r == regname[PROGCTR]) {
8499668Slinton 			switch (typelen(argtype)) {
8509668Slinton 			    case TYPB:
8519668Slinton 				argval = getdisp(addr, 1, r, amode);
8529668Slinton 				addr += 1;
8539668Slinton 				break;
8549668Slinton 
8559668Slinton 			    case TYPW:
8569668Slinton 				argval = getdisp(addr, 2, r, amode);
8579668Slinton 				addr += 2;
8589668Slinton 				break;
8599668Slinton 
8609668Slinton 			    case TYPL:
8619668Slinton 				argval = getdisp(addr, 4, r, amode);
8629668Slinton 				addr += 4;
8639668Slinton 				break;
8649668Slinton 
8659668Slinton 			    case TYPF:
8669668Slinton 				iread(&argval, addr, sizeof(argval));
8679668Slinton 				addr += 4;
8689668Slinton 				break;
8699668Slinton 
8709668Slinton 			    case TYPQ:
8719668Slinton 			    case TYPD:
8729668Slinton 				iread(&argval, addr+4, sizeof(argval));
8739668Slinton 				addr += 8;
8749668Slinton 				break;
8759668Slinton 			}
8769668Slinton 		    }
8779668Slinton 		    break;
8789668Slinton 
8799668Slinton 		case AUTOINCDEF:
8809668Slinton 		    if (r == regname[PROGCTR]) {
8819668Slinton 			argval = getdisp(addr, 4, r, amode);
8829668Slinton 			addr += 4;
8839668Slinton 		    }
8849668Slinton 		    break;
8859668Slinton 
8869668Slinton 		case BYTEDISP:
8879668Slinton 		case BYTEDISPDEF:
8889668Slinton 		    argval = getdisp(addr, 1, r, amode);
8899668Slinton 		    addr += 1;
8909668Slinton 		    break;
8919668Slinton 
8929668Slinton 		case WORDDISP:
8939668Slinton 		case WORDDISPDEF:
8949668Slinton 		    argval = getdisp(addr, 2, r, amode);
8959668Slinton 		    addr += 2;
8969668Slinton 		    break;
8979668Slinton 
8989668Slinton 		case LONGDISP:
8999668Slinton 		case LONGDISPDEF:
9009668Slinton 		    argval = getdisp(addr, 4, r, amode);
9019668Slinton 		    addr += 4;
9029668Slinton 		    break;
9039668Slinton 	    }
9049668Slinton 	}
9059668Slinton 	if (ins == O_CALLS or ins == O_CALLG) {
9069668Slinton 	    argval += 2;
9079668Slinton 	}
9089668Slinton 	if (addrstatus == BRANCH) {
9099668Slinton 	    addr = argval;
9109668Slinton 	}
9119668Slinton     }
9129668Slinton     return addr;
9139668Slinton }
9149668Slinton 
9159668Slinton /*
9169668Slinton  * Get the displacement of an instruction that uses displacement addressing.
9179668Slinton  */
9189668Slinton 
9199668Slinton private int getdisp(addr, nbytes, reg, mode)
9209668Slinton Address addr;
9219668Slinton int nbytes;
9229668Slinton String reg;
9239668Slinton int mode;
9249668Slinton {
9259668Slinton     char byte;
9269668Slinton     short hword;
9279668Slinton     int argval;
9289668Slinton 
9299668Slinton     switch (nbytes) {
9309668Slinton 	case 1:
9319668Slinton 	    iread(&byte, addr, sizeof(byte));
9329668Slinton 	    argval = byte;
9339668Slinton 	    break;
9349668Slinton 
9359668Slinton 	case 2:
9369668Slinton 	    iread(&hword, addr, sizeof(hword));
9379668Slinton 	    argval = hword;
9389668Slinton 	    break;
9399668Slinton 
9409668Slinton 	case 4:
9419668Slinton 	    iread(&argval, addr, sizeof(argval));
9429668Slinton 	    break;
9439668Slinton     }
9449668Slinton     if (reg == regname[PROGCTR] && mode >= BYTEDISP) {
9459668Slinton 	argval += addr + nbytes;
9469668Slinton     }
9479668Slinton     return argval;
9489668Slinton }
9499668Slinton 
9509668Slinton #define BP_OP       O_BPT       /* breakpoint trap */
9519668Slinton #define BP_ERRNO    SIGTRAP     /* signal received at a breakpoint */
9529668Slinton 
9539668Slinton /*
9549668Slinton  * Setting a breakpoint at a location consists of saving
9559668Slinton  * the word at the location and poking a BP_OP there.
9569668Slinton  *
9579668Slinton  * We save the locations and words on a list for use in unsetting.
9589668Slinton  */
9599668Slinton 
9609668Slinton typedef struct Savelist *Savelist;
9619668Slinton 
9629668Slinton struct Savelist {
9639668Slinton     Address location;
9649668Slinton     Byte save;
9659668Slinton     Byte refcount;
9669668Slinton     Savelist link;
9679668Slinton };
9689668Slinton 
9699668Slinton private Savelist savelist;
9709668Slinton 
9719668Slinton /*
9729668Slinton  * Set a breakpoint at the given address.  Only save the word there
9739668Slinton  * if it's not already a breakpoint.
9749668Slinton  */
9759668Slinton 
9769668Slinton public setbp(addr)
9779668Slinton Address addr;
9789668Slinton {
9799668Slinton     Byte w;
9809668Slinton     Byte save;
9819668Slinton     register Savelist newsave, s;
9829668Slinton 
9839668Slinton     for (s = savelist; s != nil; s = s->link) {
9849668Slinton 	if (s->location == addr) {
9859668Slinton 	    s->refcount++;
9869668Slinton 	    return;
9879668Slinton 	}
9889668Slinton     }
98911174Slinton     iread(&save, addr, sizeof(save));
9909668Slinton     newsave = new(Savelist);
9919668Slinton     newsave->location = addr;
9929668Slinton     newsave->save = save;
9939668Slinton     newsave->refcount = 1;
9949668Slinton     newsave->link = savelist;
9959668Slinton     savelist = newsave;
9969668Slinton     w = BP_OP;
9979668Slinton     iwrite(&w, addr, sizeof(w));
9989668Slinton }
9999668Slinton 
10009668Slinton /*
10019668Slinton  * Unset a breakpoint; unfortunately we have to search the SAVELIST
10029668Slinton  * to find the saved value.  The assumption is that the SAVELIST will
10039668Slinton  * usually be quite small.
10049668Slinton  */
10059668Slinton 
10069668Slinton public unsetbp(addr)
10079668Slinton Address addr;
10089668Slinton {
10099668Slinton     register Savelist s, prev;
10109668Slinton 
10119668Slinton     prev = nil;
10129668Slinton     for (s = savelist; s != nil; s = s->link) {
10139668Slinton 	if (s->location == addr) {
10149668Slinton 	    iwrite(&s->save, addr, sizeof(s->save));
10159668Slinton 	    s->refcount--;
10169668Slinton 	    if (s->refcount == 0) {
10179668Slinton 		if (prev == nil) {
10189668Slinton 		    savelist = s->link;
10199668Slinton 		} else {
10209668Slinton 		    prev->link = s->link;
10219668Slinton 		}
10229668Slinton 		dispose(s);
10239668Slinton 	    }
10249668Slinton 	    return;
10259668Slinton 	}
10269668Slinton 	prev = s;
10279668Slinton     }
10289668Slinton     panic("unsetbp: couldn't find address %d", addr);
10299668Slinton }
10309668Slinton 
10319668Slinton /*
10329668Slinton  * Enter a procedure by creating and executing a call instruction.
10339668Slinton  */
10349668Slinton 
10359668Slinton #define CALLSIZE 7	/* size of call instruction */
10369668Slinton 
10379668Slinton public beginproc(p, argc)
10389668Slinton Symbol p;
10399668Slinton Integer argc;
10409668Slinton {
10419668Slinton     char save[CALLSIZE];
10429668Slinton     struct {
10439668Slinton 	VaxOpcode op;
10449668Slinton 	unsigned char numargs;
10459668Slinton 	unsigned char mode;
10469668Slinton 	char addr[sizeof(long)];	/* unaligned long */
10479668Slinton     } call;
10489668Slinton     long dest;
10499668Slinton 
10509668Slinton     pc = 2;
10519668Slinton     iread(save, pc, sizeof(save));
10529668Slinton     call.op = O_CALLS;
10539668Slinton     call.numargs = argc;
10549668Slinton     call.mode = 0xef;
10559668Slinton     dest = codeloc(p) - 2 - (pc + 7);
10569668Slinton     mov(&dest, call.addr, sizeof(call.addr));
10579668Slinton     iwrite(&call, pc, sizeof(call));
10589668Slinton     setreg(PROGCTR, pc);
105916612Ssam     pstep(process, DEFSIG);
10609668Slinton     iwrite(save, pc, sizeof(save));
10619668Slinton     pc = reg(PROGCTR);
10629668Slinton     if (not isbperr()) {
10639668Slinton 	printstatus();
10649668Slinton     }
10659668Slinton }
106626336Ssam 
106726336Ssam /*
106826336Ssam  * Special variables for debugging the kernel.
106926336Ssam  */
107026336Ssam 
107126336Ssam public integer masterpcbb;
107226336Ssam public integer slr;
107326336Ssam public struct pte *sbr;
107426336Ssam public struct pcb pcb;
107526336Ssam 
107626336Ssam public getpcb ()
107726336Ssam {
107826336Ssam     fseek(corefile, physaddr(masterpcbb), 0);
107926336Ssam     get(corefile, pcb);
108026336Ssam     pcb.pcb_p0lr &= ~AST_CLR;
108126336Ssam     printf("p0br %lx p0lr %lx p1br %lx p1lr %lx\n",
108226336Ssam 	pcb.pcb_p0br, pcb.pcb_p0lr, pcb.pcb_p1br, pcb.pcb_p1lr
108326336Ssam     );
108426336Ssam     setreg(0, pcb.pcb_r0);
108526336Ssam     setreg(1, pcb.pcb_r1);
108626336Ssam     setreg(2, pcb.pcb_r2);
108726336Ssam     setreg(3, pcb.pcb_r3);
108826336Ssam     setreg(4, pcb.pcb_r4);
108926336Ssam     setreg(5, pcb.pcb_r5);
109026336Ssam     setreg(6, pcb.pcb_r6);
109126336Ssam     setreg(7, pcb.pcb_r7);
109226336Ssam     setreg(8, pcb.pcb_r8);
109326336Ssam     setreg(9, pcb.pcb_r9);
109426336Ssam     setreg(10, pcb.pcb_r10);
109526336Ssam     setreg(11, pcb.pcb_r11);
109626336Ssam     setreg(ARGP, pcb.pcb_ap);
109726336Ssam     setreg(FRP, pcb.pcb_fp);
109826336Ssam     setreg(STKP, pcb.pcb_ksp);
109926336Ssam     setreg(PROGCTR, pcb.pcb_pc);
110026336Ssam }
110126336Ssam 
110226336Ssam public copyregs (savreg, reg)
110326336Ssam Word savreg[], reg[];
110426336Ssam {
110526336Ssam     reg[0] = savreg[R0];
110626336Ssam     reg[1] = savreg[R1];
110726336Ssam     reg[2] = savreg[R2];
110826336Ssam     reg[3] = savreg[R3];
110926336Ssam     reg[4] = savreg[R4];
111026336Ssam     reg[5] = savreg[R5];
111126336Ssam     reg[6] = savreg[R6];
111226336Ssam     reg[7] = savreg[R7];
111326336Ssam     reg[8] = savreg[R8];
111426336Ssam     reg[9] = savreg[R9];
111526336Ssam     reg[10] = savreg[R10];
111626336Ssam     reg[11] = savreg[R11];
111726336Ssam     reg[ARGP] = savreg[AP];
111826336Ssam     reg[FRP] = savreg[FP];
111926336Ssam     reg[STKP] = savreg[SP];
112026336Ssam     reg[PROGCTR] = savreg[PC];
112126336Ssam }
112226336Ssam 
112326336Ssam /*
112426336Ssam  * Map a virtual address to a physical address.
112526336Ssam  */
112626336Ssam 
112726336Ssam public Address vmap (addr)
112826336Ssam Address addr;
112926336Ssam {
113026336Ssam     Address r;
113126336Ssam     integer v, n;
113226336Ssam     struct pte pte;
113326336Ssam 
113426336Ssam     r = addr & ~0xc0000000;
113526336Ssam     v = btop(r);
113626336Ssam     switch (addr&0xc0000000) {
113726336Ssam 	case 0xc0000000:
113826336Ssam 	case 0x80000000:
113926336Ssam 	    /*
114026336Ssam 	     * In system space, so get system pte.
114126336Ssam 	     * If it is valid or reclaimable then the physical address
114226336Ssam 	     * is the combination of its page number and the page offset
114326336Ssam 	     * of the original address.
114426336Ssam 	     */
114526336Ssam 	    if (v >= slr) {
114626336Ssam 		error("address %x out of segment", addr);
114726336Ssam 	    }
114826336Ssam 	    r = ((long) (sbr + v)) & ~0x80000000;
114926336Ssam 	    goto simple;
115026336Ssam 
115126336Ssam 	case 0x40000000:
115226336Ssam 	    /*
115326336Ssam 	     * In p1 space, must not be in shadow region.
115426336Ssam 	     */
115526336Ssam 	    if (v < pcb.pcb_p1lr) {
115626336Ssam 		error("address %x out of segment", addr);
115726336Ssam 	    }
115826336Ssam 	    r = (Address) (pcb.pcb_p1br + v);
115926336Ssam 	    break;
116026336Ssam 
116126336Ssam 	case 0x00000000:
116226336Ssam 	    /*
116326336Ssam 	     * In p0 space, must not be off end of region.
116426336Ssam 	     */
116526336Ssam 	    if (v >= pcb.pcb_p0lr) {
116626336Ssam 		error("address %x out of segment", addr);
116726336Ssam 	    }
116826336Ssam 	    r = (Address) (pcb.pcb_p0br + v);
116926336Ssam 	    break;
117026336Ssam 
117126336Ssam 	default:
117226336Ssam 	    /* do nothing */
117326336Ssam 	    break;
117426336Ssam     }
117526336Ssam     /*
117626336Ssam      * For p0/p1 address, user-level page table should be in
117726336Ssam      * kernel virtual memory.  Do second-level indirect by recursing.
117826336Ssam      */
117926336Ssam     if ((r & 0x80000000) == 0) {
118026336Ssam 	error("bad p0br or p1br in pcb");
118126336Ssam     }
118226336Ssam     r = vmap(r);
118326336Ssam simple:
118426336Ssam     /*
118526336Ssam      * "r" is now the address of the pte of the page
118626336Ssam      * we are interested in; get the pte and paste up the physical address.
118726336Ssam      */
118826336Ssam     fseek(corefile, r, 0);
118926336Ssam     n = fread(&pte, sizeof(pte), 1, corefile);
119026336Ssam     if (n != 1) {
119126336Ssam 	error("page table botch (fread at %x returns %d)", r, n);
119226336Ssam     }
119326336Ssam     if (pte.pg_v == 0 and (pte.pg_fod != 0 or pte.pg_pfnum == 0)) {
119426336Ssam 	error("page no valid or reclamable");
119526336Ssam     }
119626336Ssam     return (addr&PGOFSET) + ((Address) ptob(pte.pg_pfnum));
119726336Ssam }
1198