xref: /csrg-svn/old/dbx/vax.c (revision 33340)
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*33340Sdonn static char sccsid[] = "@(#)vax.c	5.4 (Berkeley) 01/12/88";
921608Sdist #endif not lint
109668Slinton 
11*33340Sdonn static char rcsid[] = "$Header: machine.c,v 1.2 87/03/26 14:54:55 donn 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"
27*33340Sdonn #include "tree.h"
28*33340Sdonn #include "eval.h"
2918222Slinton #include "keywords.h"
309693Slinton #include "ops.h"
319668Slinton 
329668Slinton #ifndef public
339668Slinton typedef unsigned int Address;
349668Slinton typedef unsigned char Byte;
359668Slinton typedef unsigned int Word;
369668Slinton 
379668Slinton #define NREG 16
389668Slinton 
399668Slinton #define ARGP 12
409668Slinton #define FRP 13
419668Slinton #define STKP 14
429668Slinton #define PROGCTR 15
439668Slinton 
44*33340Sdonn #define CODESTART 0
45*33340Sdonn #define FUNCOFFSET 2
46*33340Sdonn 
47*33340Sdonn #define nargspassed(frame) argn(0, frame)
48*33340Sdonn 
499668Slinton #define BITSPERBYTE 8
509668Slinton #define BITSPERWORD (BITSPERBYTE * sizeof(Word))
519668Slinton 
5226336Ssam /*
53*33340Sdonn  * This magic macro enables us to look at the process' registers
54*33340Sdonn  * in its user structure.
5526336Ssam  */
569668Slinton 
57*33340Sdonn #define regloc(reg)	(ctob(UPAGES) + (sizeof(Word) * (reg)))
5826336Ssam 
599668Slinton #include "source.h"
609668Slinton #include "symbols.h"
61*33340Sdonn #include <signal.h>
6226344Ssam #include <sys/param.h>
6326344Ssam #include <sys/dir.h>
6426344Ssam #include <machine/psl.h>
6526344Ssam #include <machine/pte.h>
6626344Ssam #include <sys/user.h>
67*33340Sdonn #undef DELETE /* XXX */
6826344Ssam #include <sys/vm.h>
6926344Ssam #include <machine/reg.h>
709668Slinton 
719668Slinton Address pc;
729668Slinton Address prtaddr;
739668Slinton 
749668Slinton #endif
759668Slinton 
76*33340Sdonn /*
77*33340Sdonn  * Indices into u. for use in collecting registers values.
78*33340Sdonn  */
79*33340Sdonn public int rloc[] ={
80*33340Sdonn     R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, AP, FP, SP, PC
81*33340Sdonn };
82*33340Sdonn 
839668Slinton private Address printop();
849668Slinton 
85*33340Sdonn private Optab *ioptab[256];	/* index by opcode to optab */
86*33340Sdonn 
879668Slinton /*
88*33340Sdonn  * Initialize the opcode lookup table.
8926344Ssam  */
90*33340Sdonn public optab_init()
91*33340Sdonn {
92*33340Sdonn 	register Optab *p;
9326344Ssam 
94*33340Sdonn 	for (p = optab; p->iname; p++)
95*33340Sdonn 		ioptab[p->val & 0xff] = p;
96*33340Sdonn }
97*33340Sdonn 
9826344Ssam /*
999668Slinton  * Decode and print the instructions within the given address range.
1009668Slinton  */
1019668Slinton 
1029668Slinton public printinst(lowaddr, highaddr)
1039668Slinton Address lowaddr;
1049668Slinton Address highaddr;
1059668Slinton {
1069668Slinton     register Address addr;
1079668Slinton 
1089668Slinton     for (addr = lowaddr; addr <= highaddr; ) {
1099668Slinton 	addr = printop(addr);
1109668Slinton     }
1119668Slinton     prtaddr = addr;
1129668Slinton }
1139668Slinton 
1149668Slinton /*
1159668Slinton  * Another approach:  print n instructions starting at the given address.
1169668Slinton  */
1179668Slinton 
1189668Slinton public printninst(count, addr)
1199668Slinton int count;
1209668Slinton Address addr;
1219668Slinton {
1229668Slinton     register Integer i;
1239668Slinton     register Address newaddr;
1249668Slinton 
1259668Slinton     if (count <= 0) {
1269668Slinton 	error("non-positive repetition count");
1279668Slinton     } else {
1289668Slinton 	newaddr = addr;
1299668Slinton 	for (i = 0; i < count; i++) {
1309668Slinton 	    newaddr = printop(newaddr);
1319668Slinton 	}
1329668Slinton 	prtaddr = newaddr;
1339668Slinton     }
1349668Slinton }
1359668Slinton 
1369668Slinton /*
1379668Slinton  * Print the contents of the addresses within the given range
1389668Slinton  * according to the given format.
1399668Slinton  */
1409668Slinton 
1419668Slinton typedef struct {
1429668Slinton     String name;
1439668Slinton     String printfstring;
1449668Slinton     int length;
1459668Slinton } Format;
1469668Slinton 
1479668Slinton private Format fmt[] = {
1489668Slinton     { "d", " %d", sizeof(short) },
1499668Slinton     { "D", " %ld", sizeof(long) },
1509668Slinton     { "o", " %o", sizeof(short) },
1519668Slinton     { "O", " %lo", sizeof(long) },
1529668Slinton     { "x", " %04x", sizeof(short) },
1539668Slinton     { "X", " %08x", sizeof(long) },
1549668Slinton     { "b", " \\%o", sizeof(char) },
1559668Slinton     { "c", " '%c'", sizeof(char) },
1569668Slinton     { "s", "%c", sizeof(char) },
15714338Slinton     { "f", " %f", sizeof(float) },
1589668Slinton     { "g", " %g", sizeof(double) },
1599668Slinton     { nil, nil, 0 }
1609668Slinton };
1619668Slinton 
16211174Slinton private Format *findformat(s)
16311174Slinton String s;
16411174Slinton {
16511174Slinton     register Format *f;
16611174Slinton 
16711174Slinton     f = &fmt[0];
16811174Slinton     while (f->name != nil and not streq(f->name, s)) {
16911174Slinton 	++f;
17011174Slinton     }
17111174Slinton     if (f->name == nil) {
17211174Slinton 	error("bad print format \"%s\"", s);
17311174Slinton     }
17411174Slinton     return f;
17511174Slinton }
17611174Slinton 
177*33340Sdonn /*
178*33340Sdonn  * Retrieve and print out the appropriate data in the given format.
179*33340Sdonn  * Floats have to be handled specially to allow the compiler to
180*33340Sdonn  * convert them to doubles when passing to printf.
181*33340Sdonn  */
182*33340Sdonn 
183*33340Sdonn private printformat (f, addr)
184*33340Sdonn Format *f;
185*33340Sdonn Address addr;
186*33340Sdonn {
187*33340Sdonn     union {
188*33340Sdonn 	char charv;
189*33340Sdonn 	short shortv;
190*33340Sdonn 	int intv;
191*33340Sdonn 	float floatv;
192*33340Sdonn 	double doublev;
193*33340Sdonn     } value;
194*33340Sdonn 
195*33340Sdonn     value.intv = 0;
196*33340Sdonn     dread(&value, addr, f->length);
197*33340Sdonn     if (streq(f->name, "f")) {
198*33340Sdonn 	printf(f->printfstring, value.floatv);
199*33340Sdonn     } else {
200*33340Sdonn 	printf(f->printfstring, value);
201*33340Sdonn     }
202*33340Sdonn }
203*33340Sdonn 
2049668Slinton public Address printdata(lowaddr, highaddr, format)
2059668Slinton Address lowaddr;
2069668Slinton Address highaddr;
2079668Slinton String format;
2089668Slinton {
209*33340Sdonn     int n;
2109668Slinton     register Address addr;
211*33340Sdonn     Format *f;
2129668Slinton 
2139668Slinton     if (lowaddr > highaddr) {
2149668Slinton 	error("first address larger than second");
2159668Slinton     }
21611174Slinton     f = findformat(format);
2179668Slinton     n = 0;
2189668Slinton     for (addr = lowaddr; addr <= highaddr; addr += f->length) {
2199668Slinton 	if (n == 0) {
2209668Slinton 	    printf("%08x: ", addr);
2219668Slinton 	}
222*33340Sdonn 	printformat(f, addr);
2239668Slinton 	++n;
2249668Slinton 	if (n >= (16 div f->length)) {
225*33340Sdonn 	    printf("\n");
2269668Slinton 	    n = 0;
2279668Slinton 	}
2289668Slinton     }
2299668Slinton     if (n != 0) {
230*33340Sdonn 	printf("\n");
2319668Slinton     }
2329668Slinton     prtaddr = addr;
2339668Slinton     return addr;
2349668Slinton }
2359668Slinton 
2369668Slinton /*
2379668Slinton  * The other approach is to print n items starting with a given address.
2389668Slinton  */
2399668Slinton 
2409668Slinton public printndata(count, startaddr, format)
2419668Slinton int count;
2429668Slinton Address startaddr;
2439668Slinton String format;
2449668Slinton {
245*33340Sdonn     int i, n;
246*33340Sdonn     Address addr;
247*33340Sdonn     Format *f;
248*33340Sdonn     Boolean isstring;
24914338Slinton     char c;
2509668Slinton 
2519668Slinton     if (count <= 0) {
2529668Slinton 	error("non-positive repetition count");
2539668Slinton     }
25411174Slinton     f = findformat(format);
2559668Slinton     isstring = (Boolean) streq(f->name, "s");
2569668Slinton     n = 0;
2579668Slinton     addr = startaddr;
2589668Slinton     for (i = 0; i < count; i++) {
2599668Slinton 	if (n == 0) {
2609668Slinton 	    printf("%08x: ", addr);
2619668Slinton 	}
2629668Slinton 	if (isstring) {
263*33340Sdonn 	    printf("\"");
26414338Slinton 	    dread(&c, addr, sizeof(char));
26514338Slinton 	    while (c != '\0') {
26614338Slinton 		printchar(c);
2679668Slinton 		++addr;
26814338Slinton 		dread(&c, addr, sizeof(char));
2699668Slinton 	    }
270*33340Sdonn 	    printf("\"\n");
2719668Slinton 	    n = 0;
2729668Slinton 	    addr += sizeof(String);
2739668Slinton 	} else {
274*33340Sdonn 	    printformat(f, addr);
2759668Slinton 	    ++n;
2769668Slinton 	    if (n >= (16 div f->length)) {
277*33340Sdonn 		printf("\n");
2789668Slinton 		n = 0;
2799668Slinton 	    }
2809668Slinton 	    addr += f->length;
2819668Slinton 	}
2829668Slinton     }
2839668Slinton     if (n != 0) {
284*33340Sdonn 	printf("\n");
2859668Slinton     }
2869668Slinton     prtaddr = addr;
2879668Slinton }
2889668Slinton 
2899668Slinton /*
29011174Slinton  * Print out a value according to the given format.
29111174Slinton  */
29211174Slinton 
29311174Slinton public printvalue(v, format)
29411174Slinton long v;
29511174Slinton String format;
29611174Slinton {
29711174Slinton     Format *f;
29811174Slinton     char *p, *q;
29911174Slinton 
30011174Slinton     f = findformat(format);
30111174Slinton     if (streq(f->name, "s")) {
30211174Slinton 	putchar('"');
30311174Slinton 	p = (char *) &v;
30411174Slinton 	q = p + sizeof(v);
30511174Slinton 	while (p < q) {
30611174Slinton 	    printchar(*p);
30711174Slinton 	    ++p;
30811174Slinton 	}
30911174Slinton 	putchar('"');
31011174Slinton     } else {
31111174Slinton 	printf(f->printfstring, v);
31211174Slinton     }
31311174Slinton     putchar('\n');
31411174Slinton }
31511174Slinton 
31611174Slinton /*
3179668Slinton  * Print out an execution time error.
3189842Slinton  * Assumes the source position of the error has been calculated.
3199668Slinton  *
3209668Slinton  * Have to check if the -r option was specified; if so then
3219668Slinton  * the object file information hasn't been read in yet.
3229668Slinton  */
3239668Slinton 
3249668Slinton public printerror()
3259668Slinton {
3269668Slinton     extern Integer sys_nsig;
3279668Slinton     extern String sys_siglist[];
32818222Slinton     integer err;
3299668Slinton 
3309668Slinton     if (isfinished(process)) {
33116932Ssam 	err = exitcode(process);
33218222Slinton 	if (err == 0) {
33318222Slinton 	    printf("\"%s\" terminated normally\n", objname);
33418222Slinton 	} else {
33518222Slinton 	    printf("\"%s\" terminated abnormally (exit code %d)\n",
33618222Slinton 		objname, err
33718222Slinton 	    );
33818222Slinton 	}
3399668Slinton 	erecover();
3409668Slinton     }
3419668Slinton     err = errnum(process);
3429668Slinton     putchar('\n');
34316932Ssam     printsig(err);
34418222Slinton     putchar(' ');
34516932Ssam     printloc();
34616932Ssam     putchar('\n');
3479668Slinton     if (curline > 0) {
3489668Slinton 	printlines(curline, curline);
3499668Slinton     } else {
3509668Slinton 	printinst(pc, pc);
3519668Slinton     }
3529668Slinton     erecover();
3539668Slinton }
3549668Slinton 
35518222Slinton /*
35618222Slinton  * Print out a signal.
35718222Slinton  */
35818222Slinton 
35916932Ssam private String illinames[] = {
36018222Slinton     "reserved addressing fault",
361*33340Sdonn     "privileged instruction fault",
36218222Slinton     "reserved operand fault"
36316932Ssam };
36418222Slinton 
36516932Ssam private String fpenames[] = {
36618222Slinton     nil,
36718222Slinton     "integer overflow trap",
36818222Slinton     "integer divide by zero trap",
36918222Slinton     "floating overflow trap",
37018222Slinton     "floating/decimal divide by zero trap",
37118222Slinton     "floating underflow trap",
37218222Slinton     "decimal overflow trap",
37318222Slinton     "subscript out of range trap",
37418222Slinton     "floating overflow fault",
37518222Slinton     "floating divide by zero fault",
376*33340Sdonn     "floating underflow fault"
37716932Ssam };
37816932Ssam 
37918222Slinton public printsig (signo)
38018222Slinton integer signo;
38116932Ssam {
38218222Slinton     integer code;
38316932Ssam 
38418222Slinton     if (signo < 0 or signo > sys_nsig) {
38518222Slinton 	printf("[signal %d]", signo);
38618222Slinton     } else {
38718222Slinton 	printf("%s", sys_siglist[signo]);
38816932Ssam     }
38918222Slinton     code = errcode(process);
39018222Slinton     if (signo == SIGILL) {
39118222Slinton 	if (code >= 0 and code < sizeof(illinames) / sizeof(illinames[0])) {
39218222Slinton 	    printf(" (%s)", illinames[code]);
39318222Slinton 	}
39418222Slinton     } else if (signo == SIGFPE) {
39518222Slinton 	if (code > 0 and code < sizeof(fpenames) / sizeof(fpenames[0])) {
39618222Slinton 	    printf(" (%s)", fpenames[code]);
39718222Slinton 	}
39818222Slinton     }
39916932Ssam }
40016932Ssam 
4019668Slinton /*
4029668Slinton  * Note the termination of the program.  We do this so as to avoid
4039668Slinton  * having the process exit, which would make the values of variables
4049668Slinton  * inaccessible.  We do want to flush all output buffers here,
4059668Slinton  * otherwise it'll never get done.
4069668Slinton  */
4079668Slinton 
4089668Slinton public endprogram()
4099668Slinton {
4109668Slinton     Integer exitcode;
4119668Slinton 
4129668Slinton     stepto(nextaddr(pc, true));
4139668Slinton     printnews();
4149668Slinton     exitcode = argn(1, nil);
41518222Slinton     if (exitcode != 0) {
41618222Slinton 	printf("\nexecution completed (exit code %d)\n", exitcode);
41718222Slinton     } else {
41818222Slinton 	printf("\nexecution completed\n");
41918222Slinton     }
4209668Slinton     getsrcpos();
4219668Slinton     erecover();
4229668Slinton }
4239668Slinton 
4249668Slinton /*
4259668Slinton  * Single step the machine a source line (or instruction if "inst_tracing"
42610621Slinton  * is true).  If "isnext" is true, skip over procedure calls.
4279668Slinton  */
4289668Slinton 
4299668Slinton private Address getcall();
4309668Slinton 
4319668Slinton public dostep(isnext)
4329668Slinton Boolean isnext;
4339668Slinton {
4349668Slinton     register Address addr;
4359668Slinton     register Lineno line;
4369668Slinton     String filename;
43718222Slinton     Address startaddr;
4389668Slinton 
43916612Ssam     startaddr = pc;
4409668Slinton     addr = nextaddr(pc, isnext);
44110621Slinton     if (not inst_tracing and nlhdr.nlines != 0) {
4429668Slinton 	line = linelookup(addr);
4439668Slinton 	while (line == 0) {
44418222Slinton 	    addr = nextaddr(addr, isnext);
4459668Slinton 	    line = linelookup(addr);
4469668Slinton 	}
44710621Slinton 	curline = line;
44810621Slinton     } else {
44910621Slinton 	curline = 0;
4509668Slinton     }
4519668Slinton     stepto(addr);
4529668Slinton     filename = srcfilename(addr);
4539668Slinton     setsource(filename);
4549668Slinton }
4559668Slinton 
456*33340Sdonn typedef char Bpinst;
457*33340Sdonn 
458*33340Sdonn #define BP_OP       O_BPT       /* breakpoint trap */
459*33340Sdonn 
460*33340Sdonn #define BP_ERRNO    SIGTRAP     /* signal received at a breakpoint */
461*33340Sdonn 
4629668Slinton /*
463*33340Sdonn  * Setting a breakpoint at a location consists of saving
464*33340Sdonn  * the word at the location and poking a BP_OP there.
465*33340Sdonn  *
466*33340Sdonn  * We save the locations and words on a list for use in unsetting.
467*33340Sdonn  */
468*33340Sdonn 
469*33340Sdonn typedef struct Savelist *Savelist;
470*33340Sdonn 
471*33340Sdonn struct Savelist {
472*33340Sdonn     Address location;
473*33340Sdonn     Bpinst save;
474*33340Sdonn     short refcount;
475*33340Sdonn     Savelist link;
476*33340Sdonn };
477*33340Sdonn 
478*33340Sdonn private Savelist savelist;
479*33340Sdonn 
480*33340Sdonn /*
481*33340Sdonn  * Set a breakpoint at the given address.  Only save the word there
482*33340Sdonn  * if it's not already a breakpoint.
483*33340Sdonn  */
484*33340Sdonn 
485*33340Sdonn public setbp(addr)
486*33340Sdonn Address addr;
487*33340Sdonn {
488*33340Sdonn     Bpinst w, save;
489*33340Sdonn     register Savelist newsave, s;
490*33340Sdonn 
491*33340Sdonn     for (s = savelist; s != nil; s = s->link) {
492*33340Sdonn 	if (s->location == addr) {
493*33340Sdonn 	    s->refcount++;
494*33340Sdonn 	    return;
495*33340Sdonn 	}
496*33340Sdonn     }
497*33340Sdonn     iread(&save, addr, sizeof(save));
498*33340Sdonn     newsave = new(Savelist);
499*33340Sdonn     newsave->location = addr;
500*33340Sdonn     newsave->save = save;
501*33340Sdonn     newsave->refcount = 1;
502*33340Sdonn     newsave->link = savelist;
503*33340Sdonn     savelist = newsave;
504*33340Sdonn     w = BP_OP;
505*33340Sdonn     iwrite(&w, addr, sizeof(w));
506*33340Sdonn }
507*33340Sdonn 
508*33340Sdonn /*
509*33340Sdonn  * Unset a breakpoint; unfortunately we have to search the SAVELIST
510*33340Sdonn  * to find the saved value.  The assumption is that the SAVELIST will
511*33340Sdonn  * usually be quite small.
512*33340Sdonn  */
513*33340Sdonn 
514*33340Sdonn public unsetbp(addr)
515*33340Sdonn Address addr;
516*33340Sdonn {
517*33340Sdonn     register Savelist s, prev;
518*33340Sdonn 
519*33340Sdonn     prev = nil;
520*33340Sdonn     for (s = savelist; s != nil; s = s->link) {
521*33340Sdonn 	if (s->location == addr) {
522*33340Sdonn 	    iwrite(&s->save, addr, sizeof(s->save));
523*33340Sdonn 	    s->refcount--;
524*33340Sdonn 	    if (s->refcount == 0) {
525*33340Sdonn 		if (prev == nil) {
526*33340Sdonn 		    savelist = s->link;
527*33340Sdonn 		} else {
528*33340Sdonn 		    prev->link = s->link;
529*33340Sdonn 		}
530*33340Sdonn 		dispose(s);
531*33340Sdonn 	    }
532*33340Sdonn 	    return;
533*33340Sdonn 	}
534*33340Sdonn 	prev = s;
535*33340Sdonn     }
536*33340Sdonn     panic("unsetbp: couldn't find address %d", addr);
537*33340Sdonn }
538*33340Sdonn 
539*33340Sdonn /*
540*33340Sdonn  * VAX instruction decoder, derived from adb.
541*33340Sdonn  */
542*33340Sdonn 
543*33340Sdonn private Address printop(addr)
544*33340Sdonn Address addr;
545*33340Sdonn {
546*33340Sdonn     register Optab *op;
547*33340Sdonn     VaxOpcode ins;
548*33340Sdonn     unsigned char mode;
549*33340Sdonn     int argtype, amode, argno, argval;
550*33340Sdonn     String reg;
551*33340Sdonn     Boolean indexf;
552*33340Sdonn     short offset;
553*33340Sdonn 
554*33340Sdonn     argval = 0;
555*33340Sdonn     indexf = false;
556*33340Sdonn     printf("%08x  ", addr);
557*33340Sdonn     iread(&ins, addr, sizeof(ins));
558*33340Sdonn     addr += 1;
559*33340Sdonn     op = ioptab[ins];
560*33340Sdonn     printf("%s", op->iname);
561*33340Sdonn     for (argno = 0; argno < op->numargs; argno++) {
562*33340Sdonn 	if (indexf == true) {
563*33340Sdonn 	    indexf = false;
564*33340Sdonn 	} else if (argno == 0) {
565*33340Sdonn 	    printf("\t");
566*33340Sdonn 	} else {
567*33340Sdonn 	    printf(",");
568*33340Sdonn 	}
569*33340Sdonn 	argtype = op->argtype[argno];
570*33340Sdonn 	if (is_branch_disp(argtype)) {
571*33340Sdonn 	    mode = 0xAF + (typelen(argtype) << 5);
572*33340Sdonn 	} else {
573*33340Sdonn 	    iread(&mode, addr, sizeof(mode));
574*33340Sdonn 	    addr += 1;
575*33340Sdonn 	}
576*33340Sdonn 	reg = regname[regnm(mode)];
577*33340Sdonn 	amode = addrmode(mode);
578*33340Sdonn 	switch (amode) {
579*33340Sdonn 	    case LITSHORT:
580*33340Sdonn 	    case LITUPTO31:
581*33340Sdonn 	    case LITUPTO47:
582*33340Sdonn 	    case LITUPTO63:
583*33340Sdonn 		if (typelen(argtype) == TYPF || typelen(argtype) ==TYPD)
584*33340Sdonn 		    printf("$%s", fltimm[mode]);
585*33340Sdonn 		else
586*33340Sdonn 		    printf("$%x", mode);
587*33340Sdonn 		argval = mode;
588*33340Sdonn 		break;
589*33340Sdonn 
590*33340Sdonn 	    case INDEX:
591*33340Sdonn 		printf("[%s]", reg);
592*33340Sdonn 		indexf = true;
593*33340Sdonn 		argno--;
594*33340Sdonn 		break;
595*33340Sdonn 
596*33340Sdonn 	    case REG:
597*33340Sdonn 		printf("%s", reg);
598*33340Sdonn 		break;
599*33340Sdonn 
600*33340Sdonn 	    case REGDEF:
601*33340Sdonn 		printf("(%s)", reg);
602*33340Sdonn 		break;
603*33340Sdonn 
604*33340Sdonn 	    case AUTODEC:
605*33340Sdonn 		printf("-(%s)", reg);
606*33340Sdonn 		break;
607*33340Sdonn 
608*33340Sdonn 	    case AUTOINC:
609*33340Sdonn 		if (reg != regname[PROGCTR]) {
610*33340Sdonn 		    printf("(%s)+", reg);
611*33340Sdonn 		} else {
612*33340Sdonn 		    printf("$");
613*33340Sdonn 		    switch (typelen(argtype)) {
614*33340Sdonn 			case TYPB:
615*33340Sdonn 			    argval = printdisp(addr, 1, reg, amode);
616*33340Sdonn 			    addr += 1;
617*33340Sdonn 			    break;
618*33340Sdonn 
619*33340Sdonn 			case TYPW:
620*33340Sdonn 			    argval = printdisp(addr, 2, reg, amode);
621*33340Sdonn 			    addr += 2;
622*33340Sdonn 			    break;
623*33340Sdonn 
624*33340Sdonn 			case TYPL:
625*33340Sdonn 			    argval = printdisp(addr, 4, reg, amode);
626*33340Sdonn 			    addr += 4;
627*33340Sdonn 			    break;
628*33340Sdonn 
629*33340Sdonn 			case TYPF:
630*33340Sdonn 			    iread(&argval, addr, sizeof(argval));
631*33340Sdonn 			    printf("%06x", argval);
632*33340Sdonn 			    addr += 4;
633*33340Sdonn 			    break;
634*33340Sdonn 
635*33340Sdonn 			case TYPQ:
636*33340Sdonn 			case TYPD:
637*33340Sdonn 			    iread(&argval, addr, sizeof(argval));
638*33340Sdonn 			    printf("%06x", argval);
639*33340Sdonn 			    iread(&argval, addr+4, sizeof(argval));
640*33340Sdonn 			    printf("%06x", argval);
641*33340Sdonn 			    addr += 8;
642*33340Sdonn 			    break;
643*33340Sdonn 		    }
644*33340Sdonn 		}
645*33340Sdonn 		break;
646*33340Sdonn 
647*33340Sdonn 	    case AUTOINCDEF:
648*33340Sdonn 		if (reg == regname[PROGCTR]) {
649*33340Sdonn 		    printf("*$");
650*33340Sdonn 		    argval = printdisp(addr, 4, reg, amode);
651*33340Sdonn 		    addr += 4;
652*33340Sdonn 		} else {
653*33340Sdonn 		    printf("*(%s)+", reg);
654*33340Sdonn 		}
655*33340Sdonn 		break;
656*33340Sdonn 
657*33340Sdonn 	    case BYTEDISP:
658*33340Sdonn 		argval = printdisp(addr, 1, reg, amode);
659*33340Sdonn 		addr += 1;
660*33340Sdonn 		break;
661*33340Sdonn 
662*33340Sdonn 	    case BYTEDISPDEF:
663*33340Sdonn 		printf("*");
664*33340Sdonn 		argval = printdisp(addr, 1, reg, amode);
665*33340Sdonn 		addr += 1;
666*33340Sdonn 		break;
667*33340Sdonn 
668*33340Sdonn 	    case WORDDISP:
669*33340Sdonn 		argval = printdisp(addr, 2, reg, amode);
670*33340Sdonn 		addr += 2;
671*33340Sdonn 		break;
672*33340Sdonn 
673*33340Sdonn 	    case WORDDISPDEF:
674*33340Sdonn 		printf("*");
675*33340Sdonn 		argval = printdisp(addr, 2, reg, amode);
676*33340Sdonn 		addr += 2;
677*33340Sdonn 		break;
678*33340Sdonn 
679*33340Sdonn 	    case LONGDISP:
680*33340Sdonn 		argval = printdisp(addr, 4, reg, amode);
681*33340Sdonn 		addr += 4;
682*33340Sdonn 		break;
683*33340Sdonn 
684*33340Sdonn 	    case LONGDISPDEF:
685*33340Sdonn 		printf("*");
686*33340Sdonn 		argval = printdisp(addr, 4, reg, amode);
687*33340Sdonn 		addr += 4;
688*33340Sdonn 		break;
689*33340Sdonn 	}
690*33340Sdonn     }
691*33340Sdonn     if (ins == O_CASEB || ins == O_CASEW || ins == O_CASEL) {
692*33340Sdonn 	for (argno = 0; argno <= argval; argno++) {
693*33340Sdonn 	    iread(&offset, addr, sizeof(offset));
694*33340Sdonn 	    printf("\n\t\t%d", offset);
695*33340Sdonn 	    addr += 2;
696*33340Sdonn 	}
697*33340Sdonn     }
698*33340Sdonn     printf("\n");
699*33340Sdonn     return addr;
700*33340Sdonn }
701*33340Sdonn 
702*33340Sdonn /*
703*33340Sdonn  * Print the displacement of an instruction that uses displacement
704*33340Sdonn  * addressing.
705*33340Sdonn  */
706*33340Sdonn 
707*33340Sdonn private int printdisp(addr, nbytes, reg, mode)
708*33340Sdonn Address addr;
709*33340Sdonn int nbytes;
710*33340Sdonn char *reg;
711*33340Sdonn int mode;
712*33340Sdonn {
713*33340Sdonn     char byte;
714*33340Sdonn     short hword;
715*33340Sdonn     int argval;
716*33340Sdonn     Symbol f;
717*33340Sdonn 
718*33340Sdonn     switch (nbytes) {
719*33340Sdonn 	case 1:
720*33340Sdonn 	    iread(&byte, addr, sizeof(byte));
721*33340Sdonn 	    argval = byte;
722*33340Sdonn 	    break;
723*33340Sdonn 
724*33340Sdonn 	case 2:
725*33340Sdonn 	    iread(&hword, addr, sizeof(hword));
726*33340Sdonn 	    argval = hword;
727*33340Sdonn 	    break;
728*33340Sdonn 
729*33340Sdonn 	case 4:
730*33340Sdonn 	    iread(&argval, addr, sizeof(argval));
731*33340Sdonn 	    break;
732*33340Sdonn     }
733*33340Sdonn     if (reg == regname[PROGCTR] && mode >= BYTEDISP) {
734*33340Sdonn 	argval += addr + nbytes;
735*33340Sdonn     }
736*33340Sdonn     if (reg == regname[PROGCTR]) {
737*33340Sdonn 	f = whatblock((Address) argval + 2);
738*33340Sdonn 	if (codeloc(f) == argval + 2) {
739*33340Sdonn 	    printf("%s", symname(f));
740*33340Sdonn 	} else {
741*33340Sdonn 	    printf("%x", argval);
742*33340Sdonn 	}
743*33340Sdonn     } else {
744*33340Sdonn 	if (varIsSet("$hexoffsets")) {
745*33340Sdonn 	    if (argval < 0) {
746*33340Sdonn 		printf("-%x(%s)", -(argval), reg);
747*33340Sdonn 	    } else {
748*33340Sdonn 		printf("%x(%s)", argval, reg);
749*33340Sdonn 	    }
750*33340Sdonn 	} else {
751*33340Sdonn 	    printf("%d(%s)", argval, reg);
752*33340Sdonn 	}
753*33340Sdonn     }
754*33340Sdonn     return argval;
755*33340Sdonn }
756*33340Sdonn 
757*33340Sdonn /*
7589668Slinton  * Compute the next address that will be executed from the given one.
7599668Slinton  * If "isnext" is true then consider a procedure call as straight line code.
7609668Slinton  *
7619668Slinton  * We must unfortunately do much of the same work that is necessary
7629668Slinton  * to print instructions.  In addition we have to deal with branches.
7639668Slinton  * Unconditional branches we just follow, for conditional branches
7649668Slinton  * we continue execution to the current location and then single step
7659668Slinton  * the machine.  We assume that the last argument in an instruction
7669668Slinton  * that branches is the branch address (or relative offset).
7679668Slinton  */
7689668Slinton 
76918222Slinton private Address findnextaddr();
77018222Slinton 
7719668Slinton public Address nextaddr(startaddr, isnext)
7729668Slinton Address startaddr;
77316612Ssam boolean isnext;
77416612Ssam {
77516612Ssam     Address addr;
77616612Ssam 
77716612Ssam     addr = usignal(process);
77816612Ssam     if (addr == 0 or addr == 1) {
77916612Ssam 	addr = findnextaddr(startaddr, isnext);
78016612Ssam     }
78116612Ssam     return addr;
78216612Ssam }
78316612Ssam 
78418222Slinton /*
78518222Slinton  * Determine if it's ok to skip function f entered by instruction ins.
78618222Slinton  * If so, we're going to compute the return address and step to it.
78718222Slinton  * Therefore we cannot skip over a function entered by a jsb or bsb,
78818222Slinton  * since the return address is not easily computed for them.
78918222Slinton  */
79018222Slinton 
79118222Slinton private boolean skipfunc (ins, f)
79218222Slinton VaxOpcode ins;
79318222Slinton Symbol f;
79418222Slinton {
79518222Slinton     boolean b;
79618222Slinton 
79718222Slinton     b = (boolean) (
79818222Slinton 	ins != O_JSB and ins != O_BSBB and ins != O_BSBW and
79918222Slinton 	not inst_tracing and nlhdr.nlines != 0 and
80018222Slinton 	nosource(curfunc) and canskip(curfunc)
80118222Slinton     );
80218222Slinton     return b;
80318222Slinton }
80418222Slinton 
80516612Ssam private Address findnextaddr(startaddr, isnext)
80616612Ssam Address startaddr;
8079668Slinton Boolean isnext;
8089668Slinton {
8099668Slinton     register Address addr;
810*33340Sdonn     register Optab *op;
8119668Slinton     VaxOpcode ins;
8129668Slinton     unsigned char mode;
8139668Slinton     int argtype, amode, argno, argval;
8149668Slinton     String r;
8159668Slinton     Boolean indexf;
8169668Slinton     enum { KNOWN, SEQUENTIAL, BRANCH } addrstatus;
8179668Slinton 
8189668Slinton     argval = 0;
8199668Slinton     indexf = false;
8209668Slinton     addr = startaddr;
8219668Slinton     iread(&ins, addr, sizeof(ins));
8229668Slinton     switch (ins) {
82318222Slinton 	/*
82418222Slinton 	 * It used to be that unconditional jumps and branches were handled
82518222Slinton 	 * by taking their destination address as the next address.  While
82618222Slinton 	 * saving the cost of starting up the process, this approach
82718222Slinton 	 * doesn't work when jumping indirect (since the value in the
82818222Slinton 	 * register might not yet have been set).
82918222Slinton 	 *
83018222Slinton 	 * So unconditional jumps and branches are now handled the same way
83118222Slinton 	 * as conditional jumps and branches.
83218222Slinton 	 *
8339668Slinton 	case O_BRB:
8349668Slinton 	case O_BRW:
8359668Slinton 	    addrstatus = BRANCH;
8369668Slinton 	    break;
83718222Slinton 	 *
83818222Slinton 	 */
8399668Slinton 
8409668Slinton 	case O_BSBB:
8419668Slinton 	case O_BSBW:
8429668Slinton 	case O_JSB:
8439668Slinton 	case O_CALLG:
8449668Slinton 	case O_CALLS:
84518222Slinton 	    addrstatus = KNOWN;
84618222Slinton 	    stepto(addr);
84718222Slinton 	    pstep(process, DEFSIG);
84818222Slinton 	    addr = reg(PROGCTR);
84918222Slinton 	    pc = addr;
85018222Slinton 	    setcurfunc(whatblock(pc));
85118222Slinton 	    if (not isbperr()) {
85218222Slinton 		printstatus();
85318222Slinton 		/* NOTREACHED */
85418222Slinton 	    }
85518222Slinton 	    bpact();
85618222Slinton 	    if (isnext or skipfunc(ins, curfunc)) {
8579668Slinton 		addrstatus = KNOWN;
85818222Slinton 		addr = return_addr();
8599668Slinton 		stepto(addr);
86011864Slinton 		bpact();
86118222Slinton 	    } else {
86218222Slinton 		callnews(/* iscall = */ true);
8639668Slinton 	    }
8649668Slinton 	    break;
8659668Slinton 
8669668Slinton 	case O_RSB:
8679668Slinton 	case O_RET:
8689668Slinton 	    addrstatus = KNOWN;
86918222Slinton 	    stepto(addr);
8709668Slinton 	    callnews(/* iscall = */ false);
87118222Slinton 	    pstep(process, DEFSIG);
87218222Slinton 	    addr = reg(PROGCTR);
87318222Slinton 	    pc = addr;
87418222Slinton 	    if (not isbperr()) {
87518222Slinton 		printstatus();
87616612Ssam 	    }
87711874Slinton 	    bpact();
8789668Slinton 	    break;
8799668Slinton 
88018222Slinton 	case O_BRB: case O_BRW:
88116612Ssam 	case O_JMP: /* because it may be jmp (r1) */
8829668Slinton 	case O_BNEQ: case O_BEQL: case O_BGTR:
8839668Slinton 	case O_BLEQ: case O_BGEQ: case O_BLSS:
8849668Slinton 	case O_BGTRU: case O_BLEQU: case O_BVC:
8859668Slinton 	case O_BVS: case O_BCC: case O_BCS:
8869668Slinton 	case O_CASEB: case O_CASEW: case O_CASEL:
8879668Slinton 	case O_BBS: case O_BBC: case O_BBSS: case O_BBCS:
8889668Slinton 	case O_BBSC: case O_BBCC: case O_BBSSI:
8899668Slinton 	case O_BBCCI: case O_BLBS: case O_BLBC:
8909668Slinton 	case O_ACBL: case O_AOBLSS: case O_AOBLEQ:
8919668Slinton 	case O_SOBGEQ: case O_SOBGTR:
8929668Slinton 	    addrstatus = KNOWN;
8939668Slinton 	    stepto(addr);
89416612Ssam 	    pstep(process, DEFSIG);
8959668Slinton 	    addr = reg(PROGCTR);
8969668Slinton 	    pc = addr;
8979668Slinton 	    if (not isbperr()) {
8989668Slinton 		printstatus();
8999668Slinton 	    }
9009668Slinton 	    break;
9019668Slinton 
9029668Slinton 	default:
9039668Slinton 	    addrstatus = SEQUENTIAL;
9049668Slinton 	    break;
9059668Slinton     }
9069668Slinton     if (addrstatus != KNOWN) {
9079668Slinton 	addr += 1;
908*33340Sdonn 	op = ioptab[ins];
909*33340Sdonn 	for (argno = 0; argno < op->numargs; argno++) {
9109668Slinton 	    if (indexf == true) {
9119668Slinton 		indexf = false;
9129668Slinton 	    }
913*33340Sdonn 	    argtype = op->argtype[argno];
9149668Slinton 	    if (is_branch_disp(argtype)) {
9159668Slinton 		mode = 0xAF + (typelen(argtype) << 5);
9169668Slinton 	    } else {
9179668Slinton 		iread(&mode, addr, sizeof(mode));
9189668Slinton 		addr += 1;
9199668Slinton 	    }
9209668Slinton 	    r = regname[regnm(mode)];
9219668Slinton 	    amode = addrmode(mode);
9229668Slinton 	    switch (amode) {
9239668Slinton 		case LITSHORT:
9249668Slinton 		case LITUPTO31:
9259668Slinton 		case LITUPTO47:
9269668Slinton 		case LITUPTO63:
9279668Slinton 		    argval = mode;
9289668Slinton 		    break;
9299668Slinton 
9309668Slinton 		case INDEX:
9319668Slinton 		    indexf = true;
9329668Slinton 		    --argno;
9339668Slinton 		    break;
9349668Slinton 
9359668Slinton 		case REG:
9369668Slinton 		case REGDEF:
9379668Slinton 		case AUTODEC:
9389668Slinton 		    break;
9399668Slinton 
9409668Slinton 		case AUTOINC:
9419668Slinton 		    if (r == regname[PROGCTR]) {
9429668Slinton 			switch (typelen(argtype)) {
9439668Slinton 			    case TYPB:
9449668Slinton 				argval = getdisp(addr, 1, r, amode);
9459668Slinton 				addr += 1;
9469668Slinton 				break;
9479668Slinton 
9489668Slinton 			    case TYPW:
9499668Slinton 				argval = getdisp(addr, 2, r, amode);
9509668Slinton 				addr += 2;
9519668Slinton 				break;
9529668Slinton 
9539668Slinton 			    case TYPL:
9549668Slinton 				argval = getdisp(addr, 4, r, amode);
9559668Slinton 				addr += 4;
9569668Slinton 				break;
9579668Slinton 
9589668Slinton 			    case TYPF:
9599668Slinton 				iread(&argval, addr, sizeof(argval));
9609668Slinton 				addr += 4;
9619668Slinton 				break;
9629668Slinton 
9639668Slinton 			    case TYPQ:
9649668Slinton 			    case TYPD:
9659668Slinton 				iread(&argval, addr+4, sizeof(argval));
9669668Slinton 				addr += 8;
9679668Slinton 				break;
9689668Slinton 			}
9699668Slinton 		    }
9709668Slinton 		    break;
9719668Slinton 
9729668Slinton 		case AUTOINCDEF:
9739668Slinton 		    if (r == regname[PROGCTR]) {
9749668Slinton 			argval = getdisp(addr, 4, r, amode);
9759668Slinton 			addr += 4;
9769668Slinton 		    }
9779668Slinton 		    break;
9789668Slinton 
9799668Slinton 		case BYTEDISP:
9809668Slinton 		case BYTEDISPDEF:
9819668Slinton 		    argval = getdisp(addr, 1, r, amode);
9829668Slinton 		    addr += 1;
9839668Slinton 		    break;
9849668Slinton 
9859668Slinton 		case WORDDISP:
9869668Slinton 		case WORDDISPDEF:
9879668Slinton 		    argval = getdisp(addr, 2, r, amode);
9889668Slinton 		    addr += 2;
9899668Slinton 		    break;
9909668Slinton 
9919668Slinton 		case LONGDISP:
9929668Slinton 		case LONGDISPDEF:
9939668Slinton 		    argval = getdisp(addr, 4, r, amode);
9949668Slinton 		    addr += 4;
9959668Slinton 		    break;
9969668Slinton 	    }
9979668Slinton 	}
9989668Slinton 	if (ins == O_CALLS or ins == O_CALLG) {
9999668Slinton 	    argval += 2;
10009668Slinton 	}
10019668Slinton 	if (addrstatus == BRANCH) {
10029668Slinton 	    addr = argval;
10039668Slinton 	}
10049668Slinton     }
10059668Slinton     return addr;
10069668Slinton }
10079668Slinton 
10089668Slinton /*
10099668Slinton  * Get the displacement of an instruction that uses displacement addressing.
10109668Slinton  */
10119668Slinton 
10129668Slinton private int getdisp(addr, nbytes, reg, mode)
10139668Slinton Address addr;
10149668Slinton int nbytes;
10159668Slinton String reg;
10169668Slinton int mode;
10179668Slinton {
10189668Slinton     char byte;
10199668Slinton     short hword;
10209668Slinton     int argval;
10219668Slinton 
10229668Slinton     switch (nbytes) {
10239668Slinton 	case 1:
10249668Slinton 	    iread(&byte, addr, sizeof(byte));
10259668Slinton 	    argval = byte;
10269668Slinton 	    break;
10279668Slinton 
10289668Slinton 	case 2:
10299668Slinton 	    iread(&hword, addr, sizeof(hword));
10309668Slinton 	    argval = hword;
10319668Slinton 	    break;
10329668Slinton 
10339668Slinton 	case 4:
10349668Slinton 	    iread(&argval, addr, sizeof(argval));
10359668Slinton 	    break;
10369668Slinton     }
10379668Slinton     if (reg == regname[PROGCTR] && mode >= BYTEDISP) {
10389668Slinton 	argval += addr + nbytes;
10399668Slinton     }
10409668Slinton     return argval;
10419668Slinton }
10429668Slinton 
10439668Slinton /*
10449668Slinton  * Enter a procedure by creating and executing a call instruction.
10459668Slinton  */
10469668Slinton 
10479668Slinton #define CALLSIZE 7	/* size of call instruction */
10489668Slinton 
10499668Slinton public beginproc(p, argc)
10509668Slinton Symbol p;
10519668Slinton Integer argc;
10529668Slinton {
10539668Slinton     char save[CALLSIZE];
10549668Slinton     struct {
10559668Slinton 	VaxOpcode op;
10569668Slinton 	unsigned char numargs;
10579668Slinton 	unsigned char mode;
10589668Slinton 	char addr[sizeof(long)];	/* unaligned long */
10599668Slinton     } call;
10609668Slinton     long dest;
10619668Slinton 
10629668Slinton     pc = 2;
10639668Slinton     iread(save, pc, sizeof(save));
10649668Slinton     call.op = O_CALLS;
10659668Slinton     call.numargs = argc;
10669668Slinton     call.mode = 0xef;
10679668Slinton     dest = codeloc(p) - 2 - (pc + 7);
10689668Slinton     mov(&dest, call.addr, sizeof(call.addr));
10699668Slinton     iwrite(&call, pc, sizeof(call));
10709668Slinton     setreg(PROGCTR, pc);
107116612Ssam     pstep(process, DEFSIG);
10729668Slinton     iwrite(save, pc, sizeof(save));
10739668Slinton     pc = reg(PROGCTR);
10749668Slinton     if (not isbperr()) {
10759668Slinton 	printstatus();
10769668Slinton     }
10779668Slinton }
107826336Ssam 
107926336Ssam /*
108026336Ssam  * Special variables for debugging the kernel.
108126336Ssam  */
108226336Ssam 
108326336Ssam public integer masterpcbb;
108426336Ssam public integer slr;
108526336Ssam public struct pte *sbr;
1086*33340Sdonn private struct pcb pcb;
108726336Ssam 
108826336Ssam public getpcb ()
108926336Ssam {
1090*33340Sdonn     integer i;
1091*33340Sdonn 
1092*33340Sdonn     fseek(corefile, masterpcbb & ~0x80000000, 0);
109326336Ssam     get(corefile, pcb);
109426336Ssam     pcb.pcb_p0lr &= ~AST_CLR;
109526336Ssam     printf("p0br %lx p0lr %lx p1br %lx p1lr %lx\n",
109626336Ssam 	pcb.pcb_p0br, pcb.pcb_p0lr, pcb.pcb_p1br, pcb.pcb_p1lr
109726336Ssam     );
109826336Ssam     setreg(0, pcb.pcb_r0);
109926336Ssam     setreg(1, pcb.pcb_r1);
110026336Ssam     setreg(2, pcb.pcb_r2);
110126336Ssam     setreg(3, pcb.pcb_r3);
110226336Ssam     setreg(4, pcb.pcb_r4);
110326336Ssam     setreg(5, pcb.pcb_r5);
110426336Ssam     setreg(6, pcb.pcb_r6);
110526336Ssam     setreg(7, pcb.pcb_r7);
110626336Ssam     setreg(8, pcb.pcb_r8);
110726336Ssam     setreg(9, pcb.pcb_r9);
110826336Ssam     setreg(10, pcb.pcb_r10);
110926336Ssam     setreg(11, pcb.pcb_r11);
111026336Ssam     setreg(ARGP, pcb.pcb_ap);
111126336Ssam     setreg(FRP, pcb.pcb_fp);
111226336Ssam     setreg(STKP, pcb.pcb_ksp);
111326336Ssam     setreg(PROGCTR, pcb.pcb_pc);
111426336Ssam }
111526336Ssam 
111626336Ssam public copyregs (savreg, reg)
111726336Ssam Word savreg[], reg[];
111826336Ssam {
111926336Ssam     reg[0] = savreg[R0];
112026336Ssam     reg[1] = savreg[R1];
112126336Ssam     reg[2] = savreg[R2];
112226336Ssam     reg[3] = savreg[R3];
112326336Ssam     reg[4] = savreg[R4];
112426336Ssam     reg[5] = savreg[R5];
112526336Ssam     reg[6] = savreg[R6];
112626336Ssam     reg[7] = savreg[R7];
112726336Ssam     reg[8] = savreg[R8];
112826336Ssam     reg[9] = savreg[R9];
112926336Ssam     reg[10] = savreg[R10];
113026336Ssam     reg[11] = savreg[R11];
113126336Ssam     reg[ARGP] = savreg[AP];
113226336Ssam     reg[FRP] = savreg[FP];
113326336Ssam     reg[STKP] = savreg[SP];
113426336Ssam     reg[PROGCTR] = savreg[PC];
113526336Ssam }
113626336Ssam 
113726336Ssam /*
113826336Ssam  * Map a virtual address to a physical address.
113926336Ssam  */
114026336Ssam 
114126336Ssam public Address vmap (addr)
114226336Ssam Address addr;
114326336Ssam {
114426336Ssam     Address r;
114526336Ssam     integer v, n;
114626336Ssam     struct pte pte;
114726336Ssam 
114826336Ssam     r = addr & ~0xc0000000;
114926336Ssam     v = btop(r);
115026336Ssam     switch (addr&0xc0000000) {
115126336Ssam 	case 0xc0000000:
115226336Ssam 	case 0x80000000:
115326336Ssam 	    /*
115426336Ssam 	     * In system space, so get system pte.
115526336Ssam 	     * If it is valid or reclaimable then the physical address
115626336Ssam 	     * is the combination of its page number and the page offset
115726336Ssam 	     * of the original address.
115826336Ssam 	     */
115926336Ssam 	    if (v >= slr) {
116026336Ssam 		error("address %x out of segment", addr);
116126336Ssam 	    }
116226336Ssam 	    r = ((long) (sbr + v)) & ~0x80000000;
116326336Ssam 	    goto simple;
116426336Ssam 
116526336Ssam 	case 0x40000000:
116626336Ssam 	    /*
116726336Ssam 	     * In p1 space, must not be in shadow region.
116826336Ssam 	     */
116926336Ssam 	    if (v < pcb.pcb_p1lr) {
117026336Ssam 		error("address %x out of segment", addr);
117126336Ssam 	    }
117226336Ssam 	    r = (Address) (pcb.pcb_p1br + v);
117326336Ssam 	    break;
117426336Ssam 
117526336Ssam 	case 0x00000000:
117626336Ssam 	    /*
117726336Ssam 	     * In p0 space, must not be off end of region.
117826336Ssam 	     */
117926336Ssam 	    if (v >= pcb.pcb_p0lr) {
118026336Ssam 		error("address %x out of segment", addr);
118126336Ssam 	    }
118226336Ssam 	    r = (Address) (pcb.pcb_p0br + v);
118326336Ssam 	    break;
118426336Ssam 
118526336Ssam 	default:
118626336Ssam 	    /* do nothing */
118726336Ssam 	    break;
118826336Ssam     }
118926336Ssam     /*
119026336Ssam      * For p0/p1 address, user-level page table should be in
119126336Ssam      * kernel virtual memory.  Do second-level indirect by recursing.
119226336Ssam      */
119326336Ssam     if ((r & 0x80000000) == 0) {
119426336Ssam 	error("bad p0br or p1br in pcb");
119526336Ssam     }
119626336Ssam     r = vmap(r);
119726336Ssam simple:
119826336Ssam     /*
119926336Ssam      * "r" is now the address of the pte of the page
120026336Ssam      * we are interested in; get the pte and paste up the physical address.
120126336Ssam      */
120226336Ssam     fseek(corefile, r, 0);
120326336Ssam     n = fread(&pte, sizeof(pte), 1, corefile);
120426336Ssam     if (n != 1) {
120526336Ssam 	error("page table botch (fread at %x returns %d)", r, n);
120626336Ssam     }
120726336Ssam     if (pte.pg_v == 0 and (pte.pg_fod != 0 or pte.pg_pfnum == 0)) {
120826336Ssam 	error("page no valid or reclamable");
120926336Ssam     }
121026336Ssam     return (addr&PGOFSET) + ((Address) ptob(pte.pg_pfnum));
121126336Ssam }
1212*33340Sdonn 
1213*33340Sdonn /*
1214*33340Sdonn  * Extract a bit field from an integer.
1215*33340Sdonn  */
1216*33340Sdonn 
1217*33340Sdonn public integer extractField (s)
1218*33340Sdonn Symbol s;
1219*33340Sdonn {
1220*33340Sdonn     integer n, nbytes, r;
1221*33340Sdonn 
1222*33340Sdonn     n = 0;
1223*33340Sdonn     nbytes = size(s);
1224*33340Sdonn     if (nbytes > sizeof(n)) {
1225*33340Sdonn 	printf("[bad size in extractField -- word assumed]\n");
1226*33340Sdonn 	nbytes = sizeof(n);
1227*33340Sdonn     }
1228*33340Sdonn     popn(nbytes, &n);
1229*33340Sdonn     r = n >> (s->symvalue.field.offset mod BITSPERBYTE);
1230*33340Sdonn     r &= ((1 << s->symvalue.field.length) - 1);
1231*33340Sdonn     return r;
1232*33340Sdonn }
1233*33340Sdonn 
1234*33340Sdonn /*
1235*33340Sdonn  * Change the length of a value in memory according to a given difference
1236*33340Sdonn  * in the lengths of its new and old types.
1237*33340Sdonn  */
1238*33340Sdonn 
1239*33340Sdonn public loophole (oldlen, newlen)
1240*33340Sdonn integer oldlen, newlen;
1241*33340Sdonn {
1242*33340Sdonn     integer n, i;
1243*33340Sdonn 
1244*33340Sdonn     n = newlen - oldlen;
1245*33340Sdonn     if (n > 0) {
1246*33340Sdonn 	for (i = 0; i < n; i++) {
1247*33340Sdonn 	    sp[i] = '\0';
1248*33340Sdonn 	}
1249*33340Sdonn     }
1250*33340Sdonn     sp += n;
1251*33340Sdonn }
1252