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