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