xref: /csrg-svn/old/dbx/vax.c (revision 42688)
121608Sdist /*
238105Sbostic  * Copyright (c) 1983 The Regents of the University of California.
338105Sbostic  * All rights reserved.
438105Sbostic  *
5*42688Sbostic  * %sccs.include.redist.c%
621608Sdist  */
79668Slinton 
821608Sdist #ifndef lint
9*42688Sbostic static char sccsid[] = "@(#)vax.c	5.8 (Berkeley) 06/01/90";
1038105Sbostic #endif /* not lint */
119668Slinton 
129668Slinton /*
139668Slinton  * Target machine dependent stuff.
149668Slinton  */
159668Slinton 
169668Slinton #include "defs.h"
179668Slinton #include "machine.h"
189668Slinton #include "process.h"
1916612Ssam #include "runtime.h"
209668Slinton #include "events.h"
219668Slinton #include "main.h"
229668Slinton #include "symbols.h"
239668Slinton #include "source.h"
249668Slinton #include "mappings.h"
259668Slinton #include "object.h"
2633340Sdonn #include "tree.h"
2733340Sdonn #include "eval.h"
2818222Slinton #include "keywords.h"
299693Slinton #include "ops.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 
4333340Sdonn #define CODESTART 0
4433340Sdonn #define FUNCOFFSET 2
4533340Sdonn 
4633340Sdonn #define nargspassed(frame) argn(0, frame)
4733340Sdonn 
489668Slinton #define BITSPERBYTE 8
499668Slinton #define BITSPERWORD (BITSPERBYTE * sizeof(Word))
509668Slinton 
5126336Ssam /*
5233340Sdonn  * This magic macro enables us to look at the process' registers
5333340Sdonn  * in its user structure.
5426336Ssam  */
559668Slinton 
5633340Sdonn #define regloc(reg)	(ctob(UPAGES) + (sizeof(Word) * (reg)))
5726336Ssam 
589668Slinton #include "source.h"
599668Slinton #include "symbols.h"
6033340Sdonn #include <signal.h>
6126344Ssam #include <sys/param.h>
6226344Ssam #include <machine/psl.h>
6326344Ssam #include <machine/pte.h>
6426344Ssam #include <sys/user.h>
6533340Sdonn #undef DELETE /* XXX */
6626344Ssam #include <sys/vm.h>
6726344Ssam #include <machine/reg.h>
689668Slinton 
699668Slinton Address pc;
709668Slinton Address prtaddr;
719668Slinton 
729668Slinton #endif
739668Slinton 
7433340Sdonn /*
7533340Sdonn  * Indices into u. for use in collecting registers values.
7633340Sdonn  */
7733340Sdonn public int rloc[] ={
7833340Sdonn     R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, AP, FP, SP, PC
7933340Sdonn };
8033340Sdonn 
819668Slinton private Address printop();
829668Slinton 
8333340Sdonn private Optab *ioptab[256];	/* index by opcode to optab */
8436169Sdonn private Optab *esctab[256];	/* for extended opcodes */
8533340Sdonn 
869668Slinton /*
8733340Sdonn  * Initialize the opcode lookup table.
8826344Ssam  */
optab_init()8933340Sdonn public optab_init()
9033340Sdonn {
9136169Sdonn     register Optab *p;
9226344Ssam 
9336169Sdonn     for (p = optab; p->iname; p++) {
9436169Sdonn 	if (p->format == O_ESCD) {
9536169Sdonn 	    esctab[p->val] = p;
9636169Sdonn 	} else if (p->format != O_ESCD && p->format != O_ESCE) {
9736169Sdonn 	    ioptab[p->val] = p;
9836169Sdonn 	}
9936169Sdonn     }
10033340Sdonn }
10133340Sdonn 
10226344Ssam /*
1039668Slinton  * Decode and print the instructions within the given address range.
1049668Slinton  */
1059668Slinton 
printinst(lowaddr,highaddr)1069668Slinton public printinst(lowaddr, highaddr)
1079668Slinton Address lowaddr;
1089668Slinton Address highaddr;
1099668Slinton {
1109668Slinton     register Address addr;
1119668Slinton 
1129668Slinton     for (addr = lowaddr; addr <= highaddr; ) {
1139668Slinton 	addr = printop(addr);
1149668Slinton     }
1159668Slinton     prtaddr = addr;
1169668Slinton }
1179668Slinton 
1189668Slinton /*
1199668Slinton  * Another approach:  print n instructions starting at the given address.
1209668Slinton  */
1219668Slinton 
printninst(count,addr)1229668Slinton public printninst(count, addr)
1239668Slinton int count;
1249668Slinton Address addr;
1259668Slinton {
1269668Slinton     register Integer i;
1279668Slinton     register Address newaddr;
1289668Slinton 
1299668Slinton     if (count <= 0) {
1309668Slinton 	error("non-positive repetition count");
1319668Slinton     } else {
1329668Slinton 	newaddr = addr;
1339668Slinton 	for (i = 0; i < count; i++) {
1349668Slinton 	    newaddr = printop(newaddr);
1359668Slinton 	}
1369668Slinton 	prtaddr = newaddr;
1379668Slinton     }
1389668Slinton }
1399668Slinton 
1409668Slinton /*
1419668Slinton  * Print the contents of the addresses within the given range
1429668Slinton  * according to the given format.
1439668Slinton  */
1449668Slinton 
1459668Slinton typedef struct {
1469668Slinton     String name;
1479668Slinton     String printfstring;
1489668Slinton     int length;
1499668Slinton } Format;
1509668Slinton 
1519668Slinton private Format fmt[] = {
1529668Slinton     { "d", " %d", sizeof(short) },
1539668Slinton     { "D", " %ld", sizeof(long) },
1549668Slinton     { "o", " %o", sizeof(short) },
1559668Slinton     { "O", " %lo", sizeof(long) },
1569668Slinton     { "x", " %04x", sizeof(short) },
1579668Slinton     { "X", " %08x", sizeof(long) },
1589668Slinton     { "b", " \\%o", sizeof(char) },
1599668Slinton     { "c", " '%c'", sizeof(char) },
1609668Slinton     { "s", "%c", sizeof(char) },
16114338Slinton     { "f", " %f", sizeof(float) },
1629668Slinton     { "g", " %g", sizeof(double) },
1639668Slinton     { nil, nil, 0 }
1649668Slinton };
1659668Slinton 
findformat(s)16611174Slinton private Format *findformat(s)
16711174Slinton String s;
16811174Slinton {
16911174Slinton     register Format *f;
17011174Slinton 
17111174Slinton     f = &fmt[0];
17211174Slinton     while (f->name != nil and not streq(f->name, s)) {
17311174Slinton 	++f;
17411174Slinton     }
17511174Slinton     if (f->name == nil) {
17611174Slinton 	error("bad print format \"%s\"", s);
17711174Slinton     }
17811174Slinton     return f;
17911174Slinton }
18011174Slinton 
18133340Sdonn /*
18233340Sdonn  * Retrieve and print out the appropriate data in the given format.
18333340Sdonn  * Floats have to be handled specially to allow the compiler to
18433340Sdonn  * convert them to doubles when passing to printf.
18533340Sdonn  */
18633340Sdonn 
printformat(f,addr)18733340Sdonn private printformat (f, addr)
18833340Sdonn Format *f;
18933340Sdonn Address addr;
19033340Sdonn {
19133340Sdonn     union {
19233340Sdonn 	char charv;
19333340Sdonn 	short shortv;
19433340Sdonn 	int intv;
19533340Sdonn 	float floatv;
19633340Sdonn 	double doublev;
19733340Sdonn     } value;
19833340Sdonn 
19933340Sdonn     value.intv = 0;
20033340Sdonn     dread(&value, addr, f->length);
20133340Sdonn     if (streq(f->name, "f")) {
20233340Sdonn 	printf(f->printfstring, value.floatv);
20333340Sdonn     } else {
20433340Sdonn 	printf(f->printfstring, value);
20533340Sdonn     }
20633340Sdonn }
20733340Sdonn 
printdata(lowaddr,highaddr,format)2089668Slinton public Address printdata(lowaddr, highaddr, format)
2099668Slinton Address lowaddr;
2109668Slinton Address highaddr;
2119668Slinton String format;
2129668Slinton {
21333340Sdonn     int n;
2149668Slinton     register Address addr;
21533340Sdonn     Format *f;
2169668Slinton 
2179668Slinton     if (lowaddr > highaddr) {
2189668Slinton 	error("first address larger than second");
2199668Slinton     }
22011174Slinton     f = findformat(format);
2219668Slinton     n = 0;
2229668Slinton     for (addr = lowaddr; addr <= highaddr; addr += f->length) {
2239668Slinton 	if (n == 0) {
2249668Slinton 	    printf("%08x: ", addr);
2259668Slinton 	}
22633340Sdonn 	printformat(f, addr);
2279668Slinton 	++n;
2289668Slinton 	if (n >= (16 div f->length)) {
22933340Sdonn 	    printf("\n");
2309668Slinton 	    n = 0;
2319668Slinton 	}
2329668Slinton     }
2339668Slinton     if (n != 0) {
23433340Sdonn 	printf("\n");
2359668Slinton     }
2369668Slinton     prtaddr = addr;
2379668Slinton     return addr;
2389668Slinton }
2399668Slinton 
2409668Slinton /*
2419668Slinton  * The other approach is to print n items starting with a given address.
2429668Slinton  */
2439668Slinton 
printndata(count,startaddr,format)2449668Slinton public printndata(count, startaddr, format)
2459668Slinton int count;
2469668Slinton Address startaddr;
2479668Slinton String format;
2489668Slinton {
24933340Sdonn     int i, n;
25033340Sdonn     Address addr;
25133340Sdonn     Format *f;
25233340Sdonn     Boolean isstring;
25314338Slinton     char c;
2549668Slinton 
2559668Slinton     if (count <= 0) {
2569668Slinton 	error("non-positive repetition count");
2579668Slinton     }
25811174Slinton     f = findformat(format);
2599668Slinton     isstring = (Boolean) streq(f->name, "s");
2609668Slinton     n = 0;
2619668Slinton     addr = startaddr;
2629668Slinton     for (i = 0; i < count; i++) {
2639668Slinton 	if (n == 0) {
2649668Slinton 	    printf("%08x: ", addr);
2659668Slinton 	}
2669668Slinton 	if (isstring) {
26733340Sdonn 	    printf("\"");
26814338Slinton 	    dread(&c, addr, sizeof(char));
26914338Slinton 	    while (c != '\0') {
27014338Slinton 		printchar(c);
2719668Slinton 		++addr;
27214338Slinton 		dread(&c, addr, sizeof(char));
2739668Slinton 	    }
27433340Sdonn 	    printf("\"\n");
2759668Slinton 	    n = 0;
2769668Slinton 	    addr += sizeof(String);
2779668Slinton 	} else {
27833340Sdonn 	    printformat(f, addr);
2799668Slinton 	    ++n;
2809668Slinton 	    if (n >= (16 div f->length)) {
28133340Sdonn 		printf("\n");
2829668Slinton 		n = 0;
2839668Slinton 	    }
2849668Slinton 	    addr += f->length;
2859668Slinton 	}
2869668Slinton     }
2879668Slinton     if (n != 0) {
28833340Sdonn 	printf("\n");
2899668Slinton     }
2909668Slinton     prtaddr = addr;
2919668Slinton }
2929668Slinton 
2939668Slinton /*
29411174Slinton  * Print out a value according to the given format.
29511174Slinton  */
29611174Slinton 
printvalue(v,format)29711174Slinton public printvalue(v, format)
29811174Slinton long v;
29911174Slinton String format;
30011174Slinton {
30111174Slinton     Format *f;
30211174Slinton     char *p, *q;
30311174Slinton 
30411174Slinton     f = findformat(format);
30511174Slinton     if (streq(f->name, "s")) {
30611174Slinton 	putchar('"');
30711174Slinton 	p = (char *) &v;
30811174Slinton 	q = p + sizeof(v);
30911174Slinton 	while (p < q) {
31011174Slinton 	    printchar(*p);
31111174Slinton 	    ++p;
31211174Slinton 	}
31311174Slinton 	putchar('"');
31411174Slinton     } else {
31511174Slinton 	printf(f->printfstring, v);
31611174Slinton     }
31711174Slinton     putchar('\n');
31811174Slinton }
31911174Slinton 
32011174Slinton /*
3219668Slinton  * Print out an execution time error.
3229842Slinton  * Assumes the source position of the error has been calculated.
3239668Slinton  *
3249668Slinton  * Have to check if the -r option was specified; if so then
3259668Slinton  * the object file information hasn't been read in yet.
3269668Slinton  */
3279668Slinton 
printerror()3289668Slinton public printerror()
3299668Slinton {
3309668Slinton     extern Integer sys_nsig;
3319668Slinton     extern String sys_siglist[];
33218222Slinton     integer err;
3339668Slinton 
3349668Slinton     if (isfinished(process)) {
33516932Ssam 	err = exitcode(process);
33618222Slinton 	if (err == 0) {
33718222Slinton 	    printf("\"%s\" terminated normally\n", objname);
33818222Slinton 	} else {
33918222Slinton 	    printf("\"%s\" terminated abnormally (exit code %d)\n",
34018222Slinton 		objname, err
34118222Slinton 	    );
34218222Slinton 	}
3439668Slinton 	erecover();
3449668Slinton     }
3459668Slinton     err = errnum(process);
3469668Slinton     putchar('\n');
34716932Ssam     printsig(err);
34818222Slinton     putchar(' ');
34916932Ssam     printloc();
35016932Ssam     putchar('\n');
3519668Slinton     if (curline > 0) {
3529668Slinton 	printlines(curline, curline);
3539668Slinton     } else {
3549668Slinton 	printinst(pc, pc);
3559668Slinton     }
3569668Slinton     erecover();
3579668Slinton }
3589668Slinton 
35918222Slinton /*
36018222Slinton  * Print out a signal.
36118222Slinton  */
36218222Slinton 
36316932Ssam private String illinames[] = {
36418222Slinton     "reserved addressing fault",
36533340Sdonn     "privileged instruction fault",
36618222Slinton     "reserved operand fault"
36716932Ssam };
36818222Slinton 
36916932Ssam private String fpenames[] = {
37018222Slinton     nil,
37118222Slinton     "integer overflow trap",
37218222Slinton     "integer divide by zero trap",
37318222Slinton     "floating overflow trap",
37418222Slinton     "floating/decimal divide by zero trap",
37518222Slinton     "floating underflow trap",
37618222Slinton     "decimal overflow trap",
37718222Slinton     "subscript out of range trap",
37818222Slinton     "floating overflow fault",
37918222Slinton     "floating divide by zero fault",
38033340Sdonn     "floating underflow fault"
38116932Ssam };
38216932Ssam 
printsig(signo)38318222Slinton public printsig (signo)
38418222Slinton integer signo;
38516932Ssam {
38618222Slinton     integer code;
38716932Ssam 
38818222Slinton     if (signo < 0 or signo > sys_nsig) {
38918222Slinton 	printf("[signal %d]", signo);
39018222Slinton     } else {
39118222Slinton 	printf("%s", sys_siglist[signo]);
39216932Ssam     }
39318222Slinton     code = errcode(process);
39418222Slinton     if (signo == SIGILL) {
39518222Slinton 	if (code >= 0 and code < sizeof(illinames) / sizeof(illinames[0])) {
39618222Slinton 	    printf(" (%s)", illinames[code]);
39718222Slinton 	}
39818222Slinton     } else if (signo == SIGFPE) {
39918222Slinton 	if (code > 0 and code < sizeof(fpenames) / sizeof(fpenames[0])) {
40018222Slinton 	    printf(" (%s)", fpenames[code]);
40118222Slinton 	}
40218222Slinton     }
40316932Ssam }
40416932Ssam 
4059668Slinton /*
4069668Slinton  * Note the termination of the program.  We do this so as to avoid
4079668Slinton  * having the process exit, which would make the values of variables
4089668Slinton  * inaccessible.  We do want to flush all output buffers here,
4099668Slinton  * otherwise it'll never get done.
4109668Slinton  */
4119668Slinton 
endprogram()4129668Slinton public endprogram()
4139668Slinton {
4149668Slinton     Integer exitcode;
4159668Slinton 
4169668Slinton     stepto(nextaddr(pc, true));
4179668Slinton     printnews();
4189668Slinton     exitcode = argn(1, nil);
41918222Slinton     if (exitcode != 0) {
42018222Slinton 	printf("\nexecution completed (exit code %d)\n", exitcode);
42118222Slinton     } else {
42218222Slinton 	printf("\nexecution completed\n");
42318222Slinton     }
4249668Slinton     getsrcpos();
4259668Slinton     erecover();
4269668Slinton }
4279668Slinton 
4289668Slinton /*
4299668Slinton  * Single step the machine a source line (or instruction if "inst_tracing"
43010621Slinton  * is true).  If "isnext" is true, skip over procedure calls.
4319668Slinton  */
4329668Slinton 
4339668Slinton private Address getcall();
4349668Slinton 
dostep(isnext)4359668Slinton public dostep(isnext)
4369668Slinton Boolean isnext;
4379668Slinton {
4389668Slinton     register Address addr;
4399668Slinton     register Lineno line;
4409668Slinton     String filename;
44118222Slinton     Address startaddr;
4429668Slinton 
44316612Ssam     startaddr = pc;
4449668Slinton     addr = nextaddr(pc, isnext);
44510621Slinton     if (not inst_tracing and nlhdr.nlines != 0) {
4469668Slinton 	line = linelookup(addr);
4479668Slinton 	while (line == 0) {
44818222Slinton 	    addr = nextaddr(addr, isnext);
4499668Slinton 	    line = linelookup(addr);
4509668Slinton 	}
45110621Slinton 	curline = line;
45210621Slinton     } else {
45310621Slinton 	curline = 0;
4549668Slinton     }
4559668Slinton     stepto(addr);
4569668Slinton     filename = srcfilename(addr);
4579668Slinton     setsource(filename);
4589668Slinton }
4599668Slinton 
46033340Sdonn typedef char Bpinst;
46133340Sdonn 
46233340Sdonn #define BP_OP       O_BPT       /* breakpoint trap */
46333340Sdonn 
46433340Sdonn #define BP_ERRNO    SIGTRAP     /* signal received at a breakpoint */
46533340Sdonn 
4669668Slinton /*
46733340Sdonn  * Setting a breakpoint at a location consists of saving
46833340Sdonn  * the word at the location and poking a BP_OP there.
46933340Sdonn  *
47033340Sdonn  * We save the locations and words on a list for use in unsetting.
47133340Sdonn  */
47233340Sdonn 
47333340Sdonn typedef struct Savelist *Savelist;
47433340Sdonn 
47533340Sdonn struct Savelist {
47633340Sdonn     Address location;
47733340Sdonn     Bpinst save;
47833340Sdonn     short refcount;
47933340Sdonn     Savelist link;
48033340Sdonn };
48133340Sdonn 
48233340Sdonn private Savelist savelist;
48333340Sdonn 
48433340Sdonn /*
48533340Sdonn  * Set a breakpoint at the given address.  Only save the word there
48633340Sdonn  * if it's not already a breakpoint.
48733340Sdonn  */
48833340Sdonn 
setbp(addr)48933340Sdonn public setbp(addr)
49033340Sdonn Address addr;
49133340Sdonn {
49233340Sdonn     Bpinst w, save;
49333340Sdonn     register Savelist newsave, s;
49433340Sdonn 
49533340Sdonn     for (s = savelist; s != nil; s = s->link) {
49633340Sdonn 	if (s->location == addr) {
49733340Sdonn 	    s->refcount++;
49833340Sdonn 	    return;
49933340Sdonn 	}
50033340Sdonn     }
50133340Sdonn     iread(&save, addr, sizeof(save));
50233340Sdonn     newsave = new(Savelist);
50333340Sdonn     newsave->location = addr;
50433340Sdonn     newsave->save = save;
50533340Sdonn     newsave->refcount = 1;
50633340Sdonn     newsave->link = savelist;
50733340Sdonn     savelist = newsave;
50833340Sdonn     w = BP_OP;
50933340Sdonn     iwrite(&w, addr, sizeof(w));
51033340Sdonn }
51133340Sdonn 
51233340Sdonn /*
51333340Sdonn  * Unset a breakpoint; unfortunately we have to search the SAVELIST
51433340Sdonn  * to find the saved value.  The assumption is that the SAVELIST will
51533340Sdonn  * usually be quite small.
51633340Sdonn  */
51733340Sdonn 
unsetbp(addr)51833340Sdonn public unsetbp(addr)
51933340Sdonn Address addr;
52033340Sdonn {
52133340Sdonn     register Savelist s, prev;
52233340Sdonn 
52333340Sdonn     prev = nil;
52433340Sdonn     for (s = savelist; s != nil; s = s->link) {
52533340Sdonn 	if (s->location == addr) {
52633340Sdonn 	    iwrite(&s->save, addr, sizeof(s->save));
52733340Sdonn 	    s->refcount--;
52833340Sdonn 	    if (s->refcount == 0) {
52933340Sdonn 		if (prev == nil) {
53033340Sdonn 		    savelist = s->link;
53133340Sdonn 		} else {
53233340Sdonn 		    prev->link = s->link;
53333340Sdonn 		}
53433340Sdonn 		dispose(s);
53533340Sdonn 	    }
53633340Sdonn 	    return;
53733340Sdonn 	}
53833340Sdonn 	prev = s;
53933340Sdonn     }
54033340Sdonn     panic("unsetbp: couldn't find address %d", addr);
54133340Sdonn }
54233340Sdonn 
54333340Sdonn /*
54433340Sdonn  * VAX instruction decoder, derived from adb.
54533340Sdonn  */
54633340Sdonn 
printop(addr)54733340Sdonn private Address printop(addr)
54833340Sdonn Address addr;
54933340Sdonn {
55033340Sdonn     register Optab *op;
55133340Sdonn     VaxOpcode ins;
55233340Sdonn     unsigned char mode;
55333340Sdonn     int argtype, amode, argno, argval;
55433340Sdonn     String reg;
55533340Sdonn     Boolean indexf;
55633340Sdonn     short offset;
55733340Sdonn 
55833340Sdonn     argval = 0;
55933340Sdonn     indexf = false;
56033340Sdonn     printf("%08x  ", addr);
56133340Sdonn     iread(&ins, addr, sizeof(ins));
56233340Sdonn     addr += 1;
56336169Sdonn     if (ins == O_ESCF) {
56436169Sdonn 	iread(&ins, addr, sizeof(ins));
56536169Sdonn 	addr += 1;
56636169Sdonn 	op = ioptab[ins];
56736169Sdonn     } else if (ins == O_ESCD) {
56836169Sdonn 	iread(&ins, addr, sizeof(ins));
56936169Sdonn 	addr += 1;
57036169Sdonn 	op = esctab[ins];
57136169Sdonn     } else {
57236169Sdonn 	op = ioptab[ins];
57336169Sdonn     }
57436169Sdonn     if (op == nil) {
57536169Sdonn 	printf("[unrecognized opcode %#0x]\n", ins);
57636169Sdonn 	return addr;
57736169Sdonn     }
57833340Sdonn     printf("%s", op->iname);
57933340Sdonn     for (argno = 0; argno < op->numargs; argno++) {
58033340Sdonn 	if (indexf == true) {
58133340Sdonn 	    indexf = false;
58233340Sdonn 	} else if (argno == 0) {
58333340Sdonn 	    printf("\t");
58433340Sdonn 	} else {
58533340Sdonn 	    printf(",");
58633340Sdonn 	}
58733340Sdonn 	argtype = op->argtype[argno];
58833340Sdonn 	if (is_branch_disp(argtype)) {
58933340Sdonn 	    mode = 0xAF + (typelen(argtype) << 5);
59033340Sdonn 	} else {
59133340Sdonn 	    iread(&mode, addr, sizeof(mode));
59233340Sdonn 	    addr += 1;
59333340Sdonn 	}
59433340Sdonn 	reg = regname[regnm(mode)];
59533340Sdonn 	amode = addrmode(mode);
59633340Sdonn 	switch (amode) {
59733340Sdonn 	    case LITSHORT:
59833340Sdonn 	    case LITUPTO31:
59933340Sdonn 	    case LITUPTO47:
60033340Sdonn 	    case LITUPTO63:
60136169Sdonn 		if (typelen(argtype) == TYPF || typelen(argtype) == TYPD ||
60236169Sdonn 		    typelen(argtype) == TYPG || typelen(argtype) == TYPH)
60333340Sdonn 		    printf("$%s", fltimm[mode]);
60433340Sdonn 		else
60533340Sdonn 		    printf("$%x", mode);
60633340Sdonn 		argval = mode;
60733340Sdonn 		break;
60833340Sdonn 
60933340Sdonn 	    case INDEX:
61033340Sdonn 		printf("[%s]", reg);
61133340Sdonn 		indexf = true;
61233340Sdonn 		argno--;
61333340Sdonn 		break;
61433340Sdonn 
61533340Sdonn 	    case REG:
61633340Sdonn 		printf("%s", reg);
61733340Sdonn 		break;
61833340Sdonn 
61933340Sdonn 	    case REGDEF:
62033340Sdonn 		printf("(%s)", reg);
62133340Sdonn 		break;
62233340Sdonn 
62333340Sdonn 	    case AUTODEC:
62433340Sdonn 		printf("-(%s)", reg);
62533340Sdonn 		break;
62633340Sdonn 
62733340Sdonn 	    case AUTOINC:
62833340Sdonn 		if (reg != regname[PROGCTR]) {
62933340Sdonn 		    printf("(%s)+", reg);
63033340Sdonn 		} else {
63133340Sdonn 		    printf("$");
63233340Sdonn 		    switch (typelen(argtype)) {
63333340Sdonn 			case TYPB:
63433340Sdonn 			    argval = printdisp(addr, 1, reg, amode);
63533340Sdonn 			    addr += 1;
63633340Sdonn 			    break;
63733340Sdonn 
63833340Sdonn 			case TYPW:
63933340Sdonn 			    argval = printdisp(addr, 2, reg, amode);
64033340Sdonn 			    addr += 2;
64133340Sdonn 			    break;
64233340Sdonn 
64333340Sdonn 			case TYPL:
64433340Sdonn 			    argval = printdisp(addr, 4, reg, amode);
64533340Sdonn 			    addr += 4;
64633340Sdonn 			    break;
64733340Sdonn 
64833340Sdonn 			case TYPF:
64933340Sdonn 			    iread(&argval, addr, sizeof(argval));
65036169Sdonn 			    if ((argval & 0xffff007f) == 0x8000) {
65136169Sdonn 				printf("[reserved operand]");
65236169Sdonn 			    } else {
65336169Sdonn 				printf("%g", *(float *)&argval);
65436169Sdonn 			    }
65533340Sdonn 			    addr += 4;
65633340Sdonn 			    break;
65733340Sdonn 
65833340Sdonn 			case TYPD:
65936169Sdonn 			    /* XXX this bags the low order bits */
66033340Sdonn 			    iread(&argval, addr, sizeof(argval));
66136169Sdonn 			    if ((argval & 0xffff007f) == 0x8000) {
66236169Sdonn 				printf("[reserved operand]");
66336169Sdonn 			    } else {
66436169Sdonn 				printf("%g", *(float *)&argval);
66536169Sdonn 			    }
66636169Sdonn 			    addr += 8;
66736169Sdonn 			    break;
66836169Sdonn 
66936169Sdonn 			case TYPG:
67036169Sdonn 			case TYPQ:
67133340Sdonn 			    iread(&argval, addr+4, sizeof(argval));
67236169Sdonn 			    printf("%08x", argval);
67336169Sdonn 			    iread(&argval, addr, sizeof(argval));
67436169Sdonn 			    printf("%08x", argval);
67533340Sdonn 			    addr += 8;
67633340Sdonn 			    break;
67736169Sdonn 
67836169Sdonn 			case TYPH:
67936169Sdonn 			case TYPO:
68036169Sdonn 			    iread(&argval, addr+12, sizeof(argval));
68136169Sdonn 			    printf("%08x", argval);
68236169Sdonn 			    iread(&argval, addr+8, sizeof(argval));
68336169Sdonn 			    printf("%08x", argval);
68436169Sdonn 			    iread(&argval, addr+4, sizeof(argval));
68536169Sdonn 			    printf("%08x", argval);
68636169Sdonn 			    iread(&argval, addr, sizeof(argval));
68736169Sdonn 			    printf("%08x", argval);
68836169Sdonn 			    addr += 16;
68936169Sdonn 			    break;
69033340Sdonn 		    }
69133340Sdonn 		}
69233340Sdonn 		break;
69333340Sdonn 
69433340Sdonn 	    case AUTOINCDEF:
69533340Sdonn 		if (reg == regname[PROGCTR]) {
69633340Sdonn 		    printf("*$");
69733340Sdonn 		    argval = printdisp(addr, 4, reg, amode);
69833340Sdonn 		    addr += 4;
69933340Sdonn 		} else {
70033340Sdonn 		    printf("*(%s)+", reg);
70133340Sdonn 		}
70233340Sdonn 		break;
70333340Sdonn 
70433340Sdonn 	    case BYTEDISP:
70533340Sdonn 		argval = printdisp(addr, 1, reg, amode);
70633340Sdonn 		addr += 1;
70733340Sdonn 		break;
70833340Sdonn 
70933340Sdonn 	    case BYTEDISPDEF:
71033340Sdonn 		printf("*");
71133340Sdonn 		argval = printdisp(addr, 1, reg, amode);
71233340Sdonn 		addr += 1;
71333340Sdonn 		break;
71433340Sdonn 
71533340Sdonn 	    case WORDDISP:
71633340Sdonn 		argval = printdisp(addr, 2, reg, amode);
71733340Sdonn 		addr += 2;
71833340Sdonn 		break;
71933340Sdonn 
72033340Sdonn 	    case WORDDISPDEF:
72133340Sdonn 		printf("*");
72233340Sdonn 		argval = printdisp(addr, 2, reg, amode);
72333340Sdonn 		addr += 2;
72433340Sdonn 		break;
72533340Sdonn 
72633340Sdonn 	    case LONGDISP:
72733340Sdonn 		argval = printdisp(addr, 4, reg, amode);
72833340Sdonn 		addr += 4;
72933340Sdonn 		break;
73033340Sdonn 
73133340Sdonn 	    case LONGDISPDEF:
73233340Sdonn 		printf("*");
73333340Sdonn 		argval = printdisp(addr, 4, reg, amode);
73433340Sdonn 		addr += 4;
73533340Sdonn 		break;
73633340Sdonn 	}
73733340Sdonn     }
73833340Sdonn     if (ins == O_CASEB || ins == O_CASEW || ins == O_CASEL) {
73933340Sdonn 	for (argno = 0; argno <= argval; argno++) {
74033340Sdonn 	    iread(&offset, addr, sizeof(offset));
74133340Sdonn 	    printf("\n\t\t%d", offset);
74233340Sdonn 	    addr += 2;
74333340Sdonn 	}
74433340Sdonn     }
74533340Sdonn     printf("\n");
74633340Sdonn     return addr;
74733340Sdonn }
74833340Sdonn 
74933340Sdonn /*
75033340Sdonn  * Print the displacement of an instruction that uses displacement
75133340Sdonn  * addressing.
75233340Sdonn  */
75333340Sdonn 
printdisp(addr,nbytes,reg,mode)75433340Sdonn private int printdisp(addr, nbytes, reg, mode)
75533340Sdonn Address addr;
75633340Sdonn int nbytes;
75733340Sdonn char *reg;
75833340Sdonn int mode;
75933340Sdonn {
76033340Sdonn     char byte;
76133340Sdonn     short hword;
76233340Sdonn     int argval;
76333340Sdonn     Symbol f;
76433340Sdonn 
76533340Sdonn     switch (nbytes) {
76633340Sdonn 	case 1:
76733340Sdonn 	    iread(&byte, addr, sizeof(byte));
76833340Sdonn 	    argval = byte;
76933340Sdonn 	    break;
77033340Sdonn 
77133340Sdonn 	case 2:
77233340Sdonn 	    iread(&hword, addr, sizeof(hword));
77333340Sdonn 	    argval = hword;
77433340Sdonn 	    break;
77533340Sdonn 
77633340Sdonn 	case 4:
77733340Sdonn 	    iread(&argval, addr, sizeof(argval));
77833340Sdonn 	    break;
77933340Sdonn     }
78033340Sdonn     if (reg == regname[PROGCTR] && mode >= BYTEDISP) {
78133340Sdonn 	argval += addr + nbytes;
78233340Sdonn     }
78333340Sdonn     if (reg == regname[PROGCTR]) {
78433340Sdonn 	f = whatblock((Address) argval + 2);
78533340Sdonn 	if (codeloc(f) == argval + 2) {
78633340Sdonn 	    printf("%s", symname(f));
78733340Sdonn 	} else {
78833340Sdonn 	    printf("%x", argval);
78933340Sdonn 	}
79033340Sdonn     } else {
79133340Sdonn 	if (varIsSet("$hexoffsets")) {
79233340Sdonn 	    if (argval < 0) {
79333340Sdonn 		printf("-%x(%s)", -(argval), reg);
79433340Sdonn 	    } else {
79533340Sdonn 		printf("%x(%s)", argval, reg);
79633340Sdonn 	    }
79733340Sdonn 	} else {
79833340Sdonn 	    printf("%d(%s)", argval, reg);
79933340Sdonn 	}
80033340Sdonn     }
80133340Sdonn     return argval;
80233340Sdonn }
80333340Sdonn 
80433340Sdonn /*
8059668Slinton  * Compute the next address that will be executed from the given one.
8069668Slinton  * If "isnext" is true then consider a procedure call as straight line code.
8079668Slinton  *
8089668Slinton  * We must unfortunately do much of the same work that is necessary
8099668Slinton  * to print instructions.  In addition we have to deal with branches.
8109668Slinton  * Unconditional branches we just follow, for conditional branches
8119668Slinton  * we continue execution to the current location and then single step
8129668Slinton  * the machine.  We assume that the last argument in an instruction
8139668Slinton  * that branches is the branch address (or relative offset).
8149668Slinton  */
8159668Slinton 
81618222Slinton private Address findnextaddr();
81718222Slinton 
nextaddr(startaddr,isnext)8189668Slinton public Address nextaddr(startaddr, isnext)
8199668Slinton Address startaddr;
82016612Ssam boolean isnext;
82116612Ssam {
82216612Ssam     Address addr;
82316612Ssam 
82416612Ssam     addr = usignal(process);
82516612Ssam     if (addr == 0 or addr == 1) {
82616612Ssam 	addr = findnextaddr(startaddr, isnext);
82716612Ssam     }
82816612Ssam     return addr;
82916612Ssam }
83016612Ssam 
83118222Slinton /*
83218222Slinton  * Determine if it's ok to skip function f entered by instruction ins.
83318222Slinton  * If so, we're going to compute the return address and step to it.
83418222Slinton  * Therefore we cannot skip over a function entered by a jsb or bsb,
83518222Slinton  * since the return address is not easily computed for them.
83618222Slinton  */
83718222Slinton 
skipfunc(ins,f)83818222Slinton private boolean skipfunc (ins, f)
83918222Slinton VaxOpcode ins;
84018222Slinton Symbol f;
84118222Slinton {
84218222Slinton     boolean b;
84318222Slinton 
84418222Slinton     b = (boolean) (
84518222Slinton 	ins != O_JSB and ins != O_BSBB and ins != O_BSBW and
84618222Slinton 	not inst_tracing and nlhdr.nlines != 0 and
84718222Slinton 	nosource(curfunc) and canskip(curfunc)
84818222Slinton     );
84918222Slinton     return b;
85018222Slinton }
85118222Slinton 
findnextaddr(startaddr,isnext)85216612Ssam private Address findnextaddr(startaddr, isnext)
85316612Ssam Address startaddr;
8549668Slinton Boolean isnext;
8559668Slinton {
8569668Slinton     register Address addr;
85733340Sdonn     register Optab *op;
85836169Sdonn     VaxOpcode ins, ins2;
8599668Slinton     unsigned char mode;
8609668Slinton     int argtype, amode, argno, argval;
8619668Slinton     String r;
8629668Slinton     Boolean indexf;
8639668Slinton     enum { KNOWN, SEQUENTIAL, BRANCH } addrstatus;
8649668Slinton 
8659668Slinton     argval = 0;
8669668Slinton     indexf = false;
8679668Slinton     addr = startaddr;
8689668Slinton     iread(&ins, addr, sizeof(ins));
8699668Slinton     switch (ins) {
87018222Slinton 	/*
87118222Slinton 	 * It used to be that unconditional jumps and branches were handled
87218222Slinton 	 * by taking their destination address as the next address.  While
87318222Slinton 	 * saving the cost of starting up the process, this approach
87418222Slinton 	 * doesn't work when jumping indirect (since the value in the
87518222Slinton 	 * register might not yet have been set).
87618222Slinton 	 *
87718222Slinton 	 * So unconditional jumps and branches are now handled the same way
87818222Slinton 	 * as conditional jumps and branches.
87918222Slinton 	 *
8809668Slinton 	case O_BRB:
8819668Slinton 	case O_BRW:
8829668Slinton 	    addrstatus = BRANCH;
8839668Slinton 	    break;
88418222Slinton 	 *
88518222Slinton 	 */
8869668Slinton 
8879668Slinton 	case O_BSBB:
8889668Slinton 	case O_BSBW:
8899668Slinton 	case O_JSB:
8909668Slinton 	case O_CALLG:
8919668Slinton 	case O_CALLS:
89218222Slinton 	    addrstatus = KNOWN;
89318222Slinton 	    stepto(addr);
89418222Slinton 	    pstep(process, DEFSIG);
89518222Slinton 	    addr = reg(PROGCTR);
89618222Slinton 	    pc = addr;
89718222Slinton 	    setcurfunc(whatblock(pc));
89818222Slinton 	    if (not isbperr()) {
89918222Slinton 		printstatus();
90018222Slinton 		/* NOTREACHED */
90118222Slinton 	    }
90218222Slinton 	    bpact();
90318222Slinton 	    if (isnext or skipfunc(ins, curfunc)) {
9049668Slinton 		addrstatus = KNOWN;
90518222Slinton 		addr = return_addr();
9069668Slinton 		stepto(addr);
90711864Slinton 		bpact();
90818222Slinton 	    } else {
90918222Slinton 		callnews(/* iscall = */ true);
9109668Slinton 	    }
9119668Slinton 	    break;
9129668Slinton 
9139668Slinton 	case O_RSB:
9149668Slinton 	case O_RET:
9159668Slinton 	    addrstatus = KNOWN;
91618222Slinton 	    stepto(addr);
9179668Slinton 	    callnews(/* iscall = */ false);
91818222Slinton 	    pstep(process, DEFSIG);
91918222Slinton 	    addr = reg(PROGCTR);
92018222Slinton 	    pc = addr;
92118222Slinton 	    if (not isbperr()) {
92218222Slinton 		printstatus();
92316612Ssam 	    }
92411874Slinton 	    bpact();
9259668Slinton 	    break;
9269668Slinton 
92718222Slinton 	case O_BRB: case O_BRW:
92816612Ssam 	case O_JMP: /* because it may be jmp (r1) */
9299668Slinton 	case O_BNEQ: case O_BEQL: case O_BGTR:
9309668Slinton 	case O_BLEQ: case O_BGEQ: case O_BLSS:
9319668Slinton 	case O_BGTRU: case O_BLEQU: case O_BVC:
9329668Slinton 	case O_BVS: case O_BCC: case O_BCS:
9339668Slinton 	case O_CASEB: case O_CASEW: case O_CASEL:
9349668Slinton 	case O_BBS: case O_BBC: case O_BBSS: case O_BBCS:
9359668Slinton 	case O_BBSC: case O_BBCC: case O_BBSSI:
9369668Slinton 	case O_BBCCI: case O_BLBS: case O_BLBC:
9379668Slinton 	case O_ACBL: case O_AOBLSS: case O_AOBLEQ:
9389668Slinton 	case O_SOBGEQ: case O_SOBGTR:
93936169Sdonn 	case O_ESCF: /* bugchecks */
94036169Sdonn 	branches:
9419668Slinton 	    addrstatus = KNOWN;
9429668Slinton 	    stepto(addr);
94316612Ssam 	    pstep(process, DEFSIG);
9449668Slinton 	    addr = reg(PROGCTR);
9459668Slinton 	    pc = addr;
9469668Slinton 	    if (not isbperr()) {
9479668Slinton 		printstatus();
9489668Slinton 	    }
9499668Slinton 	    break;
9509668Slinton 
95136169Sdonn 	case O_ESCD:
95236169Sdonn 	    iread(&ins2, addr+1, sizeof(ins2));
95336169Sdonn 	    if (ins2 == O_ACBF || ins2 == O_ACBD)
95436169Sdonn 		/* actually ACBG and ACBH */
95536169Sdonn 		goto branches;
95636169Sdonn 	    /* fall through */
95736169Sdonn 
9589668Slinton 	default:
9599668Slinton 	    addrstatus = SEQUENTIAL;
9609668Slinton 	    break;
9619668Slinton     }
9629668Slinton     if (addrstatus != KNOWN) {
9639668Slinton 	addr += 1;
96436169Sdonn 	if (ins == O_ESCD) {
96536169Sdonn 	    ins = ins2;
96636169Sdonn 	    addr += 1;
96736169Sdonn 	    op = esctab[ins];
96836169Sdonn 	    if (op == nil) {
96936169Sdonn 		printf("[bad extended opcode %#x in findnextaddr]\n", ins);
97036169Sdonn 		return addr;
97136169Sdonn 	    }
97236169Sdonn 	} else {
97336169Sdonn 	    op = ioptab[ins];
97436169Sdonn 	    if (op == nil) {
97536169Sdonn 		printf("[bad opcode %#x in findnextaddr]\n", ins);
97636169Sdonn 		return addr;
97736169Sdonn 	    }
97836169Sdonn 	}
97933340Sdonn 	for (argno = 0; argno < op->numargs; argno++) {
9809668Slinton 	    if (indexf == true) {
9819668Slinton 		indexf = false;
9829668Slinton 	    }
98333340Sdonn 	    argtype = op->argtype[argno];
9849668Slinton 	    if (is_branch_disp(argtype)) {
9859668Slinton 		mode = 0xAF + (typelen(argtype) << 5);
9869668Slinton 	    } else {
9879668Slinton 		iread(&mode, addr, sizeof(mode));
9889668Slinton 		addr += 1;
9899668Slinton 	    }
9909668Slinton 	    r = regname[regnm(mode)];
9919668Slinton 	    amode = addrmode(mode);
9929668Slinton 	    switch (amode) {
9939668Slinton 		case LITSHORT:
9949668Slinton 		case LITUPTO31:
9959668Slinton 		case LITUPTO47:
9969668Slinton 		case LITUPTO63:
9979668Slinton 		    argval = mode;
9989668Slinton 		    break;
9999668Slinton 
10009668Slinton 		case INDEX:
10019668Slinton 		    indexf = true;
10029668Slinton 		    --argno;
10039668Slinton 		    break;
10049668Slinton 
10059668Slinton 		case REG:
10069668Slinton 		case REGDEF:
10079668Slinton 		case AUTODEC:
10089668Slinton 		    break;
10099668Slinton 
10109668Slinton 		case AUTOINC:
10119668Slinton 		    if (r == regname[PROGCTR]) {
10129668Slinton 			switch (typelen(argtype)) {
10139668Slinton 			    case TYPB:
10149668Slinton 				argval = getdisp(addr, 1, r, amode);
10159668Slinton 				addr += 1;
10169668Slinton 				break;
10179668Slinton 
10189668Slinton 			    case TYPW:
10199668Slinton 				argval = getdisp(addr, 2, r, amode);
10209668Slinton 				addr += 2;
10219668Slinton 				break;
10229668Slinton 
10239668Slinton 			    case TYPL:
10249668Slinton 				argval = getdisp(addr, 4, r, amode);
10259668Slinton 				addr += 4;
10269668Slinton 				break;
10279668Slinton 
10289668Slinton 			    case TYPF:
10299668Slinton 				iread(&argval, addr, sizeof(argval));
10309668Slinton 				addr += 4;
10319668Slinton 				break;
10329668Slinton 
10339668Slinton 			    case TYPQ:
10349668Slinton 			    case TYPD:
103536169Sdonn 			    case TYPG:
10369668Slinton 				iread(&argval, addr+4, sizeof(argval));
10379668Slinton 				addr += 8;
10389668Slinton 				break;
103936169Sdonn 
104036169Sdonn 			    case TYPO:
104136169Sdonn 			    case TYPH:
104236169Sdonn 				iread(&argval, addr+12, sizeof(argval));
104336169Sdonn 				addr += 16;
104436169Sdonn 				break;
10459668Slinton 			}
10469668Slinton 		    }
10479668Slinton 		    break;
10489668Slinton 
10499668Slinton 		case AUTOINCDEF:
10509668Slinton 		    if (r == regname[PROGCTR]) {
10519668Slinton 			argval = getdisp(addr, 4, r, amode);
10529668Slinton 			addr += 4;
10539668Slinton 		    }
10549668Slinton 		    break;
10559668Slinton 
10569668Slinton 		case BYTEDISP:
10579668Slinton 		case BYTEDISPDEF:
10589668Slinton 		    argval = getdisp(addr, 1, r, amode);
10599668Slinton 		    addr += 1;
10609668Slinton 		    break;
10619668Slinton 
10629668Slinton 		case WORDDISP:
10639668Slinton 		case WORDDISPDEF:
10649668Slinton 		    argval = getdisp(addr, 2, r, amode);
10659668Slinton 		    addr += 2;
10669668Slinton 		    break;
10679668Slinton 
10689668Slinton 		case LONGDISP:
10699668Slinton 		case LONGDISPDEF:
10709668Slinton 		    argval = getdisp(addr, 4, r, amode);
10719668Slinton 		    addr += 4;
10729668Slinton 		    break;
10739668Slinton 	    }
10749668Slinton 	}
10759668Slinton 	if (ins == O_CALLS or ins == O_CALLG) {
10769668Slinton 	    argval += 2;
10779668Slinton 	}
10789668Slinton 	if (addrstatus == BRANCH) {
10799668Slinton 	    addr = argval;
10809668Slinton 	}
10819668Slinton     }
10829668Slinton     return addr;
10839668Slinton }
10849668Slinton 
10859668Slinton /*
10869668Slinton  * Get the displacement of an instruction that uses displacement addressing.
10879668Slinton  */
10889668Slinton 
getdisp(addr,nbytes,reg,mode)10899668Slinton private int getdisp(addr, nbytes, reg, mode)
10909668Slinton Address addr;
10919668Slinton int nbytes;
10929668Slinton String reg;
10939668Slinton int mode;
10949668Slinton {
10959668Slinton     char byte;
10969668Slinton     short hword;
10979668Slinton     int argval;
10989668Slinton 
10999668Slinton     switch (nbytes) {
11009668Slinton 	case 1:
11019668Slinton 	    iread(&byte, addr, sizeof(byte));
11029668Slinton 	    argval = byte;
11039668Slinton 	    break;
11049668Slinton 
11059668Slinton 	case 2:
11069668Slinton 	    iread(&hword, addr, sizeof(hword));
11079668Slinton 	    argval = hword;
11089668Slinton 	    break;
11099668Slinton 
11109668Slinton 	case 4:
11119668Slinton 	    iread(&argval, addr, sizeof(argval));
11129668Slinton 	    break;
11139668Slinton     }
11149668Slinton     if (reg == regname[PROGCTR] && mode >= BYTEDISP) {
11159668Slinton 	argval += addr + nbytes;
11169668Slinton     }
11179668Slinton     return argval;
11189668Slinton }
11199668Slinton 
11209668Slinton /*
11219668Slinton  * Enter a procedure by creating and executing a call instruction.
11229668Slinton  */
11239668Slinton 
11249668Slinton #define CALLSIZE 7	/* size of call instruction */
11259668Slinton 
beginproc(p,argc)11269668Slinton public beginproc(p, argc)
11279668Slinton Symbol p;
11289668Slinton Integer argc;
11299668Slinton {
11309668Slinton     char save[CALLSIZE];
11319668Slinton     struct {
11329668Slinton 	VaxOpcode op;
11339668Slinton 	unsigned char numargs;
11349668Slinton 	unsigned char mode;
11359668Slinton 	char addr[sizeof(long)];	/* unaligned long */
11369668Slinton     } call;
11379668Slinton     long dest;
11389668Slinton 
11399668Slinton     pc = 2;
11409668Slinton     iread(save, pc, sizeof(save));
11419668Slinton     call.op = O_CALLS;
11429668Slinton     call.numargs = argc;
11439668Slinton     call.mode = 0xef;
11449668Slinton     dest = codeloc(p) - 2 - (pc + 7);
11459668Slinton     mov(&dest, call.addr, sizeof(call.addr));
11469668Slinton     iwrite(&call, pc, sizeof(call));
11479668Slinton     setreg(PROGCTR, pc);
114816612Ssam     pstep(process, DEFSIG);
11499668Slinton     iwrite(save, pc, sizeof(save));
11509668Slinton     pc = reg(PROGCTR);
11519668Slinton     if (not isbperr()) {
11529668Slinton 	printstatus();
11539668Slinton     }
11549668Slinton }
115526336Ssam 
115626336Ssam /*
115726336Ssam  * Special variables for debugging the kernel.
115826336Ssam  */
115926336Ssam 
116026336Ssam public integer masterpcbb;
116126336Ssam public integer slr;
116226336Ssam public struct pte *sbr;
116333340Sdonn private struct pcb pcb;
116426336Ssam 
getpcb()116526336Ssam public getpcb ()
116626336Ssam {
116733340Sdonn     integer i;
116833340Sdonn 
116933340Sdonn     fseek(corefile, masterpcbb & ~0x80000000, 0);
117026336Ssam     get(corefile, pcb);
117126336Ssam     pcb.pcb_p0lr &= ~AST_CLR;
117226336Ssam     printf("p0br %lx p0lr %lx p1br %lx p1lr %lx\n",
117326336Ssam 	pcb.pcb_p0br, pcb.pcb_p0lr, pcb.pcb_p1br, pcb.pcb_p1lr
117426336Ssam     );
117526336Ssam     setreg(0, pcb.pcb_r0);
117626336Ssam     setreg(1, pcb.pcb_r1);
117726336Ssam     setreg(2, pcb.pcb_r2);
117826336Ssam     setreg(3, pcb.pcb_r3);
117926336Ssam     setreg(4, pcb.pcb_r4);
118026336Ssam     setreg(5, pcb.pcb_r5);
118126336Ssam     setreg(6, pcb.pcb_r6);
118226336Ssam     setreg(7, pcb.pcb_r7);
118326336Ssam     setreg(8, pcb.pcb_r8);
118426336Ssam     setreg(9, pcb.pcb_r9);
118526336Ssam     setreg(10, pcb.pcb_r10);
118626336Ssam     setreg(11, pcb.pcb_r11);
118726336Ssam     setreg(ARGP, pcb.pcb_ap);
118826336Ssam     setreg(FRP, pcb.pcb_fp);
118926336Ssam     setreg(STKP, pcb.pcb_ksp);
119026336Ssam     setreg(PROGCTR, pcb.pcb_pc);
119126336Ssam }
119226336Ssam 
copyregs(savreg,reg)119326336Ssam public copyregs (savreg, reg)
119426336Ssam Word savreg[], reg[];
119526336Ssam {
119626336Ssam     reg[0] = savreg[R0];
119726336Ssam     reg[1] = savreg[R1];
119826336Ssam     reg[2] = savreg[R2];
119926336Ssam     reg[3] = savreg[R3];
120026336Ssam     reg[4] = savreg[R4];
120126336Ssam     reg[5] = savreg[R5];
120226336Ssam     reg[6] = savreg[R6];
120326336Ssam     reg[7] = savreg[R7];
120426336Ssam     reg[8] = savreg[R8];
120526336Ssam     reg[9] = savreg[R9];
120626336Ssam     reg[10] = savreg[R10];
120726336Ssam     reg[11] = savreg[R11];
120826336Ssam     reg[ARGP] = savreg[AP];
120926336Ssam     reg[FRP] = savreg[FP];
121026336Ssam     reg[STKP] = savreg[SP];
121126336Ssam     reg[PROGCTR] = savreg[PC];
121226336Ssam }
121326336Ssam 
121426336Ssam /*
121526336Ssam  * Map a virtual address to a physical address.
121626336Ssam  */
121726336Ssam 
vmap(addr)121826336Ssam public Address vmap (addr)
121926336Ssam Address addr;
122026336Ssam {
122126336Ssam     Address r;
122226336Ssam     integer v, n;
122326336Ssam     struct pte pte;
122426336Ssam 
122526336Ssam     r = addr & ~0xc0000000;
122626336Ssam     v = btop(r);
122726336Ssam     switch (addr&0xc0000000) {
122826336Ssam 	case 0xc0000000:
122926336Ssam 	case 0x80000000:
123026336Ssam 	    /*
123126336Ssam 	     * In system space, so get system pte.
123226336Ssam 	     * If it is valid or reclaimable then the physical address
123326336Ssam 	     * is the combination of its page number and the page offset
123426336Ssam 	     * of the original address.
123526336Ssam 	     */
123626336Ssam 	    if (v >= slr) {
123726336Ssam 		error("address %x out of segment", addr);
123826336Ssam 	    }
123926336Ssam 	    r = ((long) (sbr + v)) & ~0x80000000;
124026336Ssam 	    goto simple;
124126336Ssam 
124226336Ssam 	case 0x40000000:
124326336Ssam 	    /*
124426336Ssam 	     * In p1 space, must not be in shadow region.
124526336Ssam 	     */
124626336Ssam 	    if (v < pcb.pcb_p1lr) {
124726336Ssam 		error("address %x out of segment", addr);
124826336Ssam 	    }
124926336Ssam 	    r = (Address) (pcb.pcb_p1br + v);
125026336Ssam 	    break;
125126336Ssam 
125226336Ssam 	case 0x00000000:
125326336Ssam 	    /*
125426336Ssam 	     * In p0 space, must not be off end of region.
125526336Ssam 	     */
125626336Ssam 	    if (v >= pcb.pcb_p0lr) {
125726336Ssam 		error("address %x out of segment", addr);
125826336Ssam 	    }
125926336Ssam 	    r = (Address) (pcb.pcb_p0br + v);
126026336Ssam 	    break;
126126336Ssam 
126226336Ssam 	default:
126326336Ssam 	    /* do nothing */
126426336Ssam 	    break;
126526336Ssam     }
126626336Ssam     /*
126726336Ssam      * For p0/p1 address, user-level page table should be in
126826336Ssam      * kernel virtual memory.  Do second-level indirect by recursing.
126926336Ssam      */
127026336Ssam     if ((r & 0x80000000) == 0) {
127126336Ssam 	error("bad p0br or p1br in pcb");
127226336Ssam     }
127326336Ssam     r = vmap(r);
127426336Ssam simple:
127526336Ssam     /*
127626336Ssam      * "r" is now the address of the pte of the page
127726336Ssam      * we are interested in; get the pte and paste up the physical address.
127826336Ssam      */
127926336Ssam     fseek(corefile, r, 0);
128026336Ssam     n = fread(&pte, sizeof(pte), 1, corefile);
128126336Ssam     if (n != 1) {
128226336Ssam 	error("page table botch (fread at %x returns %d)", r, n);
128326336Ssam     }
128426336Ssam     if (pte.pg_v == 0 and (pte.pg_fod != 0 or pte.pg_pfnum == 0)) {
128526336Ssam 	error("page no valid or reclamable");
128626336Ssam     }
128726336Ssam     return (addr&PGOFSET) + ((Address) ptob(pte.pg_pfnum));
128826336Ssam }
128933340Sdonn 
129033340Sdonn /*
129133340Sdonn  * Extract a bit field from an integer.
129233340Sdonn  */
129333340Sdonn 
extractField(s)129433340Sdonn public integer extractField (s)
129533340Sdonn Symbol s;
129633340Sdonn {
129733340Sdonn     integer n, nbytes, r;
129833340Sdonn 
129933340Sdonn     n = 0;
130033340Sdonn     nbytes = size(s);
130133340Sdonn     if (nbytes > sizeof(n)) {
130233340Sdonn 	printf("[bad size in extractField -- word assumed]\n");
130333340Sdonn 	nbytes = sizeof(n);
130433340Sdonn     }
130533340Sdonn     popn(nbytes, &n);
130633340Sdonn     r = n >> (s->symvalue.field.offset mod BITSPERBYTE);
130733340Sdonn     r &= ((1 << s->symvalue.field.length) - 1);
130833340Sdonn     return r;
130933340Sdonn }
131033340Sdonn 
131133340Sdonn /*
131233340Sdonn  * Change the length of a value in memory according to a given difference
131333340Sdonn  * in the lengths of its new and old types.
131433340Sdonn  */
131533340Sdonn 
loophole(oldlen,newlen)131633340Sdonn public loophole (oldlen, newlen)
131733340Sdonn integer oldlen, newlen;
131833340Sdonn {
131933340Sdonn     integer n, i;
132033340Sdonn 
132133340Sdonn     n = newlen - oldlen;
132233340Sdonn     if (n > 0) {
132333340Sdonn 	for (i = 0; i < n; i++) {
132433340Sdonn 	    sp[i] = '\0';
132533340Sdonn 	}
132633340Sdonn     }
132733340Sdonn     sp += n;
132833340Sdonn }
1329