xref: /csrg-svn/old/dbx/vax.c (revision 38105)
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