121608Sdist /* 2*38105Sbostic * Copyright (c) 1983 The Regents of the University of California. 3*38105Sbostic * All rights reserved. 4*38105Sbostic * 5*38105Sbostic * Redistribution and use in source and binary forms are permitted 6*38105Sbostic * provided that the above copyright notice and this paragraph are 7*38105Sbostic * duplicated in all such forms and that any documentation, 8*38105Sbostic * advertising materials, and other materials related to such 9*38105Sbostic * distribution and use acknowledge that the software was developed 10*38105Sbostic * by the University of California, Berkeley. The name of the 11*38105Sbostic * University may not be used to endorse or promote products derived 12*38105Sbostic * from this software without specific prior written permission. 13*38105Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14*38105Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15*38105Sbostic * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1621608Sdist */ 179668Slinton 1821608Sdist #ifndef lint 19*38105Sbostic static char sccsid[] = "@(#)vax.c 5.6 (Berkeley) 05/23/89"; 20*38105Sbostic #endif /* not lint */ 219668Slinton 229668Slinton /* 239668Slinton * Target machine dependent stuff. 249668Slinton */ 259668Slinton 269668Slinton #include "defs.h" 279668Slinton #include "machine.h" 289668Slinton #include "process.h" 2916612Ssam #include "runtime.h" 309668Slinton #include "events.h" 319668Slinton #include "main.h" 329668Slinton #include "symbols.h" 339668Slinton #include "source.h" 349668Slinton #include "mappings.h" 359668Slinton #include "object.h" 3633340Sdonn #include "tree.h" 3733340Sdonn #include "eval.h" 3818222Slinton #include "keywords.h" 399693Slinton #include "ops.h" 409668Slinton 419668Slinton #ifndef public 429668Slinton typedef unsigned int Address; 439668Slinton typedef unsigned char Byte; 449668Slinton typedef unsigned int Word; 459668Slinton 469668Slinton #define NREG 16 479668Slinton 489668Slinton #define ARGP 12 499668Slinton #define FRP 13 509668Slinton #define STKP 14 519668Slinton #define PROGCTR 15 529668Slinton 5333340Sdonn #define CODESTART 0 5433340Sdonn #define FUNCOFFSET 2 5533340Sdonn 5633340Sdonn #define nargspassed(frame) argn(0, frame) 5733340Sdonn 589668Slinton #define BITSPERBYTE 8 599668Slinton #define BITSPERWORD (BITSPERBYTE * sizeof(Word)) 609668Slinton 6126336Ssam /* 6233340Sdonn * This magic macro enables us to look at the process' registers 6333340Sdonn * in its user structure. 6426336Ssam */ 659668Slinton 6633340Sdonn #define regloc(reg) (ctob(UPAGES) + (sizeof(Word) * (reg))) 6726336Ssam 689668Slinton #include "source.h" 699668Slinton #include "symbols.h" 7033340Sdonn #include <signal.h> 7126344Ssam #include <sys/param.h> 7226344Ssam #include <sys/dir.h> 7326344Ssam #include <machine/psl.h> 7426344Ssam #include <machine/pte.h> 7526344Ssam #include <sys/user.h> 7633340Sdonn #undef DELETE /* XXX */ 7726344Ssam #include <sys/vm.h> 7826344Ssam #include <machine/reg.h> 799668Slinton 809668Slinton Address pc; 819668Slinton Address prtaddr; 829668Slinton 839668Slinton #endif 849668Slinton 8533340Sdonn /* 8633340Sdonn * Indices into u. for use in collecting registers values. 8733340Sdonn */ 8833340Sdonn public int rloc[] ={ 8933340Sdonn R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, AP, FP, SP, PC 9033340Sdonn }; 9133340Sdonn 929668Slinton private Address printop(); 939668Slinton 9433340Sdonn private Optab *ioptab[256]; /* index by opcode to optab */ 9536169Sdonn private Optab *esctab[256]; /* for extended opcodes */ 9633340Sdonn 979668Slinton /* 9833340Sdonn * Initialize the opcode lookup table. 9926344Ssam */ 10033340Sdonn public optab_init() 10133340Sdonn { 10236169Sdonn register Optab *p; 10326344Ssam 10436169Sdonn for (p = optab; p->iname; p++) { 10536169Sdonn if (p->format == O_ESCD) { 10636169Sdonn esctab[p->val] = p; 10736169Sdonn } else if (p->format != O_ESCD && p->format != O_ESCE) { 10836169Sdonn ioptab[p->val] = p; 10936169Sdonn } 11036169Sdonn } 11133340Sdonn } 11233340Sdonn 11326344Ssam /* 1149668Slinton * Decode and print the instructions within the given address range. 1159668Slinton */ 1169668Slinton 1179668Slinton public printinst(lowaddr, highaddr) 1189668Slinton Address lowaddr; 1199668Slinton Address highaddr; 1209668Slinton { 1219668Slinton register Address addr; 1229668Slinton 1239668Slinton for (addr = lowaddr; addr <= highaddr; ) { 1249668Slinton addr = printop(addr); 1259668Slinton } 1269668Slinton prtaddr = addr; 1279668Slinton } 1289668Slinton 1299668Slinton /* 1309668Slinton * Another approach: print n instructions starting at the given address. 1319668Slinton */ 1329668Slinton 1339668Slinton public printninst(count, addr) 1349668Slinton int count; 1359668Slinton Address addr; 1369668Slinton { 1379668Slinton register Integer i; 1389668Slinton register Address newaddr; 1399668Slinton 1409668Slinton if (count <= 0) { 1419668Slinton error("non-positive repetition count"); 1429668Slinton } else { 1439668Slinton newaddr = addr; 1449668Slinton for (i = 0; i < count; i++) { 1459668Slinton newaddr = printop(newaddr); 1469668Slinton } 1479668Slinton prtaddr = newaddr; 1489668Slinton } 1499668Slinton } 1509668Slinton 1519668Slinton /* 1529668Slinton * Print the contents of the addresses within the given range 1539668Slinton * according to the given format. 1549668Slinton */ 1559668Slinton 1569668Slinton typedef struct { 1579668Slinton String name; 1589668Slinton String printfstring; 1599668Slinton int length; 1609668Slinton } Format; 1619668Slinton 1629668Slinton private Format fmt[] = { 1639668Slinton { "d", " %d", sizeof(short) }, 1649668Slinton { "D", " %ld", sizeof(long) }, 1659668Slinton { "o", " %o", sizeof(short) }, 1669668Slinton { "O", " %lo", sizeof(long) }, 1679668Slinton { "x", " %04x", sizeof(short) }, 1689668Slinton { "X", " %08x", sizeof(long) }, 1699668Slinton { "b", " \\%o", sizeof(char) }, 1709668Slinton { "c", " '%c'", sizeof(char) }, 1719668Slinton { "s", "%c", sizeof(char) }, 17214338Slinton { "f", " %f", sizeof(float) }, 1739668Slinton { "g", " %g", sizeof(double) }, 1749668Slinton { nil, nil, 0 } 1759668Slinton }; 1769668Slinton 17711174Slinton private Format *findformat(s) 17811174Slinton String s; 17911174Slinton { 18011174Slinton register Format *f; 18111174Slinton 18211174Slinton f = &fmt[0]; 18311174Slinton while (f->name != nil and not streq(f->name, s)) { 18411174Slinton ++f; 18511174Slinton } 18611174Slinton if (f->name == nil) { 18711174Slinton error("bad print format \"%s\"", s); 18811174Slinton } 18911174Slinton return f; 19011174Slinton } 19111174Slinton 19233340Sdonn /* 19333340Sdonn * Retrieve and print out the appropriate data in the given format. 19433340Sdonn * Floats have to be handled specially to allow the compiler to 19533340Sdonn * convert them to doubles when passing to printf. 19633340Sdonn */ 19733340Sdonn 19833340Sdonn private printformat (f, addr) 19933340Sdonn Format *f; 20033340Sdonn Address addr; 20133340Sdonn { 20233340Sdonn union { 20333340Sdonn char charv; 20433340Sdonn short shortv; 20533340Sdonn int intv; 20633340Sdonn float floatv; 20733340Sdonn double doublev; 20833340Sdonn } value; 20933340Sdonn 21033340Sdonn value.intv = 0; 21133340Sdonn dread(&value, addr, f->length); 21233340Sdonn if (streq(f->name, "f")) { 21333340Sdonn printf(f->printfstring, value.floatv); 21433340Sdonn } else { 21533340Sdonn printf(f->printfstring, value); 21633340Sdonn } 21733340Sdonn } 21833340Sdonn 2199668Slinton public Address printdata(lowaddr, highaddr, format) 2209668Slinton Address lowaddr; 2219668Slinton Address highaddr; 2229668Slinton String format; 2239668Slinton { 22433340Sdonn int n; 2259668Slinton register Address addr; 22633340Sdonn Format *f; 2279668Slinton 2289668Slinton if (lowaddr > highaddr) { 2299668Slinton error("first address larger than second"); 2309668Slinton } 23111174Slinton f = findformat(format); 2329668Slinton n = 0; 2339668Slinton for (addr = lowaddr; addr <= highaddr; addr += f->length) { 2349668Slinton if (n == 0) { 2359668Slinton printf("%08x: ", addr); 2369668Slinton } 23733340Sdonn printformat(f, addr); 2389668Slinton ++n; 2399668Slinton if (n >= (16 div f->length)) { 24033340Sdonn printf("\n"); 2419668Slinton n = 0; 2429668Slinton } 2439668Slinton } 2449668Slinton if (n != 0) { 24533340Sdonn printf("\n"); 2469668Slinton } 2479668Slinton prtaddr = addr; 2489668Slinton return addr; 2499668Slinton } 2509668Slinton 2519668Slinton /* 2529668Slinton * The other approach is to print n items starting with a given address. 2539668Slinton */ 2549668Slinton 2559668Slinton public printndata(count, startaddr, format) 2569668Slinton int count; 2579668Slinton Address startaddr; 2589668Slinton String format; 2599668Slinton { 26033340Sdonn int i, n; 26133340Sdonn Address addr; 26233340Sdonn Format *f; 26333340Sdonn Boolean isstring; 26414338Slinton char c; 2659668Slinton 2669668Slinton if (count <= 0) { 2679668Slinton error("non-positive repetition count"); 2689668Slinton } 26911174Slinton f = findformat(format); 2709668Slinton isstring = (Boolean) streq(f->name, "s"); 2719668Slinton n = 0; 2729668Slinton addr = startaddr; 2739668Slinton for (i = 0; i < count; i++) { 2749668Slinton if (n == 0) { 2759668Slinton printf("%08x: ", addr); 2769668Slinton } 2779668Slinton if (isstring) { 27833340Sdonn printf("\""); 27914338Slinton dread(&c, addr, sizeof(char)); 28014338Slinton while (c != '\0') { 28114338Slinton printchar(c); 2829668Slinton ++addr; 28314338Slinton dread(&c, addr, sizeof(char)); 2849668Slinton } 28533340Sdonn printf("\"\n"); 2869668Slinton n = 0; 2879668Slinton addr += sizeof(String); 2889668Slinton } else { 28933340Sdonn printformat(f, addr); 2909668Slinton ++n; 2919668Slinton if (n >= (16 div f->length)) { 29233340Sdonn printf("\n"); 2939668Slinton n = 0; 2949668Slinton } 2959668Slinton addr += f->length; 2969668Slinton } 2979668Slinton } 2989668Slinton if (n != 0) { 29933340Sdonn printf("\n"); 3009668Slinton } 3019668Slinton prtaddr = addr; 3029668Slinton } 3039668Slinton 3049668Slinton /* 30511174Slinton * Print out a value according to the given format. 30611174Slinton */ 30711174Slinton 30811174Slinton public printvalue(v, format) 30911174Slinton long v; 31011174Slinton String format; 31111174Slinton { 31211174Slinton Format *f; 31311174Slinton char *p, *q; 31411174Slinton 31511174Slinton f = findformat(format); 31611174Slinton if (streq(f->name, "s")) { 31711174Slinton putchar('"'); 31811174Slinton p = (char *) &v; 31911174Slinton q = p + sizeof(v); 32011174Slinton while (p < q) { 32111174Slinton printchar(*p); 32211174Slinton ++p; 32311174Slinton } 32411174Slinton putchar('"'); 32511174Slinton } else { 32611174Slinton printf(f->printfstring, v); 32711174Slinton } 32811174Slinton putchar('\n'); 32911174Slinton } 33011174Slinton 33111174Slinton /* 3329668Slinton * Print out an execution time error. 3339842Slinton * Assumes the source position of the error has been calculated. 3349668Slinton * 3359668Slinton * Have to check if the -r option was specified; if so then 3369668Slinton * the object file information hasn't been read in yet. 3379668Slinton */ 3389668Slinton 3399668Slinton public printerror() 3409668Slinton { 3419668Slinton extern Integer sys_nsig; 3429668Slinton extern String sys_siglist[]; 34318222Slinton integer err; 3449668Slinton 3459668Slinton if (isfinished(process)) { 34616932Ssam err = exitcode(process); 34718222Slinton if (err == 0) { 34818222Slinton printf("\"%s\" terminated normally\n", objname); 34918222Slinton } else { 35018222Slinton printf("\"%s\" terminated abnormally (exit code %d)\n", 35118222Slinton objname, err 35218222Slinton ); 35318222Slinton } 3549668Slinton erecover(); 3559668Slinton } 3569668Slinton err = errnum(process); 3579668Slinton putchar('\n'); 35816932Ssam printsig(err); 35918222Slinton putchar(' '); 36016932Ssam printloc(); 36116932Ssam putchar('\n'); 3629668Slinton if (curline > 0) { 3639668Slinton printlines(curline, curline); 3649668Slinton } else { 3659668Slinton printinst(pc, pc); 3669668Slinton } 3679668Slinton erecover(); 3689668Slinton } 3699668Slinton 37018222Slinton /* 37118222Slinton * Print out a signal. 37218222Slinton */ 37318222Slinton 37416932Ssam private String illinames[] = { 37518222Slinton "reserved addressing fault", 37633340Sdonn "privileged instruction fault", 37718222Slinton "reserved operand fault" 37816932Ssam }; 37918222Slinton 38016932Ssam private String fpenames[] = { 38118222Slinton nil, 38218222Slinton "integer overflow trap", 38318222Slinton "integer divide by zero trap", 38418222Slinton "floating overflow trap", 38518222Slinton "floating/decimal divide by zero trap", 38618222Slinton "floating underflow trap", 38718222Slinton "decimal overflow trap", 38818222Slinton "subscript out of range trap", 38918222Slinton "floating overflow fault", 39018222Slinton "floating divide by zero fault", 39133340Sdonn "floating underflow fault" 39216932Ssam }; 39316932Ssam 39418222Slinton public printsig (signo) 39518222Slinton integer signo; 39616932Ssam { 39718222Slinton integer code; 39816932Ssam 39918222Slinton if (signo < 0 or signo > sys_nsig) { 40018222Slinton printf("[signal %d]", signo); 40118222Slinton } else { 40218222Slinton printf("%s", sys_siglist[signo]); 40316932Ssam } 40418222Slinton code = errcode(process); 40518222Slinton if (signo == SIGILL) { 40618222Slinton if (code >= 0 and code < sizeof(illinames) / sizeof(illinames[0])) { 40718222Slinton printf(" (%s)", illinames[code]); 40818222Slinton } 40918222Slinton } else if (signo == SIGFPE) { 41018222Slinton if (code > 0 and code < sizeof(fpenames) / sizeof(fpenames[0])) { 41118222Slinton printf(" (%s)", fpenames[code]); 41218222Slinton } 41318222Slinton } 41416932Ssam } 41516932Ssam 4169668Slinton /* 4179668Slinton * Note the termination of the program. We do this so as to avoid 4189668Slinton * having the process exit, which would make the values of variables 4199668Slinton * inaccessible. We do want to flush all output buffers here, 4209668Slinton * otherwise it'll never get done. 4219668Slinton */ 4229668Slinton 4239668Slinton public endprogram() 4249668Slinton { 4259668Slinton Integer exitcode; 4269668Slinton 4279668Slinton stepto(nextaddr(pc, true)); 4289668Slinton printnews(); 4299668Slinton exitcode = argn(1, nil); 43018222Slinton if (exitcode != 0) { 43118222Slinton printf("\nexecution completed (exit code %d)\n", exitcode); 43218222Slinton } else { 43318222Slinton printf("\nexecution completed\n"); 43418222Slinton } 4359668Slinton getsrcpos(); 4369668Slinton erecover(); 4379668Slinton } 4389668Slinton 4399668Slinton /* 4409668Slinton * Single step the machine a source line (or instruction if "inst_tracing" 44110621Slinton * is true). If "isnext" is true, skip over procedure calls. 4429668Slinton */ 4439668Slinton 4449668Slinton private Address getcall(); 4459668Slinton 4469668Slinton public dostep(isnext) 4479668Slinton Boolean isnext; 4489668Slinton { 4499668Slinton register Address addr; 4509668Slinton register Lineno line; 4519668Slinton String filename; 45218222Slinton Address startaddr; 4539668Slinton 45416612Ssam startaddr = pc; 4559668Slinton addr = nextaddr(pc, isnext); 45610621Slinton if (not inst_tracing and nlhdr.nlines != 0) { 4579668Slinton line = linelookup(addr); 4589668Slinton while (line == 0) { 45918222Slinton addr = nextaddr(addr, isnext); 4609668Slinton line = linelookup(addr); 4619668Slinton } 46210621Slinton curline = line; 46310621Slinton } else { 46410621Slinton curline = 0; 4659668Slinton } 4669668Slinton stepto(addr); 4679668Slinton filename = srcfilename(addr); 4689668Slinton setsource(filename); 4699668Slinton } 4709668Slinton 47133340Sdonn typedef char Bpinst; 47233340Sdonn 47333340Sdonn #define BP_OP O_BPT /* breakpoint trap */ 47433340Sdonn 47533340Sdonn #define BP_ERRNO SIGTRAP /* signal received at a breakpoint */ 47633340Sdonn 4779668Slinton /* 47833340Sdonn * Setting a breakpoint at a location consists of saving 47933340Sdonn * the word at the location and poking a BP_OP there. 48033340Sdonn * 48133340Sdonn * We save the locations and words on a list for use in unsetting. 48233340Sdonn */ 48333340Sdonn 48433340Sdonn typedef struct Savelist *Savelist; 48533340Sdonn 48633340Sdonn struct Savelist { 48733340Sdonn Address location; 48833340Sdonn Bpinst save; 48933340Sdonn short refcount; 49033340Sdonn Savelist link; 49133340Sdonn }; 49233340Sdonn 49333340Sdonn private Savelist savelist; 49433340Sdonn 49533340Sdonn /* 49633340Sdonn * Set a breakpoint at the given address. Only save the word there 49733340Sdonn * if it's not already a breakpoint. 49833340Sdonn */ 49933340Sdonn 50033340Sdonn public setbp(addr) 50133340Sdonn Address addr; 50233340Sdonn { 50333340Sdonn Bpinst w, save; 50433340Sdonn register Savelist newsave, s; 50533340Sdonn 50633340Sdonn for (s = savelist; s != nil; s = s->link) { 50733340Sdonn if (s->location == addr) { 50833340Sdonn s->refcount++; 50933340Sdonn return; 51033340Sdonn } 51133340Sdonn } 51233340Sdonn iread(&save, addr, sizeof(save)); 51333340Sdonn newsave = new(Savelist); 51433340Sdonn newsave->location = addr; 51533340Sdonn newsave->save = save; 51633340Sdonn newsave->refcount = 1; 51733340Sdonn newsave->link = savelist; 51833340Sdonn savelist = newsave; 51933340Sdonn w = BP_OP; 52033340Sdonn iwrite(&w, addr, sizeof(w)); 52133340Sdonn } 52233340Sdonn 52333340Sdonn /* 52433340Sdonn * Unset a breakpoint; unfortunately we have to search the SAVELIST 52533340Sdonn * to find the saved value. The assumption is that the SAVELIST will 52633340Sdonn * usually be quite small. 52733340Sdonn */ 52833340Sdonn 52933340Sdonn public unsetbp(addr) 53033340Sdonn Address addr; 53133340Sdonn { 53233340Sdonn register Savelist s, prev; 53333340Sdonn 53433340Sdonn prev = nil; 53533340Sdonn for (s = savelist; s != nil; s = s->link) { 53633340Sdonn if (s->location == addr) { 53733340Sdonn iwrite(&s->save, addr, sizeof(s->save)); 53833340Sdonn s->refcount--; 53933340Sdonn if (s->refcount == 0) { 54033340Sdonn if (prev == nil) { 54133340Sdonn savelist = s->link; 54233340Sdonn } else { 54333340Sdonn prev->link = s->link; 54433340Sdonn } 54533340Sdonn dispose(s); 54633340Sdonn } 54733340Sdonn return; 54833340Sdonn } 54933340Sdonn prev = s; 55033340Sdonn } 55133340Sdonn panic("unsetbp: couldn't find address %d", addr); 55233340Sdonn } 55333340Sdonn 55433340Sdonn /* 55533340Sdonn * VAX instruction decoder, derived from adb. 55633340Sdonn */ 55733340Sdonn 55833340Sdonn private Address printop(addr) 55933340Sdonn Address addr; 56033340Sdonn { 56133340Sdonn register Optab *op; 56233340Sdonn VaxOpcode ins; 56333340Sdonn unsigned char mode; 56433340Sdonn int argtype, amode, argno, argval; 56533340Sdonn String reg; 56633340Sdonn Boolean indexf; 56733340Sdonn short offset; 56833340Sdonn 56933340Sdonn argval = 0; 57033340Sdonn indexf = false; 57133340Sdonn printf("%08x ", addr); 57233340Sdonn iread(&ins, addr, sizeof(ins)); 57333340Sdonn addr += 1; 57436169Sdonn if (ins == O_ESCF) { 57536169Sdonn iread(&ins, addr, sizeof(ins)); 57636169Sdonn addr += 1; 57736169Sdonn op = ioptab[ins]; 57836169Sdonn } else if (ins == O_ESCD) { 57936169Sdonn iread(&ins, addr, sizeof(ins)); 58036169Sdonn addr += 1; 58136169Sdonn op = esctab[ins]; 58236169Sdonn } else { 58336169Sdonn op = ioptab[ins]; 58436169Sdonn } 58536169Sdonn if (op == nil) { 58636169Sdonn printf("[unrecognized opcode %#0x]\n", ins); 58736169Sdonn return addr; 58836169Sdonn } 58933340Sdonn printf("%s", op->iname); 59033340Sdonn for (argno = 0; argno < op->numargs; argno++) { 59133340Sdonn if (indexf == true) { 59233340Sdonn indexf = false; 59333340Sdonn } else if (argno == 0) { 59433340Sdonn printf("\t"); 59533340Sdonn } else { 59633340Sdonn printf(","); 59733340Sdonn } 59833340Sdonn argtype = op->argtype[argno]; 59933340Sdonn if (is_branch_disp(argtype)) { 60033340Sdonn mode = 0xAF + (typelen(argtype) << 5); 60133340Sdonn } else { 60233340Sdonn iread(&mode, addr, sizeof(mode)); 60333340Sdonn addr += 1; 60433340Sdonn } 60533340Sdonn reg = regname[regnm(mode)]; 60633340Sdonn amode = addrmode(mode); 60733340Sdonn switch (amode) { 60833340Sdonn case LITSHORT: 60933340Sdonn case LITUPTO31: 61033340Sdonn case LITUPTO47: 61133340Sdonn case LITUPTO63: 61236169Sdonn if (typelen(argtype) == TYPF || typelen(argtype) == TYPD || 61336169Sdonn typelen(argtype) == TYPG || typelen(argtype) == TYPH) 61433340Sdonn printf("$%s", fltimm[mode]); 61533340Sdonn else 61633340Sdonn printf("$%x", mode); 61733340Sdonn argval = mode; 61833340Sdonn break; 61933340Sdonn 62033340Sdonn case INDEX: 62133340Sdonn printf("[%s]", reg); 62233340Sdonn indexf = true; 62333340Sdonn argno--; 62433340Sdonn break; 62533340Sdonn 62633340Sdonn case REG: 62733340Sdonn printf("%s", reg); 62833340Sdonn break; 62933340Sdonn 63033340Sdonn case REGDEF: 63133340Sdonn printf("(%s)", reg); 63233340Sdonn break; 63333340Sdonn 63433340Sdonn case AUTODEC: 63533340Sdonn printf("-(%s)", reg); 63633340Sdonn break; 63733340Sdonn 63833340Sdonn case AUTOINC: 63933340Sdonn if (reg != regname[PROGCTR]) { 64033340Sdonn printf("(%s)+", reg); 64133340Sdonn } else { 64233340Sdonn printf("$"); 64333340Sdonn switch (typelen(argtype)) { 64433340Sdonn case TYPB: 64533340Sdonn argval = printdisp(addr, 1, reg, amode); 64633340Sdonn addr += 1; 64733340Sdonn break; 64833340Sdonn 64933340Sdonn case TYPW: 65033340Sdonn argval = printdisp(addr, 2, reg, amode); 65133340Sdonn addr += 2; 65233340Sdonn break; 65333340Sdonn 65433340Sdonn case TYPL: 65533340Sdonn argval = printdisp(addr, 4, reg, amode); 65633340Sdonn addr += 4; 65733340Sdonn break; 65833340Sdonn 65933340Sdonn case TYPF: 66033340Sdonn iread(&argval, addr, sizeof(argval)); 66136169Sdonn if ((argval & 0xffff007f) == 0x8000) { 66236169Sdonn printf("[reserved operand]"); 66336169Sdonn } else { 66436169Sdonn printf("%g", *(float *)&argval); 66536169Sdonn } 66633340Sdonn addr += 4; 66733340Sdonn break; 66833340Sdonn 66933340Sdonn case TYPD: 67036169Sdonn /* XXX this bags the low order bits */ 67133340Sdonn iread(&argval, addr, sizeof(argval)); 67236169Sdonn if ((argval & 0xffff007f) == 0x8000) { 67336169Sdonn printf("[reserved operand]"); 67436169Sdonn } else { 67536169Sdonn printf("%g", *(float *)&argval); 67636169Sdonn } 67736169Sdonn addr += 8; 67836169Sdonn break; 67936169Sdonn 68036169Sdonn case TYPG: 68136169Sdonn case TYPQ: 68233340Sdonn iread(&argval, addr+4, sizeof(argval)); 68336169Sdonn printf("%08x", argval); 68436169Sdonn iread(&argval, addr, sizeof(argval)); 68536169Sdonn printf("%08x", argval); 68633340Sdonn addr += 8; 68733340Sdonn break; 68836169Sdonn 68936169Sdonn case TYPH: 69036169Sdonn case TYPO: 69136169Sdonn iread(&argval, addr+12, sizeof(argval)); 69236169Sdonn printf("%08x", argval); 69336169Sdonn iread(&argval, addr+8, sizeof(argval)); 69436169Sdonn printf("%08x", argval); 69536169Sdonn iread(&argval, addr+4, sizeof(argval)); 69636169Sdonn printf("%08x", argval); 69736169Sdonn iread(&argval, addr, sizeof(argval)); 69836169Sdonn printf("%08x", argval); 69936169Sdonn addr += 16; 70036169Sdonn break; 70133340Sdonn } 70233340Sdonn } 70333340Sdonn break; 70433340Sdonn 70533340Sdonn case AUTOINCDEF: 70633340Sdonn if (reg == regname[PROGCTR]) { 70733340Sdonn printf("*$"); 70833340Sdonn argval = printdisp(addr, 4, reg, amode); 70933340Sdonn addr += 4; 71033340Sdonn } else { 71133340Sdonn printf("*(%s)+", reg); 71233340Sdonn } 71333340Sdonn break; 71433340Sdonn 71533340Sdonn case BYTEDISP: 71633340Sdonn argval = printdisp(addr, 1, reg, amode); 71733340Sdonn addr += 1; 71833340Sdonn break; 71933340Sdonn 72033340Sdonn case BYTEDISPDEF: 72133340Sdonn printf("*"); 72233340Sdonn argval = printdisp(addr, 1, reg, amode); 72333340Sdonn addr += 1; 72433340Sdonn break; 72533340Sdonn 72633340Sdonn case WORDDISP: 72733340Sdonn argval = printdisp(addr, 2, reg, amode); 72833340Sdonn addr += 2; 72933340Sdonn break; 73033340Sdonn 73133340Sdonn case WORDDISPDEF: 73233340Sdonn printf("*"); 73333340Sdonn argval = printdisp(addr, 2, reg, amode); 73433340Sdonn addr += 2; 73533340Sdonn break; 73633340Sdonn 73733340Sdonn case LONGDISP: 73833340Sdonn argval = printdisp(addr, 4, reg, amode); 73933340Sdonn addr += 4; 74033340Sdonn break; 74133340Sdonn 74233340Sdonn case LONGDISPDEF: 74333340Sdonn printf("*"); 74433340Sdonn argval = printdisp(addr, 4, reg, amode); 74533340Sdonn addr += 4; 74633340Sdonn break; 74733340Sdonn } 74833340Sdonn } 74933340Sdonn if (ins == O_CASEB || ins == O_CASEW || ins == O_CASEL) { 75033340Sdonn for (argno = 0; argno <= argval; argno++) { 75133340Sdonn iread(&offset, addr, sizeof(offset)); 75233340Sdonn printf("\n\t\t%d", offset); 75333340Sdonn addr += 2; 75433340Sdonn } 75533340Sdonn } 75633340Sdonn printf("\n"); 75733340Sdonn return addr; 75833340Sdonn } 75933340Sdonn 76033340Sdonn /* 76133340Sdonn * Print the displacement of an instruction that uses displacement 76233340Sdonn * addressing. 76333340Sdonn */ 76433340Sdonn 76533340Sdonn private int printdisp(addr, nbytes, reg, mode) 76633340Sdonn Address addr; 76733340Sdonn int nbytes; 76833340Sdonn char *reg; 76933340Sdonn int mode; 77033340Sdonn { 77133340Sdonn char byte; 77233340Sdonn short hword; 77333340Sdonn int argval; 77433340Sdonn Symbol f; 77533340Sdonn 77633340Sdonn switch (nbytes) { 77733340Sdonn case 1: 77833340Sdonn iread(&byte, addr, sizeof(byte)); 77933340Sdonn argval = byte; 78033340Sdonn break; 78133340Sdonn 78233340Sdonn case 2: 78333340Sdonn iread(&hword, addr, sizeof(hword)); 78433340Sdonn argval = hword; 78533340Sdonn break; 78633340Sdonn 78733340Sdonn case 4: 78833340Sdonn iread(&argval, addr, sizeof(argval)); 78933340Sdonn break; 79033340Sdonn } 79133340Sdonn if (reg == regname[PROGCTR] && mode >= BYTEDISP) { 79233340Sdonn argval += addr + nbytes; 79333340Sdonn } 79433340Sdonn if (reg == regname[PROGCTR]) { 79533340Sdonn f = whatblock((Address) argval + 2); 79633340Sdonn if (codeloc(f) == argval + 2) { 79733340Sdonn printf("%s", symname(f)); 79833340Sdonn } else { 79933340Sdonn printf("%x", argval); 80033340Sdonn } 80133340Sdonn } else { 80233340Sdonn if (varIsSet("$hexoffsets")) { 80333340Sdonn if (argval < 0) { 80433340Sdonn printf("-%x(%s)", -(argval), reg); 80533340Sdonn } else { 80633340Sdonn printf("%x(%s)", argval, reg); 80733340Sdonn } 80833340Sdonn } else { 80933340Sdonn printf("%d(%s)", argval, reg); 81033340Sdonn } 81133340Sdonn } 81233340Sdonn return argval; 81333340Sdonn } 81433340Sdonn 81533340Sdonn /* 8169668Slinton * Compute the next address that will be executed from the given one. 8179668Slinton * If "isnext" is true then consider a procedure call as straight line code. 8189668Slinton * 8199668Slinton * We must unfortunately do much of the same work that is necessary 8209668Slinton * to print instructions. In addition we have to deal with branches. 8219668Slinton * Unconditional branches we just follow, for conditional branches 8229668Slinton * we continue execution to the current location and then single step 8239668Slinton * the machine. We assume that the last argument in an instruction 8249668Slinton * that branches is the branch address (or relative offset). 8259668Slinton */ 8269668Slinton 82718222Slinton private Address findnextaddr(); 82818222Slinton 8299668Slinton public Address nextaddr(startaddr, isnext) 8309668Slinton Address startaddr; 83116612Ssam boolean isnext; 83216612Ssam { 83316612Ssam Address addr; 83416612Ssam 83516612Ssam addr = usignal(process); 83616612Ssam if (addr == 0 or addr == 1) { 83716612Ssam addr = findnextaddr(startaddr, isnext); 83816612Ssam } 83916612Ssam return addr; 84016612Ssam } 84116612Ssam 84218222Slinton /* 84318222Slinton * Determine if it's ok to skip function f entered by instruction ins. 84418222Slinton * If so, we're going to compute the return address and step to it. 84518222Slinton * Therefore we cannot skip over a function entered by a jsb or bsb, 84618222Slinton * since the return address is not easily computed for them. 84718222Slinton */ 84818222Slinton 84918222Slinton private boolean skipfunc (ins, f) 85018222Slinton VaxOpcode ins; 85118222Slinton Symbol f; 85218222Slinton { 85318222Slinton boolean b; 85418222Slinton 85518222Slinton b = (boolean) ( 85618222Slinton ins != O_JSB and ins != O_BSBB and ins != O_BSBW and 85718222Slinton not inst_tracing and nlhdr.nlines != 0 and 85818222Slinton nosource(curfunc) and canskip(curfunc) 85918222Slinton ); 86018222Slinton return b; 86118222Slinton } 86218222Slinton 86316612Ssam private Address findnextaddr(startaddr, isnext) 86416612Ssam Address startaddr; 8659668Slinton Boolean isnext; 8669668Slinton { 8679668Slinton register Address addr; 86833340Sdonn register Optab *op; 86936169Sdonn VaxOpcode ins, ins2; 8709668Slinton unsigned char mode; 8719668Slinton int argtype, amode, argno, argval; 8729668Slinton String r; 8739668Slinton Boolean indexf; 8749668Slinton enum { KNOWN, SEQUENTIAL, BRANCH } addrstatus; 8759668Slinton 8769668Slinton argval = 0; 8779668Slinton indexf = false; 8789668Slinton addr = startaddr; 8799668Slinton iread(&ins, addr, sizeof(ins)); 8809668Slinton switch (ins) { 88118222Slinton /* 88218222Slinton * It used to be that unconditional jumps and branches were handled 88318222Slinton * by taking their destination address as the next address. While 88418222Slinton * saving the cost of starting up the process, this approach 88518222Slinton * doesn't work when jumping indirect (since the value in the 88618222Slinton * register might not yet have been set). 88718222Slinton * 88818222Slinton * So unconditional jumps and branches are now handled the same way 88918222Slinton * as conditional jumps and branches. 89018222Slinton * 8919668Slinton case O_BRB: 8929668Slinton case O_BRW: 8939668Slinton addrstatus = BRANCH; 8949668Slinton break; 89518222Slinton * 89618222Slinton */ 8979668Slinton 8989668Slinton case O_BSBB: 8999668Slinton case O_BSBW: 9009668Slinton case O_JSB: 9019668Slinton case O_CALLG: 9029668Slinton case O_CALLS: 90318222Slinton addrstatus = KNOWN; 90418222Slinton stepto(addr); 90518222Slinton pstep(process, DEFSIG); 90618222Slinton addr = reg(PROGCTR); 90718222Slinton pc = addr; 90818222Slinton setcurfunc(whatblock(pc)); 90918222Slinton if (not isbperr()) { 91018222Slinton printstatus(); 91118222Slinton /* NOTREACHED */ 91218222Slinton } 91318222Slinton bpact(); 91418222Slinton if (isnext or skipfunc(ins, curfunc)) { 9159668Slinton addrstatus = KNOWN; 91618222Slinton addr = return_addr(); 9179668Slinton stepto(addr); 91811864Slinton bpact(); 91918222Slinton } else { 92018222Slinton callnews(/* iscall = */ true); 9219668Slinton } 9229668Slinton break; 9239668Slinton 9249668Slinton case O_RSB: 9259668Slinton case O_RET: 9269668Slinton addrstatus = KNOWN; 92718222Slinton stepto(addr); 9289668Slinton callnews(/* iscall = */ false); 92918222Slinton pstep(process, DEFSIG); 93018222Slinton addr = reg(PROGCTR); 93118222Slinton pc = addr; 93218222Slinton if (not isbperr()) { 93318222Slinton printstatus(); 93416612Ssam } 93511874Slinton bpact(); 9369668Slinton break; 9379668Slinton 93818222Slinton case O_BRB: case O_BRW: 93916612Ssam case O_JMP: /* because it may be jmp (r1) */ 9409668Slinton case O_BNEQ: case O_BEQL: case O_BGTR: 9419668Slinton case O_BLEQ: case O_BGEQ: case O_BLSS: 9429668Slinton case O_BGTRU: case O_BLEQU: case O_BVC: 9439668Slinton case O_BVS: case O_BCC: case O_BCS: 9449668Slinton case O_CASEB: case O_CASEW: case O_CASEL: 9459668Slinton case O_BBS: case O_BBC: case O_BBSS: case O_BBCS: 9469668Slinton case O_BBSC: case O_BBCC: case O_BBSSI: 9479668Slinton case O_BBCCI: case O_BLBS: case O_BLBC: 9489668Slinton case O_ACBL: case O_AOBLSS: case O_AOBLEQ: 9499668Slinton case O_SOBGEQ: case O_SOBGTR: 95036169Sdonn case O_ESCF: /* bugchecks */ 95136169Sdonn branches: 9529668Slinton addrstatus = KNOWN; 9539668Slinton stepto(addr); 95416612Ssam pstep(process, DEFSIG); 9559668Slinton addr = reg(PROGCTR); 9569668Slinton pc = addr; 9579668Slinton if (not isbperr()) { 9589668Slinton printstatus(); 9599668Slinton } 9609668Slinton break; 9619668Slinton 96236169Sdonn case O_ESCD: 96336169Sdonn iread(&ins2, addr+1, sizeof(ins2)); 96436169Sdonn if (ins2 == O_ACBF || ins2 == O_ACBD) 96536169Sdonn /* actually ACBG and ACBH */ 96636169Sdonn goto branches; 96736169Sdonn /* fall through */ 96836169Sdonn 9699668Slinton default: 9709668Slinton addrstatus = SEQUENTIAL; 9719668Slinton break; 9729668Slinton } 9739668Slinton if (addrstatus != KNOWN) { 9749668Slinton addr += 1; 97536169Sdonn if (ins == O_ESCD) { 97636169Sdonn ins = ins2; 97736169Sdonn addr += 1; 97836169Sdonn op = esctab[ins]; 97936169Sdonn if (op == nil) { 98036169Sdonn printf("[bad extended opcode %#x in findnextaddr]\n", ins); 98136169Sdonn return addr; 98236169Sdonn } 98336169Sdonn } else { 98436169Sdonn op = ioptab[ins]; 98536169Sdonn if (op == nil) { 98636169Sdonn printf("[bad opcode %#x in findnextaddr]\n", ins); 98736169Sdonn return addr; 98836169Sdonn } 98936169Sdonn } 99033340Sdonn for (argno = 0; argno < op->numargs; argno++) { 9919668Slinton if (indexf == true) { 9929668Slinton indexf = false; 9939668Slinton } 99433340Sdonn argtype = op->argtype[argno]; 9959668Slinton if (is_branch_disp(argtype)) { 9969668Slinton mode = 0xAF + (typelen(argtype) << 5); 9979668Slinton } else { 9989668Slinton iread(&mode, addr, sizeof(mode)); 9999668Slinton addr += 1; 10009668Slinton } 10019668Slinton r = regname[regnm(mode)]; 10029668Slinton amode = addrmode(mode); 10039668Slinton switch (amode) { 10049668Slinton case LITSHORT: 10059668Slinton case LITUPTO31: 10069668Slinton case LITUPTO47: 10079668Slinton case LITUPTO63: 10089668Slinton argval = mode; 10099668Slinton break; 10109668Slinton 10119668Slinton case INDEX: 10129668Slinton indexf = true; 10139668Slinton --argno; 10149668Slinton break; 10159668Slinton 10169668Slinton case REG: 10179668Slinton case REGDEF: 10189668Slinton case AUTODEC: 10199668Slinton break; 10209668Slinton 10219668Slinton case AUTOINC: 10229668Slinton if (r == regname[PROGCTR]) { 10239668Slinton switch (typelen(argtype)) { 10249668Slinton case TYPB: 10259668Slinton argval = getdisp(addr, 1, r, amode); 10269668Slinton addr += 1; 10279668Slinton break; 10289668Slinton 10299668Slinton case TYPW: 10309668Slinton argval = getdisp(addr, 2, r, amode); 10319668Slinton addr += 2; 10329668Slinton break; 10339668Slinton 10349668Slinton case TYPL: 10359668Slinton argval = getdisp(addr, 4, r, amode); 10369668Slinton addr += 4; 10379668Slinton break; 10389668Slinton 10399668Slinton case TYPF: 10409668Slinton iread(&argval, addr, sizeof(argval)); 10419668Slinton addr += 4; 10429668Slinton break; 10439668Slinton 10449668Slinton case TYPQ: 10459668Slinton case TYPD: 104636169Sdonn case TYPG: 10479668Slinton iread(&argval, addr+4, sizeof(argval)); 10489668Slinton addr += 8; 10499668Slinton break; 105036169Sdonn 105136169Sdonn case TYPO: 105236169Sdonn case TYPH: 105336169Sdonn iread(&argval, addr+12, sizeof(argval)); 105436169Sdonn addr += 16; 105536169Sdonn break; 10569668Slinton } 10579668Slinton } 10589668Slinton break; 10599668Slinton 10609668Slinton case AUTOINCDEF: 10619668Slinton if (r == regname[PROGCTR]) { 10629668Slinton argval = getdisp(addr, 4, r, amode); 10639668Slinton addr += 4; 10649668Slinton } 10659668Slinton break; 10669668Slinton 10679668Slinton case BYTEDISP: 10689668Slinton case BYTEDISPDEF: 10699668Slinton argval = getdisp(addr, 1, r, amode); 10709668Slinton addr += 1; 10719668Slinton break; 10729668Slinton 10739668Slinton case WORDDISP: 10749668Slinton case WORDDISPDEF: 10759668Slinton argval = getdisp(addr, 2, r, amode); 10769668Slinton addr += 2; 10779668Slinton break; 10789668Slinton 10799668Slinton case LONGDISP: 10809668Slinton case LONGDISPDEF: 10819668Slinton argval = getdisp(addr, 4, r, amode); 10829668Slinton addr += 4; 10839668Slinton break; 10849668Slinton } 10859668Slinton } 10869668Slinton if (ins == O_CALLS or ins == O_CALLG) { 10879668Slinton argval += 2; 10889668Slinton } 10899668Slinton if (addrstatus == BRANCH) { 10909668Slinton addr = argval; 10919668Slinton } 10929668Slinton } 10939668Slinton return addr; 10949668Slinton } 10959668Slinton 10969668Slinton /* 10979668Slinton * Get the displacement of an instruction that uses displacement addressing. 10989668Slinton */ 10999668Slinton 11009668Slinton private int getdisp(addr, nbytes, reg, mode) 11019668Slinton Address addr; 11029668Slinton int nbytes; 11039668Slinton String reg; 11049668Slinton int mode; 11059668Slinton { 11069668Slinton char byte; 11079668Slinton short hword; 11089668Slinton int argval; 11099668Slinton 11109668Slinton switch (nbytes) { 11119668Slinton case 1: 11129668Slinton iread(&byte, addr, sizeof(byte)); 11139668Slinton argval = byte; 11149668Slinton break; 11159668Slinton 11169668Slinton case 2: 11179668Slinton iread(&hword, addr, sizeof(hword)); 11189668Slinton argval = hword; 11199668Slinton break; 11209668Slinton 11219668Slinton case 4: 11229668Slinton iread(&argval, addr, sizeof(argval)); 11239668Slinton break; 11249668Slinton } 11259668Slinton if (reg == regname[PROGCTR] && mode >= BYTEDISP) { 11269668Slinton argval += addr + nbytes; 11279668Slinton } 11289668Slinton return argval; 11299668Slinton } 11309668Slinton 11319668Slinton /* 11329668Slinton * Enter a procedure by creating and executing a call instruction. 11339668Slinton */ 11349668Slinton 11359668Slinton #define CALLSIZE 7 /* size of call instruction */ 11369668Slinton 11379668Slinton public beginproc(p, argc) 11389668Slinton Symbol p; 11399668Slinton Integer argc; 11409668Slinton { 11419668Slinton char save[CALLSIZE]; 11429668Slinton struct { 11439668Slinton VaxOpcode op; 11449668Slinton unsigned char numargs; 11459668Slinton unsigned char mode; 11469668Slinton char addr[sizeof(long)]; /* unaligned long */ 11479668Slinton } call; 11489668Slinton long dest; 11499668Slinton 11509668Slinton pc = 2; 11519668Slinton iread(save, pc, sizeof(save)); 11529668Slinton call.op = O_CALLS; 11539668Slinton call.numargs = argc; 11549668Slinton call.mode = 0xef; 11559668Slinton dest = codeloc(p) - 2 - (pc + 7); 11569668Slinton mov(&dest, call.addr, sizeof(call.addr)); 11579668Slinton iwrite(&call, pc, sizeof(call)); 11589668Slinton setreg(PROGCTR, pc); 115916612Ssam pstep(process, DEFSIG); 11609668Slinton iwrite(save, pc, sizeof(save)); 11619668Slinton pc = reg(PROGCTR); 11629668Slinton if (not isbperr()) { 11639668Slinton printstatus(); 11649668Slinton } 11659668Slinton } 116626336Ssam 116726336Ssam /* 116826336Ssam * Special variables for debugging the kernel. 116926336Ssam */ 117026336Ssam 117126336Ssam public integer masterpcbb; 117226336Ssam public integer slr; 117326336Ssam public struct pte *sbr; 117433340Sdonn private struct pcb pcb; 117526336Ssam 117626336Ssam public getpcb () 117726336Ssam { 117833340Sdonn integer i; 117933340Sdonn 118033340Sdonn fseek(corefile, masterpcbb & ~0x80000000, 0); 118126336Ssam get(corefile, pcb); 118226336Ssam pcb.pcb_p0lr &= ~AST_CLR; 118326336Ssam printf("p0br %lx p0lr %lx p1br %lx p1lr %lx\n", 118426336Ssam pcb.pcb_p0br, pcb.pcb_p0lr, pcb.pcb_p1br, pcb.pcb_p1lr 118526336Ssam ); 118626336Ssam setreg(0, pcb.pcb_r0); 118726336Ssam setreg(1, pcb.pcb_r1); 118826336Ssam setreg(2, pcb.pcb_r2); 118926336Ssam setreg(3, pcb.pcb_r3); 119026336Ssam setreg(4, pcb.pcb_r4); 119126336Ssam setreg(5, pcb.pcb_r5); 119226336Ssam setreg(6, pcb.pcb_r6); 119326336Ssam setreg(7, pcb.pcb_r7); 119426336Ssam setreg(8, pcb.pcb_r8); 119526336Ssam setreg(9, pcb.pcb_r9); 119626336Ssam setreg(10, pcb.pcb_r10); 119726336Ssam setreg(11, pcb.pcb_r11); 119826336Ssam setreg(ARGP, pcb.pcb_ap); 119926336Ssam setreg(FRP, pcb.pcb_fp); 120026336Ssam setreg(STKP, pcb.pcb_ksp); 120126336Ssam setreg(PROGCTR, pcb.pcb_pc); 120226336Ssam } 120326336Ssam 120426336Ssam public copyregs (savreg, reg) 120526336Ssam Word savreg[], reg[]; 120626336Ssam { 120726336Ssam reg[0] = savreg[R0]; 120826336Ssam reg[1] = savreg[R1]; 120926336Ssam reg[2] = savreg[R2]; 121026336Ssam reg[3] = savreg[R3]; 121126336Ssam reg[4] = savreg[R4]; 121226336Ssam reg[5] = savreg[R5]; 121326336Ssam reg[6] = savreg[R6]; 121426336Ssam reg[7] = savreg[R7]; 121526336Ssam reg[8] = savreg[R8]; 121626336Ssam reg[9] = savreg[R9]; 121726336Ssam reg[10] = savreg[R10]; 121826336Ssam reg[11] = savreg[R11]; 121926336Ssam reg[ARGP] = savreg[AP]; 122026336Ssam reg[FRP] = savreg[FP]; 122126336Ssam reg[STKP] = savreg[SP]; 122226336Ssam reg[PROGCTR] = savreg[PC]; 122326336Ssam } 122426336Ssam 122526336Ssam /* 122626336Ssam * Map a virtual address to a physical address. 122726336Ssam */ 122826336Ssam 122926336Ssam public Address vmap (addr) 123026336Ssam Address addr; 123126336Ssam { 123226336Ssam Address r; 123326336Ssam integer v, n; 123426336Ssam struct pte pte; 123526336Ssam 123626336Ssam r = addr & ~0xc0000000; 123726336Ssam v = btop(r); 123826336Ssam switch (addr&0xc0000000) { 123926336Ssam case 0xc0000000: 124026336Ssam case 0x80000000: 124126336Ssam /* 124226336Ssam * In system space, so get system pte. 124326336Ssam * If it is valid or reclaimable then the physical address 124426336Ssam * is the combination of its page number and the page offset 124526336Ssam * of the original address. 124626336Ssam */ 124726336Ssam if (v >= slr) { 124826336Ssam error("address %x out of segment", addr); 124926336Ssam } 125026336Ssam r = ((long) (sbr + v)) & ~0x80000000; 125126336Ssam goto simple; 125226336Ssam 125326336Ssam case 0x40000000: 125426336Ssam /* 125526336Ssam * In p1 space, must not be in shadow region. 125626336Ssam */ 125726336Ssam if (v < pcb.pcb_p1lr) { 125826336Ssam error("address %x out of segment", addr); 125926336Ssam } 126026336Ssam r = (Address) (pcb.pcb_p1br + v); 126126336Ssam break; 126226336Ssam 126326336Ssam case 0x00000000: 126426336Ssam /* 126526336Ssam * In p0 space, must not be off end of region. 126626336Ssam */ 126726336Ssam if (v >= pcb.pcb_p0lr) { 126826336Ssam error("address %x out of segment", addr); 126926336Ssam } 127026336Ssam r = (Address) (pcb.pcb_p0br + v); 127126336Ssam break; 127226336Ssam 127326336Ssam default: 127426336Ssam /* do nothing */ 127526336Ssam break; 127626336Ssam } 127726336Ssam /* 127826336Ssam * For p0/p1 address, user-level page table should be in 127926336Ssam * kernel virtual memory. Do second-level indirect by recursing. 128026336Ssam */ 128126336Ssam if ((r & 0x80000000) == 0) { 128226336Ssam error("bad p0br or p1br in pcb"); 128326336Ssam } 128426336Ssam r = vmap(r); 128526336Ssam simple: 128626336Ssam /* 128726336Ssam * "r" is now the address of the pte of the page 128826336Ssam * we are interested in; get the pte and paste up the physical address. 128926336Ssam */ 129026336Ssam fseek(corefile, r, 0); 129126336Ssam n = fread(&pte, sizeof(pte), 1, corefile); 129226336Ssam if (n != 1) { 129326336Ssam error("page table botch (fread at %x returns %d)", r, n); 129426336Ssam } 129526336Ssam if (pte.pg_v == 0 and (pte.pg_fod != 0 or pte.pg_pfnum == 0)) { 129626336Ssam error("page no valid or reclamable"); 129726336Ssam } 129826336Ssam return (addr&PGOFSET) + ((Address) ptob(pte.pg_pfnum)); 129926336Ssam } 130033340Sdonn 130133340Sdonn /* 130233340Sdonn * Extract a bit field from an integer. 130333340Sdonn */ 130433340Sdonn 130533340Sdonn public integer extractField (s) 130633340Sdonn Symbol s; 130733340Sdonn { 130833340Sdonn integer n, nbytes, r; 130933340Sdonn 131033340Sdonn n = 0; 131133340Sdonn nbytes = size(s); 131233340Sdonn if (nbytes > sizeof(n)) { 131333340Sdonn printf("[bad size in extractField -- word assumed]\n"); 131433340Sdonn nbytes = sizeof(n); 131533340Sdonn } 131633340Sdonn popn(nbytes, &n); 131733340Sdonn r = n >> (s->symvalue.field.offset mod BITSPERBYTE); 131833340Sdonn r &= ((1 << s->symvalue.field.length) - 1); 131933340Sdonn return r; 132033340Sdonn } 132133340Sdonn 132233340Sdonn /* 132333340Sdonn * Change the length of a value in memory according to a given difference 132433340Sdonn * in the lengths of its new and old types. 132533340Sdonn */ 132633340Sdonn 132733340Sdonn public loophole (oldlen, newlen) 132833340Sdonn integer oldlen, newlen; 132933340Sdonn { 133033340Sdonn integer n, i; 133133340Sdonn 133233340Sdonn n = newlen - oldlen; 133333340Sdonn if (n > 0) { 133433340Sdonn for (i = 0; i < n; i++) { 133533340Sdonn sp[i] = '\0'; 133633340Sdonn } 133733340Sdonn } 133833340Sdonn sp += n; 133933340Sdonn } 1340