xref: /csrg-svn/old/dbx/vax.c (revision 36169)
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*36169Sdonn static char sccsid[] = "@(#)vax.c	5.5 (Berkeley) 10/26/88";
921608Sdist #endif not lint
109668Slinton 
11*36169Sdonn static char rcsid[] = "$Header: vax.c,v 1.2 88/10/26 18:50:53 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"
2733340Sdonn #include "tree.h"
2833340Sdonn #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 
4433340Sdonn #define CODESTART 0
4533340Sdonn #define FUNCOFFSET 2
4633340Sdonn 
4733340Sdonn #define nargspassed(frame) argn(0, frame)
4833340Sdonn 
499668Slinton #define BITSPERBYTE 8
509668Slinton #define BITSPERWORD (BITSPERBYTE * sizeof(Word))
519668Slinton 
5226336Ssam /*
5333340Sdonn  * This magic macro enables us to look at the process' registers
5433340Sdonn  * in its user structure.
5526336Ssam  */
569668Slinton 
5733340Sdonn #define regloc(reg)	(ctob(UPAGES) + (sizeof(Word) * (reg)))
5826336Ssam 
599668Slinton #include "source.h"
609668Slinton #include "symbols.h"
6133340Sdonn #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>
6733340Sdonn #undef DELETE /* XXX */
6826344Ssam #include <sys/vm.h>
6926344Ssam #include <machine/reg.h>
709668Slinton 
719668Slinton Address pc;
729668Slinton Address prtaddr;
739668Slinton 
749668Slinton #endif
759668Slinton 
7633340Sdonn /*
7733340Sdonn  * Indices into u. for use in collecting registers values.
7833340Sdonn  */
7933340Sdonn public int rloc[] ={
8033340Sdonn     R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, AP, FP, SP, PC
8133340Sdonn };
8233340Sdonn 
839668Slinton private Address printop();
849668Slinton 
8533340Sdonn private Optab *ioptab[256];	/* index by opcode to optab */
86*36169Sdonn private Optab *esctab[256];	/* for extended opcodes */
8733340Sdonn 
889668Slinton /*
8933340Sdonn  * Initialize the opcode lookup table.
9026344Ssam  */
9133340Sdonn public optab_init()
9233340Sdonn {
93*36169Sdonn     register Optab *p;
9426344Ssam 
95*36169Sdonn     for (p = optab; p->iname; p++) {
96*36169Sdonn 	if (p->format == O_ESCD) {
97*36169Sdonn 	    esctab[p->val] = p;
98*36169Sdonn 	} else if (p->format != O_ESCD && p->format != O_ESCE) {
99*36169Sdonn 	    ioptab[p->val] = p;
100*36169Sdonn 	}
101*36169Sdonn     }
10233340Sdonn }
10333340Sdonn 
10426344Ssam /*
1059668Slinton  * Decode and print the instructions within the given address range.
1069668Slinton  */
1079668Slinton 
1089668Slinton public printinst(lowaddr, highaddr)
1099668Slinton Address lowaddr;
1109668Slinton Address highaddr;
1119668Slinton {
1129668Slinton     register Address addr;
1139668Slinton 
1149668Slinton     for (addr = lowaddr; addr <= highaddr; ) {
1159668Slinton 	addr = printop(addr);
1169668Slinton     }
1179668Slinton     prtaddr = addr;
1189668Slinton }
1199668Slinton 
1209668Slinton /*
1219668Slinton  * Another approach:  print n instructions starting at the given address.
1229668Slinton  */
1239668Slinton 
1249668Slinton public printninst(count, addr)
1259668Slinton int count;
1269668Slinton Address addr;
1279668Slinton {
1289668Slinton     register Integer i;
1299668Slinton     register Address newaddr;
1309668Slinton 
1319668Slinton     if (count <= 0) {
1329668Slinton 	error("non-positive repetition count");
1339668Slinton     } else {
1349668Slinton 	newaddr = addr;
1359668Slinton 	for (i = 0; i < count; i++) {
1369668Slinton 	    newaddr = printop(newaddr);
1379668Slinton 	}
1389668Slinton 	prtaddr = newaddr;
1399668Slinton     }
1409668Slinton }
1419668Slinton 
1429668Slinton /*
1439668Slinton  * Print the contents of the addresses within the given range
1449668Slinton  * according to the given format.
1459668Slinton  */
1469668Slinton 
1479668Slinton typedef struct {
1489668Slinton     String name;
1499668Slinton     String printfstring;
1509668Slinton     int length;
1519668Slinton } Format;
1529668Slinton 
1539668Slinton private Format fmt[] = {
1549668Slinton     { "d", " %d", sizeof(short) },
1559668Slinton     { "D", " %ld", sizeof(long) },
1569668Slinton     { "o", " %o", sizeof(short) },
1579668Slinton     { "O", " %lo", sizeof(long) },
1589668Slinton     { "x", " %04x", sizeof(short) },
1599668Slinton     { "X", " %08x", sizeof(long) },
1609668Slinton     { "b", " \\%o", sizeof(char) },
1619668Slinton     { "c", " '%c'", sizeof(char) },
1629668Slinton     { "s", "%c", sizeof(char) },
16314338Slinton     { "f", " %f", sizeof(float) },
1649668Slinton     { "g", " %g", sizeof(double) },
1659668Slinton     { nil, nil, 0 }
1669668Slinton };
1679668Slinton 
16811174Slinton private Format *findformat(s)
16911174Slinton String s;
17011174Slinton {
17111174Slinton     register Format *f;
17211174Slinton 
17311174Slinton     f = &fmt[0];
17411174Slinton     while (f->name != nil and not streq(f->name, s)) {
17511174Slinton 	++f;
17611174Slinton     }
17711174Slinton     if (f->name == nil) {
17811174Slinton 	error("bad print format \"%s\"", s);
17911174Slinton     }
18011174Slinton     return f;
18111174Slinton }
18211174Slinton 
18333340Sdonn /*
18433340Sdonn  * Retrieve and print out the appropriate data in the given format.
18533340Sdonn  * Floats have to be handled specially to allow the compiler to
18633340Sdonn  * convert them to doubles when passing to printf.
18733340Sdonn  */
18833340Sdonn 
18933340Sdonn private printformat (f, addr)
19033340Sdonn Format *f;
19133340Sdonn Address addr;
19233340Sdonn {
19333340Sdonn     union {
19433340Sdonn 	char charv;
19533340Sdonn 	short shortv;
19633340Sdonn 	int intv;
19733340Sdonn 	float floatv;
19833340Sdonn 	double doublev;
19933340Sdonn     } value;
20033340Sdonn 
20133340Sdonn     value.intv = 0;
20233340Sdonn     dread(&value, addr, f->length);
20333340Sdonn     if (streq(f->name, "f")) {
20433340Sdonn 	printf(f->printfstring, value.floatv);
20533340Sdonn     } else {
20633340Sdonn 	printf(f->printfstring, value);
20733340Sdonn     }
20833340Sdonn }
20933340Sdonn 
2109668Slinton public Address printdata(lowaddr, highaddr, format)
2119668Slinton Address lowaddr;
2129668Slinton Address highaddr;
2139668Slinton String format;
2149668Slinton {
21533340Sdonn     int n;
2169668Slinton     register Address addr;
21733340Sdonn     Format *f;
2189668Slinton 
2199668Slinton     if (lowaddr > highaddr) {
2209668Slinton 	error("first address larger than second");
2219668Slinton     }
22211174Slinton     f = findformat(format);
2239668Slinton     n = 0;
2249668Slinton     for (addr = lowaddr; addr <= highaddr; addr += f->length) {
2259668Slinton 	if (n == 0) {
2269668Slinton 	    printf("%08x: ", addr);
2279668Slinton 	}
22833340Sdonn 	printformat(f, addr);
2299668Slinton 	++n;
2309668Slinton 	if (n >= (16 div f->length)) {
23133340Sdonn 	    printf("\n");
2329668Slinton 	    n = 0;
2339668Slinton 	}
2349668Slinton     }
2359668Slinton     if (n != 0) {
23633340Sdonn 	printf("\n");
2379668Slinton     }
2389668Slinton     prtaddr = addr;
2399668Slinton     return addr;
2409668Slinton }
2419668Slinton 
2429668Slinton /*
2439668Slinton  * The other approach is to print n items starting with a given address.
2449668Slinton  */
2459668Slinton 
2469668Slinton public printndata(count, startaddr, format)
2479668Slinton int count;
2489668Slinton Address startaddr;
2499668Slinton String format;
2509668Slinton {
25133340Sdonn     int i, n;
25233340Sdonn     Address addr;
25333340Sdonn     Format *f;
25433340Sdonn     Boolean isstring;
25514338Slinton     char c;
2569668Slinton 
2579668Slinton     if (count <= 0) {
2589668Slinton 	error("non-positive repetition count");
2599668Slinton     }
26011174Slinton     f = findformat(format);
2619668Slinton     isstring = (Boolean) streq(f->name, "s");
2629668Slinton     n = 0;
2639668Slinton     addr = startaddr;
2649668Slinton     for (i = 0; i < count; i++) {
2659668Slinton 	if (n == 0) {
2669668Slinton 	    printf("%08x: ", addr);
2679668Slinton 	}
2689668Slinton 	if (isstring) {
26933340Sdonn 	    printf("\"");
27014338Slinton 	    dread(&c, addr, sizeof(char));
27114338Slinton 	    while (c != '\0') {
27214338Slinton 		printchar(c);
2739668Slinton 		++addr;
27414338Slinton 		dread(&c, addr, sizeof(char));
2759668Slinton 	    }
27633340Sdonn 	    printf("\"\n");
2779668Slinton 	    n = 0;
2789668Slinton 	    addr += sizeof(String);
2799668Slinton 	} else {
28033340Sdonn 	    printformat(f, addr);
2819668Slinton 	    ++n;
2829668Slinton 	    if (n >= (16 div f->length)) {
28333340Sdonn 		printf("\n");
2849668Slinton 		n = 0;
2859668Slinton 	    }
2869668Slinton 	    addr += f->length;
2879668Slinton 	}
2889668Slinton     }
2899668Slinton     if (n != 0) {
29033340Sdonn 	printf("\n");
2919668Slinton     }
2929668Slinton     prtaddr = addr;
2939668Slinton }
2949668Slinton 
2959668Slinton /*
29611174Slinton  * Print out a value according to the given format.
29711174Slinton  */
29811174Slinton 
29911174Slinton public printvalue(v, format)
30011174Slinton long v;
30111174Slinton String format;
30211174Slinton {
30311174Slinton     Format *f;
30411174Slinton     char *p, *q;
30511174Slinton 
30611174Slinton     f = findformat(format);
30711174Slinton     if (streq(f->name, "s")) {
30811174Slinton 	putchar('"');
30911174Slinton 	p = (char *) &v;
31011174Slinton 	q = p + sizeof(v);
31111174Slinton 	while (p < q) {
31211174Slinton 	    printchar(*p);
31311174Slinton 	    ++p;
31411174Slinton 	}
31511174Slinton 	putchar('"');
31611174Slinton     } else {
31711174Slinton 	printf(f->printfstring, v);
31811174Slinton     }
31911174Slinton     putchar('\n');
32011174Slinton }
32111174Slinton 
32211174Slinton /*
3239668Slinton  * Print out an execution time error.
3249842Slinton  * Assumes the source position of the error has been calculated.
3259668Slinton  *
3269668Slinton  * Have to check if the -r option was specified; if so then
3279668Slinton  * the object file information hasn't been read in yet.
3289668Slinton  */
3299668Slinton 
3309668Slinton public printerror()
3319668Slinton {
3329668Slinton     extern Integer sys_nsig;
3339668Slinton     extern String sys_siglist[];
33418222Slinton     integer err;
3359668Slinton 
3369668Slinton     if (isfinished(process)) {
33716932Ssam 	err = exitcode(process);
33818222Slinton 	if (err == 0) {
33918222Slinton 	    printf("\"%s\" terminated normally\n", objname);
34018222Slinton 	} else {
34118222Slinton 	    printf("\"%s\" terminated abnormally (exit code %d)\n",
34218222Slinton 		objname, err
34318222Slinton 	    );
34418222Slinton 	}
3459668Slinton 	erecover();
3469668Slinton     }
3479668Slinton     err = errnum(process);
3489668Slinton     putchar('\n');
34916932Ssam     printsig(err);
35018222Slinton     putchar(' ');
35116932Ssam     printloc();
35216932Ssam     putchar('\n');
3539668Slinton     if (curline > 0) {
3549668Slinton 	printlines(curline, curline);
3559668Slinton     } else {
3569668Slinton 	printinst(pc, pc);
3579668Slinton     }
3589668Slinton     erecover();
3599668Slinton }
3609668Slinton 
36118222Slinton /*
36218222Slinton  * Print out a signal.
36318222Slinton  */
36418222Slinton 
36516932Ssam private String illinames[] = {
36618222Slinton     "reserved addressing fault",
36733340Sdonn     "privileged instruction fault",
36818222Slinton     "reserved operand fault"
36916932Ssam };
37018222Slinton 
37116932Ssam private String fpenames[] = {
37218222Slinton     nil,
37318222Slinton     "integer overflow trap",
37418222Slinton     "integer divide by zero trap",
37518222Slinton     "floating overflow trap",
37618222Slinton     "floating/decimal divide by zero trap",
37718222Slinton     "floating underflow trap",
37818222Slinton     "decimal overflow trap",
37918222Slinton     "subscript out of range trap",
38018222Slinton     "floating overflow fault",
38118222Slinton     "floating divide by zero fault",
38233340Sdonn     "floating underflow fault"
38316932Ssam };
38416932Ssam 
38518222Slinton public printsig (signo)
38618222Slinton integer signo;
38716932Ssam {
38818222Slinton     integer code;
38916932Ssam 
39018222Slinton     if (signo < 0 or signo > sys_nsig) {
39118222Slinton 	printf("[signal %d]", signo);
39218222Slinton     } else {
39318222Slinton 	printf("%s", sys_siglist[signo]);
39416932Ssam     }
39518222Slinton     code = errcode(process);
39618222Slinton     if (signo == SIGILL) {
39718222Slinton 	if (code >= 0 and code < sizeof(illinames) / sizeof(illinames[0])) {
39818222Slinton 	    printf(" (%s)", illinames[code]);
39918222Slinton 	}
40018222Slinton     } else if (signo == SIGFPE) {
40118222Slinton 	if (code > 0 and code < sizeof(fpenames) / sizeof(fpenames[0])) {
40218222Slinton 	    printf(" (%s)", fpenames[code]);
40318222Slinton 	}
40418222Slinton     }
40516932Ssam }
40616932Ssam 
4079668Slinton /*
4089668Slinton  * Note the termination of the program.  We do this so as to avoid
4099668Slinton  * having the process exit, which would make the values of variables
4109668Slinton  * inaccessible.  We do want to flush all output buffers here,
4119668Slinton  * otherwise it'll never get done.
4129668Slinton  */
4139668Slinton 
4149668Slinton public endprogram()
4159668Slinton {
4169668Slinton     Integer exitcode;
4179668Slinton 
4189668Slinton     stepto(nextaddr(pc, true));
4199668Slinton     printnews();
4209668Slinton     exitcode = argn(1, nil);
42118222Slinton     if (exitcode != 0) {
42218222Slinton 	printf("\nexecution completed (exit code %d)\n", exitcode);
42318222Slinton     } else {
42418222Slinton 	printf("\nexecution completed\n");
42518222Slinton     }
4269668Slinton     getsrcpos();
4279668Slinton     erecover();
4289668Slinton }
4299668Slinton 
4309668Slinton /*
4319668Slinton  * Single step the machine a source line (or instruction if "inst_tracing"
43210621Slinton  * is true).  If "isnext" is true, skip over procedure calls.
4339668Slinton  */
4349668Slinton 
4359668Slinton private Address getcall();
4369668Slinton 
4379668Slinton public dostep(isnext)
4389668Slinton Boolean isnext;
4399668Slinton {
4409668Slinton     register Address addr;
4419668Slinton     register Lineno line;
4429668Slinton     String filename;
44318222Slinton     Address startaddr;
4449668Slinton 
44516612Ssam     startaddr = pc;
4469668Slinton     addr = nextaddr(pc, isnext);
44710621Slinton     if (not inst_tracing and nlhdr.nlines != 0) {
4489668Slinton 	line = linelookup(addr);
4499668Slinton 	while (line == 0) {
45018222Slinton 	    addr = nextaddr(addr, isnext);
4519668Slinton 	    line = linelookup(addr);
4529668Slinton 	}
45310621Slinton 	curline = line;
45410621Slinton     } else {
45510621Slinton 	curline = 0;
4569668Slinton     }
4579668Slinton     stepto(addr);
4589668Slinton     filename = srcfilename(addr);
4599668Slinton     setsource(filename);
4609668Slinton }
4619668Slinton 
46233340Sdonn typedef char Bpinst;
46333340Sdonn 
46433340Sdonn #define BP_OP       O_BPT       /* breakpoint trap */
46533340Sdonn 
46633340Sdonn #define BP_ERRNO    SIGTRAP     /* signal received at a breakpoint */
46733340Sdonn 
4689668Slinton /*
46933340Sdonn  * Setting a breakpoint at a location consists of saving
47033340Sdonn  * the word at the location and poking a BP_OP there.
47133340Sdonn  *
47233340Sdonn  * We save the locations and words on a list for use in unsetting.
47333340Sdonn  */
47433340Sdonn 
47533340Sdonn typedef struct Savelist *Savelist;
47633340Sdonn 
47733340Sdonn struct Savelist {
47833340Sdonn     Address location;
47933340Sdonn     Bpinst save;
48033340Sdonn     short refcount;
48133340Sdonn     Savelist link;
48233340Sdonn };
48333340Sdonn 
48433340Sdonn private Savelist savelist;
48533340Sdonn 
48633340Sdonn /*
48733340Sdonn  * Set a breakpoint at the given address.  Only save the word there
48833340Sdonn  * if it's not already a breakpoint.
48933340Sdonn  */
49033340Sdonn 
49133340Sdonn public setbp(addr)
49233340Sdonn Address addr;
49333340Sdonn {
49433340Sdonn     Bpinst w, save;
49533340Sdonn     register Savelist newsave, s;
49633340Sdonn 
49733340Sdonn     for (s = savelist; s != nil; s = s->link) {
49833340Sdonn 	if (s->location == addr) {
49933340Sdonn 	    s->refcount++;
50033340Sdonn 	    return;
50133340Sdonn 	}
50233340Sdonn     }
50333340Sdonn     iread(&save, addr, sizeof(save));
50433340Sdonn     newsave = new(Savelist);
50533340Sdonn     newsave->location = addr;
50633340Sdonn     newsave->save = save;
50733340Sdonn     newsave->refcount = 1;
50833340Sdonn     newsave->link = savelist;
50933340Sdonn     savelist = newsave;
51033340Sdonn     w = BP_OP;
51133340Sdonn     iwrite(&w, addr, sizeof(w));
51233340Sdonn }
51333340Sdonn 
51433340Sdonn /*
51533340Sdonn  * Unset a breakpoint; unfortunately we have to search the SAVELIST
51633340Sdonn  * to find the saved value.  The assumption is that the SAVELIST will
51733340Sdonn  * usually be quite small.
51833340Sdonn  */
51933340Sdonn 
52033340Sdonn public unsetbp(addr)
52133340Sdonn Address addr;
52233340Sdonn {
52333340Sdonn     register Savelist s, prev;
52433340Sdonn 
52533340Sdonn     prev = nil;
52633340Sdonn     for (s = savelist; s != nil; s = s->link) {
52733340Sdonn 	if (s->location == addr) {
52833340Sdonn 	    iwrite(&s->save, addr, sizeof(s->save));
52933340Sdonn 	    s->refcount--;
53033340Sdonn 	    if (s->refcount == 0) {
53133340Sdonn 		if (prev == nil) {
53233340Sdonn 		    savelist = s->link;
53333340Sdonn 		} else {
53433340Sdonn 		    prev->link = s->link;
53533340Sdonn 		}
53633340Sdonn 		dispose(s);
53733340Sdonn 	    }
53833340Sdonn 	    return;
53933340Sdonn 	}
54033340Sdonn 	prev = s;
54133340Sdonn     }
54233340Sdonn     panic("unsetbp: couldn't find address %d", addr);
54333340Sdonn }
54433340Sdonn 
54533340Sdonn /*
54633340Sdonn  * VAX instruction decoder, derived from adb.
54733340Sdonn  */
54833340Sdonn 
54933340Sdonn private Address printop(addr)
55033340Sdonn Address addr;
55133340Sdonn {
55233340Sdonn     register Optab *op;
55333340Sdonn     VaxOpcode ins;
55433340Sdonn     unsigned char mode;
55533340Sdonn     int argtype, amode, argno, argval;
55633340Sdonn     String reg;
55733340Sdonn     Boolean indexf;
55833340Sdonn     short offset;
55933340Sdonn 
56033340Sdonn     argval = 0;
56133340Sdonn     indexf = false;
56233340Sdonn     printf("%08x  ", addr);
56333340Sdonn     iread(&ins, addr, sizeof(ins));
56433340Sdonn     addr += 1;
565*36169Sdonn     if (ins == O_ESCF) {
566*36169Sdonn 	iread(&ins, addr, sizeof(ins));
567*36169Sdonn 	addr += 1;
568*36169Sdonn 	op = ioptab[ins];
569*36169Sdonn     } else if (ins == O_ESCD) {
570*36169Sdonn 	iread(&ins, addr, sizeof(ins));
571*36169Sdonn 	addr += 1;
572*36169Sdonn 	op = esctab[ins];
573*36169Sdonn     } else {
574*36169Sdonn 	op = ioptab[ins];
575*36169Sdonn     }
576*36169Sdonn     if (op == nil) {
577*36169Sdonn 	printf("[unrecognized opcode %#0x]\n", ins);
578*36169Sdonn 	return addr;
579*36169Sdonn     }
58033340Sdonn     printf("%s", op->iname);
58133340Sdonn     for (argno = 0; argno < op->numargs; argno++) {
58233340Sdonn 	if (indexf == true) {
58333340Sdonn 	    indexf = false;
58433340Sdonn 	} else if (argno == 0) {
58533340Sdonn 	    printf("\t");
58633340Sdonn 	} else {
58733340Sdonn 	    printf(",");
58833340Sdonn 	}
58933340Sdonn 	argtype = op->argtype[argno];
59033340Sdonn 	if (is_branch_disp(argtype)) {
59133340Sdonn 	    mode = 0xAF + (typelen(argtype) << 5);
59233340Sdonn 	} else {
59333340Sdonn 	    iread(&mode, addr, sizeof(mode));
59433340Sdonn 	    addr += 1;
59533340Sdonn 	}
59633340Sdonn 	reg = regname[regnm(mode)];
59733340Sdonn 	amode = addrmode(mode);
59833340Sdonn 	switch (amode) {
59933340Sdonn 	    case LITSHORT:
60033340Sdonn 	    case LITUPTO31:
60133340Sdonn 	    case LITUPTO47:
60233340Sdonn 	    case LITUPTO63:
603*36169Sdonn 		if (typelen(argtype) == TYPF || typelen(argtype) == TYPD ||
604*36169Sdonn 		    typelen(argtype) == TYPG || typelen(argtype) == TYPH)
60533340Sdonn 		    printf("$%s", fltimm[mode]);
60633340Sdonn 		else
60733340Sdonn 		    printf("$%x", mode);
60833340Sdonn 		argval = mode;
60933340Sdonn 		break;
61033340Sdonn 
61133340Sdonn 	    case INDEX:
61233340Sdonn 		printf("[%s]", reg);
61333340Sdonn 		indexf = true;
61433340Sdonn 		argno--;
61533340Sdonn 		break;
61633340Sdonn 
61733340Sdonn 	    case REG:
61833340Sdonn 		printf("%s", reg);
61933340Sdonn 		break;
62033340Sdonn 
62133340Sdonn 	    case REGDEF:
62233340Sdonn 		printf("(%s)", reg);
62333340Sdonn 		break;
62433340Sdonn 
62533340Sdonn 	    case AUTODEC:
62633340Sdonn 		printf("-(%s)", reg);
62733340Sdonn 		break;
62833340Sdonn 
62933340Sdonn 	    case AUTOINC:
63033340Sdonn 		if (reg != regname[PROGCTR]) {
63133340Sdonn 		    printf("(%s)+", reg);
63233340Sdonn 		} else {
63333340Sdonn 		    printf("$");
63433340Sdonn 		    switch (typelen(argtype)) {
63533340Sdonn 			case TYPB:
63633340Sdonn 			    argval = printdisp(addr, 1, reg, amode);
63733340Sdonn 			    addr += 1;
63833340Sdonn 			    break;
63933340Sdonn 
64033340Sdonn 			case TYPW:
64133340Sdonn 			    argval = printdisp(addr, 2, reg, amode);
64233340Sdonn 			    addr += 2;
64333340Sdonn 			    break;
64433340Sdonn 
64533340Sdonn 			case TYPL:
64633340Sdonn 			    argval = printdisp(addr, 4, reg, amode);
64733340Sdonn 			    addr += 4;
64833340Sdonn 			    break;
64933340Sdonn 
65033340Sdonn 			case TYPF:
65133340Sdonn 			    iread(&argval, addr, sizeof(argval));
652*36169Sdonn 			    if ((argval & 0xffff007f) == 0x8000) {
653*36169Sdonn 				printf("[reserved operand]");
654*36169Sdonn 			    } else {
655*36169Sdonn 				printf("%g", *(float *)&argval);
656*36169Sdonn 			    }
65733340Sdonn 			    addr += 4;
65833340Sdonn 			    break;
65933340Sdonn 
66033340Sdonn 			case TYPD:
661*36169Sdonn 			    /* XXX this bags the low order bits */
66233340Sdonn 			    iread(&argval, addr, sizeof(argval));
663*36169Sdonn 			    if ((argval & 0xffff007f) == 0x8000) {
664*36169Sdonn 				printf("[reserved operand]");
665*36169Sdonn 			    } else {
666*36169Sdonn 				printf("%g", *(float *)&argval);
667*36169Sdonn 			    }
668*36169Sdonn 			    addr += 8;
669*36169Sdonn 			    break;
670*36169Sdonn 
671*36169Sdonn 			case TYPG:
672*36169Sdonn 			case TYPQ:
67333340Sdonn 			    iread(&argval, addr+4, sizeof(argval));
674*36169Sdonn 			    printf("%08x", argval);
675*36169Sdonn 			    iread(&argval, addr, sizeof(argval));
676*36169Sdonn 			    printf("%08x", argval);
67733340Sdonn 			    addr += 8;
67833340Sdonn 			    break;
679*36169Sdonn 
680*36169Sdonn 			case TYPH:
681*36169Sdonn 			case TYPO:
682*36169Sdonn 			    iread(&argval, addr+12, sizeof(argval));
683*36169Sdonn 			    printf("%08x", argval);
684*36169Sdonn 			    iread(&argval, addr+8, sizeof(argval));
685*36169Sdonn 			    printf("%08x", argval);
686*36169Sdonn 			    iread(&argval, addr+4, sizeof(argval));
687*36169Sdonn 			    printf("%08x", argval);
688*36169Sdonn 			    iread(&argval, addr, sizeof(argval));
689*36169Sdonn 			    printf("%08x", argval);
690*36169Sdonn 			    addr += 16;
691*36169Sdonn 			    break;
69233340Sdonn 		    }
69333340Sdonn 		}
69433340Sdonn 		break;
69533340Sdonn 
69633340Sdonn 	    case AUTOINCDEF:
69733340Sdonn 		if (reg == regname[PROGCTR]) {
69833340Sdonn 		    printf("*$");
69933340Sdonn 		    argval = printdisp(addr, 4, reg, amode);
70033340Sdonn 		    addr += 4;
70133340Sdonn 		} else {
70233340Sdonn 		    printf("*(%s)+", reg);
70333340Sdonn 		}
70433340Sdonn 		break;
70533340Sdonn 
70633340Sdonn 	    case BYTEDISP:
70733340Sdonn 		argval = printdisp(addr, 1, reg, amode);
70833340Sdonn 		addr += 1;
70933340Sdonn 		break;
71033340Sdonn 
71133340Sdonn 	    case BYTEDISPDEF:
71233340Sdonn 		printf("*");
71333340Sdonn 		argval = printdisp(addr, 1, reg, amode);
71433340Sdonn 		addr += 1;
71533340Sdonn 		break;
71633340Sdonn 
71733340Sdonn 	    case WORDDISP:
71833340Sdonn 		argval = printdisp(addr, 2, reg, amode);
71933340Sdonn 		addr += 2;
72033340Sdonn 		break;
72133340Sdonn 
72233340Sdonn 	    case WORDDISPDEF:
72333340Sdonn 		printf("*");
72433340Sdonn 		argval = printdisp(addr, 2, reg, amode);
72533340Sdonn 		addr += 2;
72633340Sdonn 		break;
72733340Sdonn 
72833340Sdonn 	    case LONGDISP:
72933340Sdonn 		argval = printdisp(addr, 4, reg, amode);
73033340Sdonn 		addr += 4;
73133340Sdonn 		break;
73233340Sdonn 
73333340Sdonn 	    case LONGDISPDEF:
73433340Sdonn 		printf("*");
73533340Sdonn 		argval = printdisp(addr, 4, reg, amode);
73633340Sdonn 		addr += 4;
73733340Sdonn 		break;
73833340Sdonn 	}
73933340Sdonn     }
74033340Sdonn     if (ins == O_CASEB || ins == O_CASEW || ins == O_CASEL) {
74133340Sdonn 	for (argno = 0; argno <= argval; argno++) {
74233340Sdonn 	    iread(&offset, addr, sizeof(offset));
74333340Sdonn 	    printf("\n\t\t%d", offset);
74433340Sdonn 	    addr += 2;
74533340Sdonn 	}
74633340Sdonn     }
74733340Sdonn     printf("\n");
74833340Sdonn     return addr;
74933340Sdonn }
75033340Sdonn 
75133340Sdonn /*
75233340Sdonn  * Print the displacement of an instruction that uses displacement
75333340Sdonn  * addressing.
75433340Sdonn  */
75533340Sdonn 
75633340Sdonn private int printdisp(addr, nbytes, reg, mode)
75733340Sdonn Address addr;
75833340Sdonn int nbytes;
75933340Sdonn char *reg;
76033340Sdonn int mode;
76133340Sdonn {
76233340Sdonn     char byte;
76333340Sdonn     short hword;
76433340Sdonn     int argval;
76533340Sdonn     Symbol f;
76633340Sdonn 
76733340Sdonn     switch (nbytes) {
76833340Sdonn 	case 1:
76933340Sdonn 	    iread(&byte, addr, sizeof(byte));
77033340Sdonn 	    argval = byte;
77133340Sdonn 	    break;
77233340Sdonn 
77333340Sdonn 	case 2:
77433340Sdonn 	    iread(&hword, addr, sizeof(hword));
77533340Sdonn 	    argval = hword;
77633340Sdonn 	    break;
77733340Sdonn 
77833340Sdonn 	case 4:
77933340Sdonn 	    iread(&argval, addr, sizeof(argval));
78033340Sdonn 	    break;
78133340Sdonn     }
78233340Sdonn     if (reg == regname[PROGCTR] && mode >= BYTEDISP) {
78333340Sdonn 	argval += addr + nbytes;
78433340Sdonn     }
78533340Sdonn     if (reg == regname[PROGCTR]) {
78633340Sdonn 	f = whatblock((Address) argval + 2);
78733340Sdonn 	if (codeloc(f) == argval + 2) {
78833340Sdonn 	    printf("%s", symname(f));
78933340Sdonn 	} else {
79033340Sdonn 	    printf("%x", argval);
79133340Sdonn 	}
79233340Sdonn     } else {
79333340Sdonn 	if (varIsSet("$hexoffsets")) {
79433340Sdonn 	    if (argval < 0) {
79533340Sdonn 		printf("-%x(%s)", -(argval), reg);
79633340Sdonn 	    } else {
79733340Sdonn 		printf("%x(%s)", argval, reg);
79833340Sdonn 	    }
79933340Sdonn 	} else {
80033340Sdonn 	    printf("%d(%s)", argval, reg);
80133340Sdonn 	}
80233340Sdonn     }
80333340Sdonn     return argval;
80433340Sdonn }
80533340Sdonn 
80633340Sdonn /*
8079668Slinton  * Compute the next address that will be executed from the given one.
8089668Slinton  * If "isnext" is true then consider a procedure call as straight line code.
8099668Slinton  *
8109668Slinton  * We must unfortunately do much of the same work that is necessary
8119668Slinton  * to print instructions.  In addition we have to deal with branches.
8129668Slinton  * Unconditional branches we just follow, for conditional branches
8139668Slinton  * we continue execution to the current location and then single step
8149668Slinton  * the machine.  We assume that the last argument in an instruction
8159668Slinton  * that branches is the branch address (or relative offset).
8169668Slinton  */
8179668Slinton 
81818222Slinton private Address findnextaddr();
81918222Slinton 
8209668Slinton public Address nextaddr(startaddr, isnext)
8219668Slinton Address startaddr;
82216612Ssam boolean isnext;
82316612Ssam {
82416612Ssam     Address addr;
82516612Ssam 
82616612Ssam     addr = usignal(process);
82716612Ssam     if (addr == 0 or addr == 1) {
82816612Ssam 	addr = findnextaddr(startaddr, isnext);
82916612Ssam     }
83016612Ssam     return addr;
83116612Ssam }
83216612Ssam 
83318222Slinton /*
83418222Slinton  * Determine if it's ok to skip function f entered by instruction ins.
83518222Slinton  * If so, we're going to compute the return address and step to it.
83618222Slinton  * Therefore we cannot skip over a function entered by a jsb or bsb,
83718222Slinton  * since the return address is not easily computed for them.
83818222Slinton  */
83918222Slinton 
84018222Slinton private boolean skipfunc (ins, f)
84118222Slinton VaxOpcode ins;
84218222Slinton Symbol f;
84318222Slinton {
84418222Slinton     boolean b;
84518222Slinton 
84618222Slinton     b = (boolean) (
84718222Slinton 	ins != O_JSB and ins != O_BSBB and ins != O_BSBW and
84818222Slinton 	not inst_tracing and nlhdr.nlines != 0 and
84918222Slinton 	nosource(curfunc) and canskip(curfunc)
85018222Slinton     );
85118222Slinton     return b;
85218222Slinton }
85318222Slinton 
85416612Ssam private Address findnextaddr(startaddr, isnext)
85516612Ssam Address startaddr;
8569668Slinton Boolean isnext;
8579668Slinton {
8589668Slinton     register Address addr;
85933340Sdonn     register Optab *op;
860*36169Sdonn     VaxOpcode ins, ins2;
8619668Slinton     unsigned char mode;
8629668Slinton     int argtype, amode, argno, argval;
8639668Slinton     String r;
8649668Slinton     Boolean indexf;
8659668Slinton     enum { KNOWN, SEQUENTIAL, BRANCH } addrstatus;
8669668Slinton 
8679668Slinton     argval = 0;
8689668Slinton     indexf = false;
8699668Slinton     addr = startaddr;
8709668Slinton     iread(&ins, addr, sizeof(ins));
8719668Slinton     switch (ins) {
87218222Slinton 	/*
87318222Slinton 	 * It used to be that unconditional jumps and branches were handled
87418222Slinton 	 * by taking their destination address as the next address.  While
87518222Slinton 	 * saving the cost of starting up the process, this approach
87618222Slinton 	 * doesn't work when jumping indirect (since the value in the
87718222Slinton 	 * register might not yet have been set).
87818222Slinton 	 *
87918222Slinton 	 * So unconditional jumps and branches are now handled the same way
88018222Slinton 	 * as conditional jumps and branches.
88118222Slinton 	 *
8829668Slinton 	case O_BRB:
8839668Slinton 	case O_BRW:
8849668Slinton 	    addrstatus = BRANCH;
8859668Slinton 	    break;
88618222Slinton 	 *
88718222Slinton 	 */
8889668Slinton 
8899668Slinton 	case O_BSBB:
8909668Slinton 	case O_BSBW:
8919668Slinton 	case O_JSB:
8929668Slinton 	case O_CALLG:
8939668Slinton 	case O_CALLS:
89418222Slinton 	    addrstatus = KNOWN;
89518222Slinton 	    stepto(addr);
89618222Slinton 	    pstep(process, DEFSIG);
89718222Slinton 	    addr = reg(PROGCTR);
89818222Slinton 	    pc = addr;
89918222Slinton 	    setcurfunc(whatblock(pc));
90018222Slinton 	    if (not isbperr()) {
90118222Slinton 		printstatus();
90218222Slinton 		/* NOTREACHED */
90318222Slinton 	    }
90418222Slinton 	    bpact();
90518222Slinton 	    if (isnext or skipfunc(ins, curfunc)) {
9069668Slinton 		addrstatus = KNOWN;
90718222Slinton 		addr = return_addr();
9089668Slinton 		stepto(addr);
90911864Slinton 		bpact();
91018222Slinton 	    } else {
91118222Slinton 		callnews(/* iscall = */ true);
9129668Slinton 	    }
9139668Slinton 	    break;
9149668Slinton 
9159668Slinton 	case O_RSB:
9169668Slinton 	case O_RET:
9179668Slinton 	    addrstatus = KNOWN;
91818222Slinton 	    stepto(addr);
9199668Slinton 	    callnews(/* iscall = */ false);
92018222Slinton 	    pstep(process, DEFSIG);
92118222Slinton 	    addr = reg(PROGCTR);
92218222Slinton 	    pc = addr;
92318222Slinton 	    if (not isbperr()) {
92418222Slinton 		printstatus();
92516612Ssam 	    }
92611874Slinton 	    bpact();
9279668Slinton 	    break;
9289668Slinton 
92918222Slinton 	case O_BRB: case O_BRW:
93016612Ssam 	case O_JMP: /* because it may be jmp (r1) */
9319668Slinton 	case O_BNEQ: case O_BEQL: case O_BGTR:
9329668Slinton 	case O_BLEQ: case O_BGEQ: case O_BLSS:
9339668Slinton 	case O_BGTRU: case O_BLEQU: case O_BVC:
9349668Slinton 	case O_BVS: case O_BCC: case O_BCS:
9359668Slinton 	case O_CASEB: case O_CASEW: case O_CASEL:
9369668Slinton 	case O_BBS: case O_BBC: case O_BBSS: case O_BBCS:
9379668Slinton 	case O_BBSC: case O_BBCC: case O_BBSSI:
9389668Slinton 	case O_BBCCI: case O_BLBS: case O_BLBC:
9399668Slinton 	case O_ACBL: case O_AOBLSS: case O_AOBLEQ:
9409668Slinton 	case O_SOBGEQ: case O_SOBGTR:
941*36169Sdonn 	case O_ESCF: /* bugchecks */
942*36169Sdonn 	branches:
9439668Slinton 	    addrstatus = KNOWN;
9449668Slinton 	    stepto(addr);
94516612Ssam 	    pstep(process, DEFSIG);
9469668Slinton 	    addr = reg(PROGCTR);
9479668Slinton 	    pc = addr;
9489668Slinton 	    if (not isbperr()) {
9499668Slinton 		printstatus();
9509668Slinton 	    }
9519668Slinton 	    break;
9529668Slinton 
953*36169Sdonn 	case O_ESCD:
954*36169Sdonn 	    iread(&ins2, addr+1, sizeof(ins2));
955*36169Sdonn 	    if (ins2 == O_ACBF || ins2 == O_ACBD)
956*36169Sdonn 		/* actually ACBG and ACBH */
957*36169Sdonn 		goto branches;
958*36169Sdonn 	    /* fall through */
959*36169Sdonn 
9609668Slinton 	default:
9619668Slinton 	    addrstatus = SEQUENTIAL;
9629668Slinton 	    break;
9639668Slinton     }
9649668Slinton     if (addrstatus != KNOWN) {
9659668Slinton 	addr += 1;
966*36169Sdonn 	if (ins == O_ESCD) {
967*36169Sdonn 	    ins = ins2;
968*36169Sdonn 	    addr += 1;
969*36169Sdonn 	    op = esctab[ins];
970*36169Sdonn 	    if (op == nil) {
971*36169Sdonn 		printf("[bad extended opcode %#x in findnextaddr]\n", ins);
972*36169Sdonn 		return addr;
973*36169Sdonn 	    }
974*36169Sdonn 	} else {
975*36169Sdonn 	    op = ioptab[ins];
976*36169Sdonn 	    if (op == nil) {
977*36169Sdonn 		printf("[bad opcode %#x in findnextaddr]\n", ins);
978*36169Sdonn 		return addr;
979*36169Sdonn 	    }
980*36169Sdonn 	}
98133340Sdonn 	for (argno = 0; argno < op->numargs; argno++) {
9829668Slinton 	    if (indexf == true) {
9839668Slinton 		indexf = false;
9849668Slinton 	    }
98533340Sdonn 	    argtype = op->argtype[argno];
9869668Slinton 	    if (is_branch_disp(argtype)) {
9879668Slinton 		mode = 0xAF + (typelen(argtype) << 5);
9889668Slinton 	    } else {
9899668Slinton 		iread(&mode, addr, sizeof(mode));
9909668Slinton 		addr += 1;
9919668Slinton 	    }
9929668Slinton 	    r = regname[regnm(mode)];
9939668Slinton 	    amode = addrmode(mode);
9949668Slinton 	    switch (amode) {
9959668Slinton 		case LITSHORT:
9969668Slinton 		case LITUPTO31:
9979668Slinton 		case LITUPTO47:
9989668Slinton 		case LITUPTO63:
9999668Slinton 		    argval = mode;
10009668Slinton 		    break;
10019668Slinton 
10029668Slinton 		case INDEX:
10039668Slinton 		    indexf = true;
10049668Slinton 		    --argno;
10059668Slinton 		    break;
10069668Slinton 
10079668Slinton 		case REG:
10089668Slinton 		case REGDEF:
10099668Slinton 		case AUTODEC:
10109668Slinton 		    break;
10119668Slinton 
10129668Slinton 		case AUTOINC:
10139668Slinton 		    if (r == regname[PROGCTR]) {
10149668Slinton 			switch (typelen(argtype)) {
10159668Slinton 			    case TYPB:
10169668Slinton 				argval = getdisp(addr, 1, r, amode);
10179668Slinton 				addr += 1;
10189668Slinton 				break;
10199668Slinton 
10209668Slinton 			    case TYPW:
10219668Slinton 				argval = getdisp(addr, 2, r, amode);
10229668Slinton 				addr += 2;
10239668Slinton 				break;
10249668Slinton 
10259668Slinton 			    case TYPL:
10269668Slinton 				argval = getdisp(addr, 4, r, amode);
10279668Slinton 				addr += 4;
10289668Slinton 				break;
10299668Slinton 
10309668Slinton 			    case TYPF:
10319668Slinton 				iread(&argval, addr, sizeof(argval));
10329668Slinton 				addr += 4;
10339668Slinton 				break;
10349668Slinton 
10359668Slinton 			    case TYPQ:
10369668Slinton 			    case TYPD:
1037*36169Sdonn 			    case TYPG:
10389668Slinton 				iread(&argval, addr+4, sizeof(argval));
10399668Slinton 				addr += 8;
10409668Slinton 				break;
1041*36169Sdonn 
1042*36169Sdonn 			    case TYPO:
1043*36169Sdonn 			    case TYPH:
1044*36169Sdonn 				iread(&argval, addr+12, sizeof(argval));
1045*36169Sdonn 				addr += 16;
1046*36169Sdonn 				break;
10479668Slinton 			}
10489668Slinton 		    }
10499668Slinton 		    break;
10509668Slinton 
10519668Slinton 		case AUTOINCDEF:
10529668Slinton 		    if (r == regname[PROGCTR]) {
10539668Slinton 			argval = getdisp(addr, 4, r, amode);
10549668Slinton 			addr += 4;
10559668Slinton 		    }
10569668Slinton 		    break;
10579668Slinton 
10589668Slinton 		case BYTEDISP:
10599668Slinton 		case BYTEDISPDEF:
10609668Slinton 		    argval = getdisp(addr, 1, r, amode);
10619668Slinton 		    addr += 1;
10629668Slinton 		    break;
10639668Slinton 
10649668Slinton 		case WORDDISP:
10659668Slinton 		case WORDDISPDEF:
10669668Slinton 		    argval = getdisp(addr, 2, r, amode);
10679668Slinton 		    addr += 2;
10689668Slinton 		    break;
10699668Slinton 
10709668Slinton 		case LONGDISP:
10719668Slinton 		case LONGDISPDEF:
10729668Slinton 		    argval = getdisp(addr, 4, r, amode);
10739668Slinton 		    addr += 4;
10749668Slinton 		    break;
10759668Slinton 	    }
10769668Slinton 	}
10779668Slinton 	if (ins == O_CALLS or ins == O_CALLG) {
10789668Slinton 	    argval += 2;
10799668Slinton 	}
10809668Slinton 	if (addrstatus == BRANCH) {
10819668Slinton 	    addr = argval;
10829668Slinton 	}
10839668Slinton     }
10849668Slinton     return addr;
10859668Slinton }
10869668Slinton 
10879668Slinton /*
10889668Slinton  * Get the displacement of an instruction that uses displacement addressing.
10899668Slinton  */
10909668Slinton 
10919668Slinton private int getdisp(addr, nbytes, reg, mode)
10929668Slinton Address addr;
10939668Slinton int nbytes;
10949668Slinton String reg;
10959668Slinton int mode;
10969668Slinton {
10979668Slinton     char byte;
10989668Slinton     short hword;
10999668Slinton     int argval;
11009668Slinton 
11019668Slinton     switch (nbytes) {
11029668Slinton 	case 1:
11039668Slinton 	    iread(&byte, addr, sizeof(byte));
11049668Slinton 	    argval = byte;
11059668Slinton 	    break;
11069668Slinton 
11079668Slinton 	case 2:
11089668Slinton 	    iread(&hword, addr, sizeof(hword));
11099668Slinton 	    argval = hword;
11109668Slinton 	    break;
11119668Slinton 
11129668Slinton 	case 4:
11139668Slinton 	    iread(&argval, addr, sizeof(argval));
11149668Slinton 	    break;
11159668Slinton     }
11169668Slinton     if (reg == regname[PROGCTR] && mode >= BYTEDISP) {
11179668Slinton 	argval += addr + nbytes;
11189668Slinton     }
11199668Slinton     return argval;
11209668Slinton }
11219668Slinton 
11229668Slinton /*
11239668Slinton  * Enter a procedure by creating and executing a call instruction.
11249668Slinton  */
11259668Slinton 
11269668Slinton #define CALLSIZE 7	/* size of call instruction */
11279668Slinton 
11289668Slinton public beginproc(p, argc)
11299668Slinton Symbol p;
11309668Slinton Integer argc;
11319668Slinton {
11329668Slinton     char save[CALLSIZE];
11339668Slinton     struct {
11349668Slinton 	VaxOpcode op;
11359668Slinton 	unsigned char numargs;
11369668Slinton 	unsigned char mode;
11379668Slinton 	char addr[sizeof(long)];	/* unaligned long */
11389668Slinton     } call;
11399668Slinton     long dest;
11409668Slinton 
11419668Slinton     pc = 2;
11429668Slinton     iread(save, pc, sizeof(save));
11439668Slinton     call.op = O_CALLS;
11449668Slinton     call.numargs = argc;
11459668Slinton     call.mode = 0xef;
11469668Slinton     dest = codeloc(p) - 2 - (pc + 7);
11479668Slinton     mov(&dest, call.addr, sizeof(call.addr));
11489668Slinton     iwrite(&call, pc, sizeof(call));
11499668Slinton     setreg(PROGCTR, pc);
115016612Ssam     pstep(process, DEFSIG);
11519668Slinton     iwrite(save, pc, sizeof(save));
11529668Slinton     pc = reg(PROGCTR);
11539668Slinton     if (not isbperr()) {
11549668Slinton 	printstatus();
11559668Slinton     }
11569668Slinton }
115726336Ssam 
115826336Ssam /*
115926336Ssam  * Special variables for debugging the kernel.
116026336Ssam  */
116126336Ssam 
116226336Ssam public integer masterpcbb;
116326336Ssam public integer slr;
116426336Ssam public struct pte *sbr;
116533340Sdonn private struct pcb pcb;
116626336Ssam 
116726336Ssam public getpcb ()
116826336Ssam {
116933340Sdonn     integer i;
117033340Sdonn 
117133340Sdonn     fseek(corefile, masterpcbb & ~0x80000000, 0);
117226336Ssam     get(corefile, pcb);
117326336Ssam     pcb.pcb_p0lr &= ~AST_CLR;
117426336Ssam     printf("p0br %lx p0lr %lx p1br %lx p1lr %lx\n",
117526336Ssam 	pcb.pcb_p0br, pcb.pcb_p0lr, pcb.pcb_p1br, pcb.pcb_p1lr
117626336Ssam     );
117726336Ssam     setreg(0, pcb.pcb_r0);
117826336Ssam     setreg(1, pcb.pcb_r1);
117926336Ssam     setreg(2, pcb.pcb_r2);
118026336Ssam     setreg(3, pcb.pcb_r3);
118126336Ssam     setreg(4, pcb.pcb_r4);
118226336Ssam     setreg(5, pcb.pcb_r5);
118326336Ssam     setreg(6, pcb.pcb_r6);
118426336Ssam     setreg(7, pcb.pcb_r7);
118526336Ssam     setreg(8, pcb.pcb_r8);
118626336Ssam     setreg(9, pcb.pcb_r9);
118726336Ssam     setreg(10, pcb.pcb_r10);
118826336Ssam     setreg(11, pcb.pcb_r11);
118926336Ssam     setreg(ARGP, pcb.pcb_ap);
119026336Ssam     setreg(FRP, pcb.pcb_fp);
119126336Ssam     setreg(STKP, pcb.pcb_ksp);
119226336Ssam     setreg(PROGCTR, pcb.pcb_pc);
119326336Ssam }
119426336Ssam 
119526336Ssam public copyregs (savreg, reg)
119626336Ssam Word savreg[], reg[];
119726336Ssam {
119826336Ssam     reg[0] = savreg[R0];
119926336Ssam     reg[1] = savreg[R1];
120026336Ssam     reg[2] = savreg[R2];
120126336Ssam     reg[3] = savreg[R3];
120226336Ssam     reg[4] = savreg[R4];
120326336Ssam     reg[5] = savreg[R5];
120426336Ssam     reg[6] = savreg[R6];
120526336Ssam     reg[7] = savreg[R7];
120626336Ssam     reg[8] = savreg[R8];
120726336Ssam     reg[9] = savreg[R9];
120826336Ssam     reg[10] = savreg[R10];
120926336Ssam     reg[11] = savreg[R11];
121026336Ssam     reg[ARGP] = savreg[AP];
121126336Ssam     reg[FRP] = savreg[FP];
121226336Ssam     reg[STKP] = savreg[SP];
121326336Ssam     reg[PROGCTR] = savreg[PC];
121426336Ssam }
121526336Ssam 
121626336Ssam /*
121726336Ssam  * Map a virtual address to a physical address.
121826336Ssam  */
121926336Ssam 
122026336Ssam public Address vmap (addr)
122126336Ssam Address addr;
122226336Ssam {
122326336Ssam     Address r;
122426336Ssam     integer v, n;
122526336Ssam     struct pte pte;
122626336Ssam 
122726336Ssam     r = addr & ~0xc0000000;
122826336Ssam     v = btop(r);
122926336Ssam     switch (addr&0xc0000000) {
123026336Ssam 	case 0xc0000000:
123126336Ssam 	case 0x80000000:
123226336Ssam 	    /*
123326336Ssam 	     * In system space, so get system pte.
123426336Ssam 	     * If it is valid or reclaimable then the physical address
123526336Ssam 	     * is the combination of its page number and the page offset
123626336Ssam 	     * of the original address.
123726336Ssam 	     */
123826336Ssam 	    if (v >= slr) {
123926336Ssam 		error("address %x out of segment", addr);
124026336Ssam 	    }
124126336Ssam 	    r = ((long) (sbr + v)) & ~0x80000000;
124226336Ssam 	    goto simple;
124326336Ssam 
124426336Ssam 	case 0x40000000:
124526336Ssam 	    /*
124626336Ssam 	     * In p1 space, must not be in shadow region.
124726336Ssam 	     */
124826336Ssam 	    if (v < pcb.pcb_p1lr) {
124926336Ssam 		error("address %x out of segment", addr);
125026336Ssam 	    }
125126336Ssam 	    r = (Address) (pcb.pcb_p1br + v);
125226336Ssam 	    break;
125326336Ssam 
125426336Ssam 	case 0x00000000:
125526336Ssam 	    /*
125626336Ssam 	     * In p0 space, must not be off end of region.
125726336Ssam 	     */
125826336Ssam 	    if (v >= pcb.pcb_p0lr) {
125926336Ssam 		error("address %x out of segment", addr);
126026336Ssam 	    }
126126336Ssam 	    r = (Address) (pcb.pcb_p0br + v);
126226336Ssam 	    break;
126326336Ssam 
126426336Ssam 	default:
126526336Ssam 	    /* do nothing */
126626336Ssam 	    break;
126726336Ssam     }
126826336Ssam     /*
126926336Ssam      * For p0/p1 address, user-level page table should be in
127026336Ssam      * kernel virtual memory.  Do second-level indirect by recursing.
127126336Ssam      */
127226336Ssam     if ((r & 0x80000000) == 0) {
127326336Ssam 	error("bad p0br or p1br in pcb");
127426336Ssam     }
127526336Ssam     r = vmap(r);
127626336Ssam simple:
127726336Ssam     /*
127826336Ssam      * "r" is now the address of the pte of the page
127926336Ssam      * we are interested in; get the pte and paste up the physical address.
128026336Ssam      */
128126336Ssam     fseek(corefile, r, 0);
128226336Ssam     n = fread(&pte, sizeof(pte), 1, corefile);
128326336Ssam     if (n != 1) {
128426336Ssam 	error("page table botch (fread at %x returns %d)", r, n);
128526336Ssam     }
128626336Ssam     if (pte.pg_v == 0 and (pte.pg_fod != 0 or pte.pg_pfnum == 0)) {
128726336Ssam 	error("page no valid or reclamable");
128826336Ssam     }
128926336Ssam     return (addr&PGOFSET) + ((Address) ptob(pte.pg_pfnum));
129026336Ssam }
129133340Sdonn 
129233340Sdonn /*
129333340Sdonn  * Extract a bit field from an integer.
129433340Sdonn  */
129533340Sdonn 
129633340Sdonn public integer extractField (s)
129733340Sdonn Symbol s;
129833340Sdonn {
129933340Sdonn     integer n, nbytes, r;
130033340Sdonn 
130133340Sdonn     n = 0;
130233340Sdonn     nbytes = size(s);
130333340Sdonn     if (nbytes > sizeof(n)) {
130433340Sdonn 	printf("[bad size in extractField -- word assumed]\n");
130533340Sdonn 	nbytes = sizeof(n);
130633340Sdonn     }
130733340Sdonn     popn(nbytes, &n);
130833340Sdonn     r = n >> (s->symvalue.field.offset mod BITSPERBYTE);
130933340Sdonn     r &= ((1 << s->symvalue.field.length) - 1);
131033340Sdonn     return r;
131133340Sdonn }
131233340Sdonn 
131333340Sdonn /*
131433340Sdonn  * Change the length of a value in memory according to a given difference
131533340Sdonn  * in the lengths of its new and old types.
131633340Sdonn  */
131733340Sdonn 
131833340Sdonn public loophole (oldlen, newlen)
131933340Sdonn integer oldlen, newlen;
132033340Sdonn {
132133340Sdonn     integer n, i;
132233340Sdonn 
132333340Sdonn     n = newlen - oldlen;
132433340Sdonn     if (n > 0) {
132533340Sdonn 	for (i = 0; i < n; i++) {
132633340Sdonn 	    sp[i] = '\0';
132733340Sdonn 	}
132833340Sdonn     }
132933340Sdonn     sp += n;
133033340Sdonn }
1331