xref: /csrg-svn/old/dbx/sun.c (revision 42686)
138103Sbostic /*
238103Sbostic  * Copyright (c) 1983 The Regents of the University of California.
338103Sbostic  * All rights reserved.
438103Sbostic  *
5*42686Sbostic  * %sccs.include.redist.c%
638103Sbostic  */
738103Sbostic 
838103Sbostic #ifndef lint
9*42686Sbostic static char sccsid[] = "@(#)sun.c	5.2 (Berkeley) 06/01/90";
1038103Sbostic #endif /* not lint */
1138103Sbostic 
1238103Sbostic /*
1338103Sbostic  * Target machine dependent stuff.
1438103Sbostic  */
1538103Sbostic 
1638103Sbostic #include "defs.h"
1738103Sbostic #include "machine.h"
1838103Sbostic #include "process.h"
1938103Sbostic #include "runtime.h"
2038103Sbostic #include "events.h"
2138103Sbostic #include "main.h"
2238103Sbostic #include "symbols.h"
2338103Sbostic #include "source.h"
2438103Sbostic #include "mappings.h"
2538103Sbostic #include "object.h"
2638103Sbostic #include "tree.h"
2738103Sbostic #include "eval.h"
2838103Sbostic #include "keywords.h"
2938103Sbostic #include "ops.h"
3038103Sbostic 
3138103Sbostic #ifndef public
3238103Sbostic typedef unsigned int Address;
3338103Sbostic typedef unsigned char Byte;
3438103Sbostic typedef unsigned int Word;
3538103Sbostic 
3638103Sbostic /*
3738103Sbostic  * On the 68000, the pc isn't in a register, but we make believe
3838103Sbostic  * so there's one more register.
3938103Sbostic  *
4038103Sbostic  * Note that there's also no argument pointer, this means code
4138103Sbostic  * involving "ARGP" should always be #ifdef'd.
4238103Sbostic  *
4338103Sbostic  * The address corresponding to the beginning of a function is recorded
4438103Sbostic  * as the address + FUNCOFFSET (skip the link instruction so that
4538103Sbostic  * local information is available).
4638103Sbostic  */
4738103Sbostic 
4838103Sbostic #define NREG 17
4938103Sbostic 
5038103Sbostic #define FRP 14
5138103Sbostic #define STKP 15
5238103Sbostic #define PROGCTR 16
5338103Sbostic 
5438103Sbostic #define CALL_RETADDR	0x800c		/* Return address for 'call' command */
5538103Sbostic #define FUNCOFFSET 4
5638103Sbostic 
5738103Sbostic #ifdef sun
5838103Sbostic #    define CODESTART 0x8000
5938103Sbostic #else /* IRIS */
6038103Sbostic #   define CODESTART 0x1000
6138103Sbostic #endif
6238103Sbostic 
6338103Sbostic #define optab_init()
6438103Sbostic 
6538103Sbostic #define BITSPERBYTE 8
6638103Sbostic #define BITSPERWORD (BITSPERBYTE * sizeof(Word))
6738103Sbostic 
6838103Sbostic /*
6938103Sbostic  * This magic macro enables us to look at the process' registers
7038103Sbostic  * in its user structure.
7138103Sbostic  */
7238103Sbostic 
7338103Sbostic #define regloc(reg)	(ctob(UPAGES) + (sizeof(Word) * ((reg) - PC)) - 10)
7438103Sbostic 
7538103Sbostic #include "source.h"
7638103Sbostic #include "symbols.h"
7738103Sbostic #include <signal.h>
7838103Sbostic #include <sys/param.h>
7938103Sbostic #include <sys/dir.h>
8038103Sbostic #include <machine/psl.h>
8138103Sbostic #include <machine/pte.h>
8238103Sbostic #include <sys/user.h>
8338103Sbostic #undef DELETE /* XXX */
8438103Sbostic #include <sys/vm.h>
8538103Sbostic #include <machine/reg.h>
8638103Sbostic 
8738103Sbostic Address pc;
8838103Sbostic Address prtaddr;
8938103Sbostic 
9038103Sbostic #endif
9138103Sbostic 
9238103Sbostic /*
9338103Sbostic  * Indices into u. for use in collecting registers values.
9438103Sbostic  */
9538103Sbostic public int rloc[] ={
9638103Sbostic #ifdef sun
9738103Sbostic     R0, R1, R2, R3, R4, R5, R6, R7, AR0, AR1, AR2, AR3, AR4, AR5, AR6, AR7, PC
9838103Sbostic #else /* IRIS */
9938103Sbostic     R0, R1, R2, R3, R4, R5, R6, R7, AR0, AR1, AR2, AR3, AR4, AR5, AR6, AR7, 16
10038103Sbostic #endif
10138103Sbostic };
10238103Sbostic 
10338103Sbostic private Address printop();
10438103Sbostic 
10538103Sbostic /*
10638103Sbostic  * Decode and print the instructions within the given address range.
10738103Sbostic  */
10838103Sbostic 
printinst(lowaddr,highaddr)10938103Sbostic public printinst(lowaddr, highaddr)
11038103Sbostic Address lowaddr;
11138103Sbostic Address highaddr;
11238103Sbostic {
11338103Sbostic     register Address addr;
11438103Sbostic 
11538103Sbostic     for (addr = lowaddr; addr <= highaddr; ) {
11638103Sbostic 	addr = printop(addr);
11738103Sbostic     }
11838103Sbostic     prtaddr = addr;
11938103Sbostic }
12038103Sbostic 
12138103Sbostic /*
12238103Sbostic  * Another approach:  print n instructions starting at the given address.
12338103Sbostic  */
12438103Sbostic 
printninst(count,addr)12538103Sbostic public printninst(count, addr)
12638103Sbostic int count;
12738103Sbostic Address addr;
12838103Sbostic {
12938103Sbostic     register Integer i;
13038103Sbostic     register Address newaddr;
13138103Sbostic 
13238103Sbostic     if (count <= 0) {
13338103Sbostic 	error("non-positive repetition count");
13438103Sbostic     } else {
13538103Sbostic 	newaddr = addr;
13638103Sbostic 	for (i = 0; i < count; i++) {
13738103Sbostic 	    newaddr = printop(newaddr);
13838103Sbostic 	}
13938103Sbostic 	prtaddr = newaddr;
14038103Sbostic     }
14138103Sbostic }
14238103Sbostic 
14338103Sbostic /*
14438103Sbostic  * Print the contents of the addresses within the given range
14538103Sbostic  * according to the given format.
14638103Sbostic  */
14738103Sbostic 
14838103Sbostic typedef struct {
14938103Sbostic     String name;
15038103Sbostic     String printfstring;
15138103Sbostic     int length;
15238103Sbostic } Format;
15338103Sbostic 
15438103Sbostic private Format fmt[] = {
15538103Sbostic     { "d", " %d", sizeof(short) },
15638103Sbostic     { "D", " %ld", sizeof(long) },
15738103Sbostic     { "o", " %o", sizeof(short) },
15838103Sbostic     { "O", " %lo", sizeof(long) },
15938103Sbostic     { "x", " %04x", sizeof(short) },
16038103Sbostic     { "X", " %08x", sizeof(long) },
16138103Sbostic     { "b", " \\%o", sizeof(char) },
16238103Sbostic     { "c", " '%c'", sizeof(char) },
16338103Sbostic     { "s", "%c", sizeof(char) },
16438103Sbostic     { "f", " %f", sizeof(float) },
16538103Sbostic     { "g", " %g", sizeof(double) },
16638103Sbostic     { nil, nil, 0 }
16738103Sbostic };
16838103Sbostic 
findformat(s)16938103Sbostic private Format *findformat(s)
17038103Sbostic String s;
17138103Sbostic {
17238103Sbostic     register Format *f;
17338103Sbostic 
17438103Sbostic     f = &fmt[0];
17538103Sbostic     while (f->name != nil and not streq(f->name, s)) {
17638103Sbostic 	++f;
17738103Sbostic     }
17838103Sbostic     if (f->name == nil) {
17938103Sbostic 	error("bad print format \"%s\"", s);
18038103Sbostic     }
18138103Sbostic     return f;
18238103Sbostic }
18338103Sbostic 
18438103Sbostic /*
18538103Sbostic  * Retrieve and print out the appropriate data in the given format.
18638103Sbostic  * Floats have to be handled specially to allow the compiler to
18738103Sbostic  * convert them to doubles when passing to printf.
18838103Sbostic  */
18938103Sbostic 
printformat(f,addr)19038103Sbostic private printformat (f, addr)
19138103Sbostic Format *f;
19238103Sbostic Address addr;
19338103Sbostic {
19438103Sbostic     union {
19538103Sbostic 	char charv;
19638103Sbostic 	short shortv;
19738103Sbostic 	int intv;
19838103Sbostic 	float floatv;
19938103Sbostic 	double doublev;
20038103Sbostic     } value;
20138103Sbostic 
20238103Sbostic     value.intv = 0;
20338103Sbostic     dread(&value, addr, f->length);
20438103Sbostic     if (streq(f->name, "f")) {
20538103Sbostic 	printf(f->printfstring, value.floatv);
20638103Sbostic     } else {
20738103Sbostic 	printf(f->printfstring, value);
20838103Sbostic     }
20938103Sbostic }
21038103Sbostic 
printdata(lowaddr,highaddr,format)21138103Sbostic public Address printdata(lowaddr, highaddr, format)
21238103Sbostic Address lowaddr;
21338103Sbostic Address highaddr;
21438103Sbostic String format;
21538103Sbostic {
21638103Sbostic     int n;
21738103Sbostic     register Address addr;
21838103Sbostic     Format *f;
21938103Sbostic 
22038103Sbostic     if (lowaddr > highaddr) {
22138103Sbostic 	error("first address larger than second");
22238103Sbostic     }
22338103Sbostic     f = findformat(format);
22438103Sbostic     n = 0;
22538103Sbostic     for (addr = lowaddr; addr <= highaddr; addr += f->length) {
22638103Sbostic 	if (n == 0) {
22738103Sbostic 	    printf("%08x: ", addr);
22838103Sbostic 	}
22938103Sbostic 	printformat(f, addr);
23038103Sbostic 	++n;
23138103Sbostic 	if (n >= (16 div f->length)) {
23238103Sbostic 	    printf("\n");
23338103Sbostic 	    n = 0;
23438103Sbostic 	}
23538103Sbostic     }
23638103Sbostic     if (n != 0) {
23738103Sbostic 	printf("\n");
23838103Sbostic     }
23938103Sbostic     prtaddr = addr;
24038103Sbostic     return addr;
24138103Sbostic }
24238103Sbostic 
24338103Sbostic /*
24438103Sbostic  * The other approach is to print n items starting with a given address.
24538103Sbostic  */
24638103Sbostic 
printndata(count,startaddr,format)24738103Sbostic public printndata(count, startaddr, format)
24838103Sbostic int count;
24938103Sbostic Address startaddr;
25038103Sbostic String format;
25138103Sbostic {
25238103Sbostic     int i, n;
25338103Sbostic     Address addr;
25438103Sbostic     Format *f;
25538103Sbostic     Boolean isstring;
25638103Sbostic     char c;
25738103Sbostic 
25838103Sbostic     if (count <= 0) {
25938103Sbostic 	error("non-positive repetition count");
26038103Sbostic     }
26138103Sbostic     f = findformat(format);
26238103Sbostic     isstring = (Boolean) streq(f->name, "s");
26338103Sbostic     n = 0;
26438103Sbostic     addr = startaddr;
26538103Sbostic     for (i = 0; i < count; i++) {
26638103Sbostic 	if (n == 0) {
26738103Sbostic 	    printf("%08x: ", addr);
26838103Sbostic 	}
26938103Sbostic 	if (isstring) {
27038103Sbostic 	    printf("\"");
27138103Sbostic 	    dread(&c, addr, sizeof(char));
27238103Sbostic 	    while (c != '\0') {
27338103Sbostic 		printchar(c);
27438103Sbostic 		++addr;
27538103Sbostic 		dread(&c, addr, sizeof(char));
27638103Sbostic 	    }
27738103Sbostic 	    printf("\"\n");
27838103Sbostic 	    n = 0;
27938103Sbostic 	    addr += sizeof(String);
28038103Sbostic 	} else {
28138103Sbostic 	    printformat(f, addr);
28238103Sbostic 	    ++n;
28338103Sbostic 	    if (n >= (16 div f->length)) {
28438103Sbostic 		printf("\n");
28538103Sbostic 		n = 0;
28638103Sbostic 	    }
28738103Sbostic 	    addr += f->length;
28838103Sbostic 	}
28938103Sbostic     }
29038103Sbostic     if (n != 0) {
29138103Sbostic 	printf("\n");
29238103Sbostic     }
29338103Sbostic     prtaddr = addr;
29438103Sbostic }
29538103Sbostic 
29638103Sbostic /*
29738103Sbostic  * Print out a value according to the given format.
29838103Sbostic  */
29938103Sbostic 
printvalue(v,format)30038103Sbostic public printvalue(v, format)
30138103Sbostic long v;
30238103Sbostic String format;
30338103Sbostic {
30438103Sbostic     Format *f;
30538103Sbostic     char *p, *q;
30638103Sbostic 
30738103Sbostic     f = findformat(format);
30838103Sbostic     if (streq(f->name, "s")) {
30938103Sbostic 	putchar('"');
31038103Sbostic 	p = (char *) &v;
31138103Sbostic 	q = p + sizeof(v);
31238103Sbostic 	while (p < q) {
31338103Sbostic 	    printchar(*p);
31438103Sbostic 	    ++p;
31538103Sbostic 	}
31638103Sbostic 	putchar('"');
31738103Sbostic     } else {
31838103Sbostic 	printf(f->printfstring, v);
31938103Sbostic     }
32038103Sbostic     putchar('\n');
32138103Sbostic }
32238103Sbostic 
32338103Sbostic /*
32438103Sbostic  * Print out an execution time error.
32538103Sbostic  * Assumes the source position of the error has been calculated.
32638103Sbostic  *
32738103Sbostic  * Have to check if the -r option was specified; if so then
32838103Sbostic  * the object file information hasn't been read in yet.
32938103Sbostic  */
33038103Sbostic 
printerror()33138103Sbostic public printerror()
33238103Sbostic {
33338103Sbostic     extern Integer sys_nsig;
33438103Sbostic     extern String sys_siglist[];
33538103Sbostic     integer err;
33638103Sbostic 
33738103Sbostic     if (isfinished(process)) {
33838103Sbostic 	err = exitcode(process);
33938103Sbostic 	if (err == 0) {
34038103Sbostic 	    printf("\"%s\" terminated normally\n", objname);
34138103Sbostic 	} else {
34238103Sbostic 	    printf("\"%s\" terminated abnormally (exit code %d)\n",
34338103Sbostic 		objname, err
34438103Sbostic 	    );
34538103Sbostic 	}
34638103Sbostic 	erecover();
34738103Sbostic     }
34838103Sbostic     err = errnum(process);
34938103Sbostic     putchar('\n');
35038103Sbostic     printsig(err);
35138103Sbostic     putchar(' ');
35238103Sbostic     printloc();
35338103Sbostic     putchar('\n');
35438103Sbostic     if (curline > 0) {
35538103Sbostic 	printlines(curline, curline);
35638103Sbostic     } else {
35738103Sbostic 	printinst(pc, pc);
35838103Sbostic     }
35938103Sbostic     erecover();
36038103Sbostic }
36138103Sbostic 
36238103Sbostic /*
36338103Sbostic  * Print out a signal.
36438103Sbostic  */
36538103Sbostic 
36638103Sbostic private String illinames[] = {
36738103Sbostic     "reserved addressing fault",
36838103Sbostic     "privileged instruction fault",
36938103Sbostic     "reserved operand fault"
37038103Sbostic };
37138103Sbostic 
37238103Sbostic private String fpenames[] = {
37338103Sbostic     nil,
37438103Sbostic     "integer overflow trap",
37538103Sbostic     "integer divide by zero trap",
37638103Sbostic     "floating overflow trap",
37738103Sbostic     "floating/decimal divide by zero trap",
37838103Sbostic     "floating underflow trap",
37938103Sbostic     "decimal overflow trap",
38038103Sbostic     "subscript out of range trap",
38138103Sbostic     "floating overflow fault",
38238103Sbostic     "floating divide by zero fault",
38338103Sbostic     "floating underflow fault"
38438103Sbostic };
38538103Sbostic 
printsig(signo)38638103Sbostic public printsig (signo)
38738103Sbostic integer signo;
38838103Sbostic {
38938103Sbostic     integer code;
39038103Sbostic 
39138103Sbostic     if (signo < 0 or signo > sys_nsig) {
39238103Sbostic 	printf("[signal %d]", signo);
39338103Sbostic     } else {
39438103Sbostic 	printf("%s", sys_siglist[signo]);
39538103Sbostic     }
39638103Sbostic     code = errcode(process);
39738103Sbostic     if (signo == SIGILL) {
39838103Sbostic 	if (code >= 0 and code < sizeof(illinames) / sizeof(illinames[0])) {
39938103Sbostic 	    printf(" (%s)", illinames[code]);
40038103Sbostic 	}
40138103Sbostic     } else if (signo == SIGFPE) {
40238103Sbostic 	if (code > 0 and code < sizeof(fpenames) / sizeof(fpenames[0])) {
40338103Sbostic 	    printf(" (%s)", fpenames[code]);
40438103Sbostic 	}
40538103Sbostic     }
40638103Sbostic }
40738103Sbostic 
40838103Sbostic /*
40938103Sbostic  * Note the termination of the program.  We do this so as to avoid
41038103Sbostic  * having the process exit, which would make the values of variables
41138103Sbostic  * inaccessible.  We do want to flush all output buffers here,
41238103Sbostic  * otherwise it'll never get done.
41338103Sbostic  */
41438103Sbostic 
endprogram()41538103Sbostic public endprogram()
41638103Sbostic {
41738103Sbostic     Integer exitcode;
41838103Sbostic 
41938103Sbostic     stepto(nextaddr(pc, true));
42038103Sbostic     printnews();
42138103Sbostic     exitcode = argn(1, nil);
42238103Sbostic     if (exitcode != 0) {
42338103Sbostic 	printf("\nexecution completed (exit code %d)\n", exitcode);
42438103Sbostic     } else {
42538103Sbostic 	printf("\nexecution completed\n");
42638103Sbostic     }
42738103Sbostic     getsrcpos();
42838103Sbostic     erecover();
42938103Sbostic }
43038103Sbostic 
43138103Sbostic /*
43238103Sbostic  * Single step the machine a source line (or instruction if "inst_tracing"
43338103Sbostic  * is true).  If "isnext" is true, skip over procedure calls.
43438103Sbostic  */
43538103Sbostic 
43638103Sbostic private Address getcall();
43738103Sbostic 
dostep(isnext)43838103Sbostic public dostep(isnext)
43938103Sbostic Boolean isnext;
44038103Sbostic {
44138103Sbostic     register Address addr;
44238103Sbostic     register Lineno line;
44338103Sbostic     String filename;
44438103Sbostic     Address startaddr;
44538103Sbostic 
44638103Sbostic     startaddr = pc;
44738103Sbostic     addr = nextaddr(pc, isnext);
44838103Sbostic     if (not inst_tracing and nlhdr.nlines != 0) {
44938103Sbostic 	line = linelookup(addr);
45038103Sbostic 	while (line == 0) {
45138103Sbostic 	    addr = nextaddr(addr, isnext);
45238103Sbostic 	    line = linelookup(addr);
45338103Sbostic 	}
45438103Sbostic 	curline = line;
45538103Sbostic     } else {
45638103Sbostic 	curline = 0;
45738103Sbostic     }
45838103Sbostic     stepto(addr);
45938103Sbostic     filename = srcfilename(addr);
46038103Sbostic     setsource(filename);
46138103Sbostic }
46238103Sbostic 
46338103Sbostic typedef short Bpinst;
46438103Sbostic 
46538103Sbostic extern Bpinst BP_OP;
46638103Sbostic #ifdef sun
46738103Sbostic 	asm("_BP_OP: trap #15");
46838103Sbostic #else /* IRIS */
46938103Sbostic 	asm("_BP_OP: trap #1");
47038103Sbostic #endif
47138103Sbostic 
47238103Sbostic #define BP_ERRNO    SIGTRAP     /* signal received at a breakpoint */
47338103Sbostic 
47438103Sbostic /*
47538103Sbostic  * Setting a breakpoint at a location consists of saving
47638103Sbostic  * the word at the location and poking a BP_OP there.
47738103Sbostic  *
47838103Sbostic  * We save the locations and words on a list for use in unsetting.
47938103Sbostic  */
48038103Sbostic 
48138103Sbostic typedef struct Savelist *Savelist;
48238103Sbostic 
48338103Sbostic struct Savelist {
48438103Sbostic     Address location;
48538103Sbostic     Bpinst save;
48638103Sbostic     short refcount;
48738103Sbostic     Savelist link;
48838103Sbostic };
48938103Sbostic 
49038103Sbostic private Savelist savelist;
49138103Sbostic 
49238103Sbostic /*
49338103Sbostic  * Set a breakpoint at the given address.  Only save the word there
49438103Sbostic  * if it's not already a breakpoint.
49538103Sbostic  */
49638103Sbostic 
setbp(addr)49738103Sbostic public setbp(addr)
49838103Sbostic Address addr;
49938103Sbostic {
50038103Sbostic     Bpinst w, save;
50138103Sbostic     register Savelist newsave, s;
50238103Sbostic 
50338103Sbostic     for (s = savelist; s != nil; s = s->link) {
50438103Sbostic 	if (s->location == addr) {
50538103Sbostic 	    s->refcount++;
50638103Sbostic 	    return;
50738103Sbostic 	}
50838103Sbostic     }
50938103Sbostic     iread(&save, addr, sizeof(save));
51038103Sbostic     newsave = new(Savelist);
51138103Sbostic     newsave->location = addr;
51238103Sbostic     newsave->save = save;
51338103Sbostic     newsave->refcount = 1;
51438103Sbostic     newsave->link = savelist;
51538103Sbostic     savelist = newsave;
51638103Sbostic     w = BP_OP;
51738103Sbostic     iwrite(&w, addr, sizeof(w));
51838103Sbostic }
51938103Sbostic 
52038103Sbostic /*
52138103Sbostic  * Unset a breakpoint; unfortunately we have to search the SAVELIST
52238103Sbostic  * to find the saved value.  The assumption is that the SAVELIST will
52338103Sbostic  * usually be quite small.
52438103Sbostic  */
52538103Sbostic 
unsetbp(addr)52638103Sbostic public unsetbp(addr)
52738103Sbostic Address addr;
52838103Sbostic {
52938103Sbostic     register Savelist s, prev;
53038103Sbostic 
53138103Sbostic     prev = nil;
53238103Sbostic     for (s = savelist; s != nil; s = s->link) {
53338103Sbostic 	if (s->location == addr) {
53438103Sbostic 	    iwrite(&s->save, addr, sizeof(s->save));
53538103Sbostic 	    s->refcount--;
53638103Sbostic 	    if (s->refcount == 0) {
53738103Sbostic 		if (prev == nil) {
53838103Sbostic 		    savelist = s->link;
53938103Sbostic 		} else {
54038103Sbostic 		    prev->link = s->link;
54138103Sbostic 		}
54238103Sbostic 		dispose(s);
54338103Sbostic 	    }
54438103Sbostic 	    return;
54538103Sbostic 	}
54638103Sbostic 	prev = s;
54738103Sbostic     }
54838103Sbostic     panic("unsetbp: couldn't find address %d", addr);
54938103Sbostic }
55038103Sbostic 
55138103Sbostic /*
55238103Sbostic  * Instruction decoding routines for 68000, derived from adb.
55338103Sbostic  *
55438103Sbostic  * The shared boolean variable "printing" is true if the decoded
55538103Sbostic  * instruction is to be printed, false if not.  In either case,
55638103Sbostic  * the address of the next instruction after the given one is returned.
55738103Sbostic  */
55838103Sbostic 
55938103Sbostic private Boolean printing;
56038103Sbostic private Boolean following;
56138103Sbostic private Boolean followcalls;
56238103Sbostic private Address instaddr;
56338103Sbostic 
56438103Sbostic #define instread(var) \
56538103Sbostic { \
56638103Sbostic     iread(&var, instaddr, sizeof(var)); \
56738103Sbostic     instaddr += sizeof(var); \
56838103Sbostic }
56938103Sbostic 
decode(inst,addr)57038103Sbostic private Optab *decode(inst, addr)
57138103Sbostic Word inst;
57238103Sbostic Address addr;
57338103Sbostic {
57438103Sbostic     register Optab *o;
57538103Sbostic 
57638103Sbostic     o = &optab[0];
57738103Sbostic     while (o->mask != 0 and (inst&o->mask) != o->match) {
57838103Sbostic 	++o;
57938103Sbostic     }
58038103Sbostic     return o;
58138103Sbostic }
58238103Sbostic 
printop(addr)58338103Sbostic private Address printop(addr)
58438103Sbostic Address addr;
58538103Sbostic {
58638103Sbostic     Optab *o;
58738103Sbostic     short inst;
58838103Sbostic 
58938103Sbostic     printf("%08x  ", addr);
59038103Sbostic     iread(&inst, addr, sizeof(inst));
59138103Sbostic     o = decode(inst, addr);
59238103Sbostic     if (o->mask == 0) {
59338103Sbostic 	printf("\tbadop");
59438103Sbostic 	instaddr = addr + sizeof(inst);
59538103Sbostic     } else {
59638103Sbostic 	printing = true;
59738103Sbostic 	following = false;
59838103Sbostic 	instaddr = addr + sizeof(inst);
59938103Sbostic 	(*o->opfun)(inst, o->farg);
60038103Sbostic 	printing = false;
60138103Sbostic     }
60238103Sbostic     printf("\n");
60338103Sbostic     return instaddr;
60438103Sbostic }
60538103Sbostic 
60638103Sbostic /*
60738103Sbostic  * Quickly find the return address of the current procedure or function
60838103Sbostic  * while single stepping.  Just get the word pointed at by sp.
60938103Sbostic  */
61038103Sbostic 
currtnaddr()61138103Sbostic private Address currtnaddr ()
61238103Sbostic {
61338103Sbostic     Address retaddr;
61438103Sbostic 
61538103Sbostic     dread(&retaddr, reg(STKP), sizeof(retaddr));
61638103Sbostic     return retaddr;
61738103Sbostic }
61838103Sbostic 
61938103Sbostic /*
62038103Sbostic  * Print out the effective address for the given parameters.
62138103Sbostic  */
62238103Sbostic 
printea(mode,reg,size)62338103Sbostic private printea(mode, reg, size)
62438103Sbostic long mode, reg;
62538103Sbostic int size;
62638103Sbostic {
62738103Sbostic     long index, disp;
62838103Sbostic     static char *aregs[] = { "a0", "a1", "a2", "a3", "a4", "a5", "a6", "sp" };
62938103Sbostic     Byte b;
63038103Sbostic     short w;
63138103Sbostic     long l;
63238103Sbostic 
63338103Sbostic     switch ((int)(mode)) {
63438103Sbostic 	case 0:
63538103Sbostic 	    if (printing) {
63638103Sbostic 		printf("d%D", reg);
63738103Sbostic 	    }
63838103Sbostic 	    break;
63938103Sbostic 
64038103Sbostic 	case 1:
64138103Sbostic 	    if (printing) {
64238103Sbostic 		printf("%s", aregs[reg]);
64338103Sbostic 	    }
64438103Sbostic 	    break;
64538103Sbostic 
64638103Sbostic 	case 2:
64738103Sbostic 	    if (printing) {
64838103Sbostic 		printf("%s@", aregs[reg]);
64938103Sbostic 	    }
65038103Sbostic 	    break;
65138103Sbostic 
65238103Sbostic 	case 3:
65338103Sbostic 	    if (printing) {
65438103Sbostic 		printf("%s@+", aregs[reg]);
65538103Sbostic 	    }
65638103Sbostic 	    break;
65738103Sbostic 
65838103Sbostic 	case 4:
65938103Sbostic 	    if (printing) {
66038103Sbostic 		printf("%s@-", aregs[reg]);
66138103Sbostic 	    }
66238103Sbostic 	    break;
66338103Sbostic 
66438103Sbostic 	case 5:
66538103Sbostic 	    instread(w);
66638103Sbostic 	    if (printing) {
66738103Sbostic 		printf("%s@(%D)", aregs[reg], w);
66838103Sbostic 	    }
66938103Sbostic 	    break;
67038103Sbostic 
67138103Sbostic 	case 6:
67238103Sbostic 	    instread(w);
67338103Sbostic 	    if (printing) {
67438103Sbostic 		index = w;
67538103Sbostic 		disp = (char)(index&0377);
67638103Sbostic 		printf("%s@(%d,%c%D:%c)", aregs[reg], disp,
67738103Sbostic 		    (index&0100000)?'a':'d',(index>>12)&07,
67838103Sbostic 		    (index&04000)?'l':'w');
67938103Sbostic 	    }
68038103Sbostic 	    break;
68138103Sbostic 
68238103Sbostic 	case 7:
68338103Sbostic 	    switch ((int)(reg)) {
68438103Sbostic 		case 0:
68538103Sbostic 		    instread(w);
68638103Sbostic 		    if (printing) {
68738103Sbostic 			index = w;
68838103Sbostic 			psymoff(index);
68938103Sbostic 		    }
69038103Sbostic 		    break;
69138103Sbostic 
69238103Sbostic 		case 1:
69338103Sbostic 		    instread(l);
69438103Sbostic 		    if (printing) {
69538103Sbostic 			index = l;
69638103Sbostic 			psymoff(index);
69738103Sbostic 		    }
69838103Sbostic 		    break;
69938103Sbostic 
70038103Sbostic 		case 2:
70138103Sbostic 		    instread(w);
70238103Sbostic 		    if (printing) {
70338103Sbostic 			disp = w;
70438103Sbostic 			psymoff(disp + instaddr);
70538103Sbostic 		    }
70638103Sbostic 		    break;
70738103Sbostic 
70838103Sbostic 		case 3:
70938103Sbostic 		    instread(w);
71038103Sbostic 		    if (printing) {
71138103Sbostic 			index = w;
71238103Sbostic 			disp = (char)(index&0377);
71338103Sbostic 			printf("pc@(%D,%c%D:%c)", disp,
71438103Sbostic 			    (index&0100000)?'a':'d',(index>>12)&07,
71538103Sbostic 			    (index&04000)?'l':'w');
71638103Sbostic 		    }
71738103Sbostic 		    break;
71838103Sbostic 
71938103Sbostic 		case 4:
72038103Sbostic 		    switch (size) {
72138103Sbostic 			case sizeof(b):
72238103Sbostic 			    instread(w);
72338103Sbostic 			    index = (w&0xff);
72438103Sbostic 			    break;
72538103Sbostic 
72638103Sbostic 			case sizeof(w):
72738103Sbostic 			    instread(w);
72838103Sbostic 			    index = w;
72938103Sbostic 			    break;
73038103Sbostic 
73138103Sbostic 			case sizeof(l):
73238103Sbostic 			    instread(l);
73338103Sbostic 			    index = l;
73438103Sbostic 			    break;
73538103Sbostic 
73638103Sbostic 			default:
73738103Sbostic 			    if (printing) {
73838103Sbostic 			    	printf("unexpected size %d in printea\n", size);
73938103Sbostic 			    }
74038103Sbostic 			    instread(l);
74138103Sbostic 			    index = l;
74238103Sbostic 			    break;
74338103Sbostic 		    }
74438103Sbostic 		    if (printing) {
74538103Sbostic 			printf(IMDF, index);
74638103Sbostic 		    }
74738103Sbostic 		    break;
74838103Sbostic 
74938103Sbostic 		default:
75038103Sbostic 		    if (printing) {
75138103Sbostic 			printf("???");
75238103Sbostic 		    }
75338103Sbostic 		    break;
75438103Sbostic 	    }
75538103Sbostic 	    break;
75638103Sbostic 
75738103Sbostic 	default:
75838103Sbostic 	    if (printing) {
75938103Sbostic 		printf("???");
76038103Sbostic 	    }
76138103Sbostic 	    break;
76238103Sbostic     }
76338103Sbostic }
76438103Sbostic 
printEA(ea,size)76538103Sbostic private printEA(ea, size)
76638103Sbostic long ea;
76738103Sbostic int size;
76838103Sbostic {
76938103Sbostic     printea((ea>>3)&07, ea&07, size);
77038103Sbostic }
77138103Sbostic 
mapsize(inst)77238103Sbostic private mapsize(inst)
77338103Sbostic register long inst;
77438103Sbostic {
77538103Sbostic     int m;
77638103Sbostic 
77738103Sbostic     inst >>= 6;
77838103Sbostic     inst &= 03;
77938103Sbostic     switch (inst) {
78038103Sbostic 	case 0:
78138103Sbostic 	    m = 1;
78238103Sbostic 	    break;
78338103Sbostic 
78438103Sbostic 	case 1:
78538103Sbostic 	    m = 2;
78638103Sbostic 	    break;
78738103Sbostic 
78838103Sbostic 	case 2:
78938103Sbostic 	    m = 4;
79038103Sbostic 	    break;
79138103Sbostic 
79238103Sbostic 	default:
79338103Sbostic 	    m = -1;
79438103Sbostic 	    break;
79538103Sbostic     }
79638103Sbostic     return m;
79738103Sbostic }
79838103Sbostic 
suffix(size)79938103Sbostic private char suffix(size)
80038103Sbostic int size;
80138103Sbostic {
80238103Sbostic     char c;
80338103Sbostic 
80438103Sbostic     switch (size) {
80538103Sbostic 	case 1:
80638103Sbostic 	    c = 'b';
80738103Sbostic 	    break;
80838103Sbostic 
80938103Sbostic 	case 2:
81038103Sbostic 	    c = 'w';
81138103Sbostic 	    break;
81238103Sbostic 
81338103Sbostic 	case 4:
81438103Sbostic 	    c = 'l';
81538103Sbostic 	    break;
81638103Sbostic 
81738103Sbostic 	default:
81838103Sbostic 	    panic("bad size %d in suffix", size);
81938103Sbostic     }
82038103Sbostic     return c;
82138103Sbostic }
82238103Sbostic 
82338103Sbostic /*
82438103Sbostic  * Print an address offset.  Eventually this should attempt to be symbolic,
82538103Sbostic  * but for now its just printed in hex.
82638103Sbostic  */
82738103Sbostic 
psymoff(off)82838103Sbostic private psymoff (off)
82938103Sbostic Word off;
83038103Sbostic {
83138103Sbostic     Symbol f;
83238103Sbostic 
83338103Sbostic     f = whatblock((Address) (off + FUNCOFFSET));
83438103Sbostic     if (codeloc(f) == off + FUNCOFFSET) {
83538103Sbostic 	printf("%s", symname(f));
83638103Sbostic     } else {
83738103Sbostic 	printf("0x%x", off);
83838103Sbostic     }
83938103Sbostic }
84038103Sbostic 
84138103Sbostic /*
84238103Sbostic  * Instruction class specific routines.
84338103Sbostic  */
84438103Sbostic 
omove(inst,s)84538103Sbostic public omove(inst, s)
84638103Sbostic long inst;
84738103Sbostic String s;
84838103Sbostic {
84938103Sbostic     register int c;
85038103Sbostic     int size;
85138103Sbostic 
85238103Sbostic     c = s[0];
85338103Sbostic     if (printing) {
85438103Sbostic 	printf("\tmov%c\t", c);
85538103Sbostic     }
85638103Sbostic     size = ((c == 'b') ? 1 : (c == 'w') ? 2 : 4);
85738103Sbostic     printea((inst>>3)&07, inst&07, size);
85838103Sbostic     if (printing) {
85938103Sbostic 	printf(",");
86038103Sbostic     }
86138103Sbostic     printea((inst>>6)&07, (inst>>9)&07, size);
86238103Sbostic }
86338103Sbostic 
86438103Sbostic /*
86538103Sbostic  * Two types: bsr (4 bytes) and bsrs (2 bytes)
86638103Sbostic  */
86738103Sbostic 
obranch(inst,dummy)86838103Sbostic public obranch(inst, dummy)
86938103Sbostic long inst;
87038103Sbostic {
87138103Sbostic     long disp;
87238103Sbostic     String s;
87338103Sbostic     short w;
87438103Sbostic     Address startingaddr;	/* address of branch instruction */
87538103Sbostic     int branchtype;		/* type of branch (0 = unconditional) */
87638103Sbostic     Address dest;
87738103Sbostic     Address retaddr;		/* for bsr instruction */
87838103Sbostic 
87938103Sbostic     startingaddr = instaddr - 2;
88038103Sbostic     disp = inst&0377;
88138103Sbostic     s = "s ";
88238103Sbostic     if (disp == 0) {
88338103Sbostic 	retaddr = startingaddr + 4;
88438103Sbostic     } else {
88538103Sbostic 	retaddr = startingaddr + 2;
88638103Sbostic     }
88738103Sbostic     if (disp > 127) {
88838103Sbostic 	disp |= ~0377;
88938103Sbostic     } else if (disp == 0){
89038103Sbostic 	s = " ";
89138103Sbostic 	instread(w);
89238103Sbostic 	disp = w;
89338103Sbostic     }
89438103Sbostic     branchtype = (int)((inst>>8)&017);
89538103Sbostic     dest = startingaddr + 2 + disp;
89638103Sbostic     if (printing) {
89738103Sbostic 	printf("\tb%s%s\t", bname[branchtype], s);
89838103Sbostic 	psymoff(dest);
89938103Sbostic     }
90038103Sbostic     if (following) {
90138103Sbostic 	/*
90238103Sbostic 	 * If we're to follow the dynamic flow of instructions,
90338103Sbostic 	 * we must see where the branch leads.  A branchtype of 0
90438103Sbostic 	 * indicates an unconditional branch which we simply take
90538103Sbostic 	 * as the new instruction address.  For a conditional branch,
90638103Sbostic 	 * we continue execution up to the current address, single step,
90738103Sbostic 	 * and keep going.
90838103Sbostic 	 */
90938103Sbostic 	if (branchtype == 0) {
91038103Sbostic 	    instaddr = dest;
91138103Sbostic 	} else if (branchtype == 01) {		/* bsr */
91238103Sbostic 	    if (followcalls) {
91338103Sbostic 		steppast(startingaddr);
91438103Sbostic 		curfunc = whatblock(pc, true);
91538103Sbostic 		if (not isbperr()) {
91638103Sbostic 		    printstatus();
91738103Sbostic 		    /* NOTREACHED */
91838103Sbostic 		}
91938103Sbostic 		bpact();
92038103Sbostic 		if (nosource(curfunc) and canskip(curfunc) and
92138103Sbostic 		  nlhdr.nlines != 0) {
92238103Sbostic 		    stepto(retaddr);
92338103Sbostic 		    instaddr = pc;
92438103Sbostic 		    bpact();
92538103Sbostic 		} else {
92638103Sbostic 		    callnews(/* iscall = */ true);
92738103Sbostic 		}
92838103Sbostic 	    }
92938103Sbostic 	} else {
93038103Sbostic 	    steppast(startingaddr);
93138103Sbostic 	}
93238103Sbostic     }
93338103Sbostic }
93438103Sbostic 
odbcc(inst,form)93538103Sbostic public odbcc(inst, form)
93638103Sbostic long inst;
93738103Sbostic String form;
93838103Sbostic {
93938103Sbostic     long disp;
94038103Sbostic     short w;
94138103Sbostic 
94238103Sbostic     instread(w);
94338103Sbostic     if (printing) {
94438103Sbostic     	printf(form, dbname[(int)((inst>>8)&017)], inst&07);
94538103Sbostic 	psymoff(w + sizeof(w));
94638103Sbostic     }
94738103Sbostic }
94838103Sbostic 
oscc(inst,dummy)94938103Sbostic public oscc(inst, dummy)
95038103Sbostic long inst;
95138103Sbostic long dummy;
95238103Sbostic {
95338103Sbostic     if (printing) {
95438103Sbostic 	printf("\ts%s\t", cname[(int)((inst>>8)&017)]);
95538103Sbostic     }
95638103Sbostic     printea((inst>>3)&07, inst&07, 1);
95738103Sbostic }
95838103Sbostic 
biti(inst,dummy)95938103Sbostic public biti(inst, dummy)
96038103Sbostic long inst;
96138103Sbostic long dummy;
96238103Sbostic {
96338103Sbostic     short w;
96438103Sbostic 
96538103Sbostic     if (printing) {
96638103Sbostic 	printf("\t%s\t", bit[(int)((inst>>6)&03)]);
96738103Sbostic     }
96838103Sbostic     if (inst&0x0100) {
96938103Sbostic 	if (printing) {
97038103Sbostic 	    printf("d%D,", inst>>9);
97138103Sbostic 	}
97238103Sbostic     } else {
97338103Sbostic 	instread(w);
97438103Sbostic 	if (printing) {
97538103Sbostic 	    printf(IMDF, w);
97638103Sbostic 	    printf(",");
97738103Sbostic 	}
97838103Sbostic     }
97938103Sbostic     printEA(inst);
98038103Sbostic }
98138103Sbostic 
opmode(inst,opcode)98238103Sbostic public opmode(inst, opcode)
98338103Sbostic long inst;
98438103Sbostic long opcode;
98538103Sbostic {
98638103Sbostic     register int opmode;
98738103Sbostic     register int reg;
98838103Sbostic     int size;
98938103Sbostic 
99038103Sbostic     opmode = (int)((inst>>6) & 07);
99138103Sbostic     reg = (int)((inst>>9) & 07);
99238103Sbostic     if (opmode == 0 or opmode == 4) {
99338103Sbostic 	size = 1;
99438103Sbostic     } else if (opmode == 1 or opmode == 3 or opmode == 5) {
99538103Sbostic 	size = 2;
99638103Sbostic     } else {
99738103Sbostic 	size = 4;
99838103Sbostic     }
99938103Sbostic     if (printing) {
100038103Sbostic 	printf("\t%s%c\t", opcode, suffix(size));
100138103Sbostic     }
100238103Sbostic     if (opmode >= 4 and opmode <= 6) {
100338103Sbostic 	if (printing) {
100438103Sbostic 	    printf("d%d,", reg);
100538103Sbostic 	}
100638103Sbostic 	printea((inst>>3)&07, inst&07, size);
100738103Sbostic     } else {
100838103Sbostic 	printea((inst>>3)&07, inst&07, size);
100938103Sbostic 	if (printing) {
101038103Sbostic 	    printf(",%c%d",(opmode<=2) ? 'd' : 'a', reg);
101138103Sbostic 	}
101238103Sbostic     }
101338103Sbostic }
101438103Sbostic 
shroi(inst,ds)101538103Sbostic public shroi(inst, ds)
101638103Sbostic long inst;
101738103Sbostic String ds;
101838103Sbostic {
101938103Sbostic     int rx, ry;
102038103Sbostic     String opcode;
102138103Sbostic 
102238103Sbostic     if ((inst & 0xC0) == 0xC0) {
102338103Sbostic 	opcode = shro[(int)((inst>>9)&03)];
102438103Sbostic 	if (printing) {
102538103Sbostic 	    printf("\t%s%s\t", opcode, ds);
102638103Sbostic 	}
102738103Sbostic 	printEA(inst);
102838103Sbostic     } else {
102938103Sbostic 	if (printing) {
103038103Sbostic 	    opcode = shro[(int)((inst>>3)&03)];
103138103Sbostic 	    printf("\t%s%s%c\t", opcode, ds, suffix(mapsize(inst)));
103238103Sbostic 	    rx = (int)((inst>>9)&07); ry = (int)(inst&07);
103338103Sbostic 	    if ((inst>>5)&01) {
103438103Sbostic 		printf("d%d,d%d", rx, ry);
103538103Sbostic 	    } else {
103638103Sbostic 		printf(IMDF, (rx ? rx : 8));
103738103Sbostic 		printf(",d%d", ry);
103838103Sbostic 	    }
103938103Sbostic 	}
104038103Sbostic     }
104138103Sbostic }
104238103Sbostic 
oimmed(inst,opcode)104338103Sbostic public oimmed(inst, opcode)
104438103Sbostic long inst;
104538103Sbostic register String opcode;
104638103Sbostic {
104738103Sbostic     register int size;
104838103Sbostic     long const;
104938103Sbostic     short w;
105038103Sbostic 
105138103Sbostic     size = mapsize(inst);
105238103Sbostic     if (size > 0) {
105338103Sbostic 	if (size == 4) {
105438103Sbostic 	    instread(const);
105538103Sbostic 	} else {
105638103Sbostic 	    instread(w);
105738103Sbostic 	    const = w;
105838103Sbostic 	}
105938103Sbostic 	if (printing) {
106038103Sbostic 	    printf("\t%s%c\t", opcode, suffix(size));
106138103Sbostic 	    printf(IMDF, const);
106238103Sbostic 	    printf(",");
106338103Sbostic 	}
106438103Sbostic 	printEA(inst, size);
106538103Sbostic     } else {
106638103Sbostic 	if (printing) {
106738103Sbostic 	    printf("\tbadop");
106838103Sbostic 	}
106938103Sbostic     }
107038103Sbostic }
107138103Sbostic 
oreg(inst,opcode)107238103Sbostic public oreg(inst, opcode)
107338103Sbostic long inst;
107438103Sbostic register String opcode;
107538103Sbostic {
107638103Sbostic     if (printing) {
107738103Sbostic 	printf(opcode, (inst & 07));
107838103Sbostic     }
107938103Sbostic }
108038103Sbostic 
extend(inst,opcode)108138103Sbostic public extend(inst, opcode)
108238103Sbostic long inst;
108338103Sbostic String opcode;
108438103Sbostic {
108538103Sbostic     register int size;
108638103Sbostic     int ry, rx;
108738103Sbostic     char c;
108838103Sbostic 
108938103Sbostic     if (printing) {
109038103Sbostic 	size = mapsize(inst);
109138103Sbostic 	ry = (inst&07);
109238103Sbostic 	rx = ((inst>>9)&07);
109338103Sbostic 	c = ((inst & 0x1000) ? suffix(size) : ' ');
109438103Sbostic 	printf("\t%s%c\t", opcode, c);
109538103Sbostic 	if (opcode[0] == 'e') {
109638103Sbostic 	    if (inst & 0x0080) {
109738103Sbostic 		printf("d%D,a%D", rx, ry);
109838103Sbostic 	    } else if (inst & 0x0008) {
109938103Sbostic 		printf("a%D,a%D", rx, ry);
110038103Sbostic 	    } else {
110138103Sbostic 		printf("d%D,d%D", rx, ry);
110238103Sbostic 	    }
110338103Sbostic 	} else if ((inst & 0xF000) == 0xB000) {
110438103Sbostic 	    printf("a%D@+,a%D@+", ry, rx);
110538103Sbostic 	} else if (inst & 0x8) {
110638103Sbostic 	    printf("a%D@-,a%D@-", ry, rx);
110738103Sbostic 	} else {
110838103Sbostic 	    printf("d%D,d%D", ry, rx);
110938103Sbostic 	}
111038103Sbostic     }
111138103Sbostic }
111238103Sbostic 
olink(inst,dummy)111338103Sbostic public olink(inst, dummy)
111438103Sbostic long inst;
111538103Sbostic long dummy;
111638103Sbostic {
111738103Sbostic     short w;
111838103Sbostic 
111938103Sbostic     instread(w);
112038103Sbostic     if (printing) {
112138103Sbostic 	printf("\tlink\ta%D,", inst&07);
112238103Sbostic 	printf(IMDF, w);
112338103Sbostic     }
112438103Sbostic }
112538103Sbostic 
otrap(inst,dummy)112638103Sbostic public otrap(inst, dummy)
112738103Sbostic long inst;
112838103Sbostic {
112938103Sbostic     if (printing) {
113038103Sbostic 	printf("\ttrap\t");
113138103Sbostic 	printf(IMDF, inst&017);
113238103Sbostic     }
113338103Sbostic }
113438103Sbostic 
oneop(inst,opcode)113538103Sbostic public oneop(inst, opcode)
113638103Sbostic long inst;
113738103Sbostic register String opcode;
113838103Sbostic {
113938103Sbostic     if (printing) {
114038103Sbostic 	printf("\t%s",opcode);
114138103Sbostic     }
114238103Sbostic     printEA(inst);
114338103Sbostic }
114438103Sbostic 
jsrop(inst,opcode)114538103Sbostic public jsrop(inst, opcode)
114638103Sbostic long inst;
114738103Sbostic register String opcode;
114838103Sbostic {
114938103Sbostic     Address startingaddr;	/* beginning of jsr instruction */
115038103Sbostic     Address retaddr; /* can't call return_addr (frame not set up yet) */
115138103Sbostic 
115238103Sbostic     startingaddr = instaddr - 2;
115338103Sbostic     switch ((inst >> 3) & 07) {
115438103Sbostic 	case 2:
115538103Sbostic 	    retaddr = instaddr;		/* two byte instruction */
115638103Sbostic 	    break;
115738103Sbostic 	case 5:
115838103Sbostic 	case 6:
115938103Sbostic 	    retaddr = instaddr + 2;	/* four byte instruction */
116038103Sbostic 	    break;
116138103Sbostic 	case 7:
116238103Sbostic 	default:
116338103Sbostic 	    switch (inst & 07) {
116438103Sbostic 		case 0:
116538103Sbostic 		case 2:
116638103Sbostic 		case 3:
116738103Sbostic 		    retaddr = instaddr + 2;
116838103Sbostic 		    break;
116938103Sbostic 		case 1:
117038103Sbostic 		default:
117138103Sbostic 		    retaddr = instaddr + 4;	/* six byte instruction */
117238103Sbostic 		    break;
117338103Sbostic 	    }
117438103Sbostic 	    break;
117538103Sbostic     }
117638103Sbostic     if (printing) {
117738103Sbostic 	printf("\t%s",opcode);
117838103Sbostic     }
117938103Sbostic     printEA(inst);
118038103Sbostic     if (following and followcalls) {
118138103Sbostic 	steppast(startingaddr);
118238103Sbostic 	curfunc = whatblock(pc, true);
118338103Sbostic 	if (not isbperr()) {
118438103Sbostic 	    printstatus();
118538103Sbostic 	    /* NOTREACHED */
118638103Sbostic 	}
118738103Sbostic 	bpact();
118838103Sbostic 	if (nosource(curfunc) and canskip(curfunc) and nlhdr.nlines != 0) {
118938103Sbostic 	    stepto(retaddr);
119038103Sbostic 	    instaddr = pc;
119138103Sbostic 	    bpact();
119238103Sbostic 	} else {
119338103Sbostic 	    callnews(/* iscall = */ true);
119438103Sbostic 	}
119538103Sbostic     }
119638103Sbostic }
119738103Sbostic 
jmpop(inst,opcode)119838103Sbostic public jmpop(inst, opcode)
119938103Sbostic long inst;
120038103Sbostic register String opcode;
120138103Sbostic {
120238103Sbostic     Address startingaddr;	/* beginning of jump instruction */
120338103Sbostic 
120438103Sbostic     startingaddr = instaddr - 2;
120538103Sbostic     if (printing) {
120638103Sbostic 	printf("\t%s",opcode);
120738103Sbostic     }
120838103Sbostic     printEA(inst);
120938103Sbostic     if (following) {
121038103Sbostic 	steppast(startingaddr);
121138103Sbostic     }
121238103Sbostic }
121338103Sbostic 
pregmask(mask)121438103Sbostic public pregmask(mask)
121538103Sbostic register int mask;
121638103Sbostic {
121738103Sbostic     register int i;
121838103Sbostic     register int flag = 0;
121938103Sbostic 
122038103Sbostic     if (printing) {
122138103Sbostic 	printf("#<");
122238103Sbostic 	for (i=0; i<16; i++) {
122338103Sbostic 	    if (mask&1) {
122438103Sbostic 		if (flag) {
122538103Sbostic 		    printf(",");
122638103Sbostic 		} else {
122738103Sbostic 		    ++flag;
122838103Sbostic 		}
122938103Sbostic 		printf("%c%d",(i<8) ? 'd' : 'a', i&07);
123038103Sbostic 	    }
123138103Sbostic 	    mask >>= 1;
123238103Sbostic 	}
123338103Sbostic 	printf(">");
123438103Sbostic     }
123538103Sbostic }
123638103Sbostic 
omovem(inst,dummy)123738103Sbostic public omovem(inst, dummy)
123838103Sbostic long inst;
123938103Sbostic long dummy;
124038103Sbostic {
124138103Sbostic     register int i, list, mask;
124238103Sbostic     register int reglist;
124338103Sbostic     short w;
124438103Sbostic 
124538103Sbostic     i = 0;
124638103Sbostic     list = 0;
124738103Sbostic     mask = 0100000;
124838103Sbostic     instread(w);
124938103Sbostic     reglist = w;
125038103Sbostic     if ((inst & 070) == 040) {	/* predecrement */
125138103Sbostic 	for (i = 15; i > 0; i -= 2) {
125238103Sbostic 	    list |= ((mask & reglist) >> i);
125338103Sbostic 	    mask >>= 1;
125438103Sbostic 	}
125538103Sbostic 	for (i = 1; i < 16; i += 2) {
125638103Sbostic 	    list |= ((mask & reglist) << i);
125738103Sbostic 	    mask >>= 1;
125838103Sbostic 	}
125938103Sbostic 	reglist = list;
126038103Sbostic     }
126138103Sbostic     if (printing) {
126238103Sbostic 	printf("\tmovem%c\t",(inst&100)?'l':'w');
126338103Sbostic     }
126438103Sbostic     if (inst&02000) {
126538103Sbostic 	printEA(inst);
126638103Sbostic 	if (printing) {
126738103Sbostic 	    printf(",");
126838103Sbostic 	}
126938103Sbostic 	pregmask(reglist);
127038103Sbostic     } else {
127138103Sbostic 	pregmask(reglist);
127238103Sbostic 	if (printing) {
127338103Sbostic 	    printf(",");
127438103Sbostic 	}
127538103Sbostic 	printEA(inst);
127638103Sbostic     }
127738103Sbostic }
127838103Sbostic 
ochk(inst,opcode)127938103Sbostic public ochk(inst, opcode)
128038103Sbostic long inst;
128138103Sbostic register String opcode;
128238103Sbostic {
128338103Sbostic     if (printing) {
128438103Sbostic 	printf("\t%s\t", opcode);
128538103Sbostic     }
128638103Sbostic     printEA(inst, sizeof(Byte));
128738103Sbostic     if (printing) {
128838103Sbostic 	printf(",%c%D", (opcode[0] == 'l') ? 'a' : 'd', (inst>>9)&07);
128938103Sbostic     }
129038103Sbostic }
129138103Sbostic 
soneop(inst,opcode)129238103Sbostic public soneop(inst, opcode)
129338103Sbostic long inst;
129438103Sbostic register String opcode;
129538103Sbostic {
129638103Sbostic     register int size;
129738103Sbostic 
129838103Sbostic     size = mapsize(inst);
129938103Sbostic     if (size > 0) {
130038103Sbostic 	if (printing) {
130138103Sbostic 	    printf("\t%s%c\t", opcode, suffix(size));
130238103Sbostic 	}
130338103Sbostic 	printEA(inst);
130438103Sbostic     } else {
130538103Sbostic 	if (printing) {
130638103Sbostic 	    printf("\tbadop");
130738103Sbostic 	}
130838103Sbostic     }
130938103Sbostic }
131038103Sbostic 
oquick(inst,opcode)131138103Sbostic public oquick(inst, opcode)
131238103Sbostic long inst;
131338103Sbostic register String opcode;
131438103Sbostic {
131538103Sbostic     register int size;
131638103Sbostic     register int data;
131738103Sbostic 
131838103Sbostic     size = mapsize(inst);
131938103Sbostic     data = (int)((inst>>9) & 07);
132038103Sbostic     if (data == 0) {
132138103Sbostic 	data = 8;
132238103Sbostic     }
132338103Sbostic     if (size > 0) {
132438103Sbostic 	if (printing) {
132538103Sbostic 	    printf("\t%s%c\t", opcode, suffix(size));
132638103Sbostic 	    printf(IMDF, data);
132738103Sbostic 	    printf(",");
132838103Sbostic 	}
132938103Sbostic 	printEA(inst);
133038103Sbostic     } else {
133138103Sbostic 	if (printing) {
133238103Sbostic 	    printf("\tbadop");
133338103Sbostic 	}
133438103Sbostic     }
133538103Sbostic }
133638103Sbostic 
omoveq(inst,dummy)133738103Sbostic public omoveq(inst, dummy)
133838103Sbostic long inst;
133938103Sbostic long dummy;
134038103Sbostic {
134138103Sbostic     register int data;
134238103Sbostic 
134338103Sbostic     if (printing) {
134438103Sbostic 	data = (int)(inst & 0377);
134538103Sbostic 	if (data > 127) {
134638103Sbostic 	    data |= ~0377;
134738103Sbostic 	}
134838103Sbostic 	printf("\tmoveq\t");
134938103Sbostic 	printf(IMDF, data);
135038103Sbostic 	printf(",d%D", (inst>>9)&07);
135138103Sbostic     }
135238103Sbostic }
135338103Sbostic 
oprint(inst,opcode)135438103Sbostic public oprint(inst, opcode)
135538103Sbostic long inst;
135638103Sbostic register String opcode;
135738103Sbostic {
135838103Sbostic     if (printing) {
135938103Sbostic 	printf("\t%s",opcode);
136038103Sbostic     }
136138103Sbostic }
136238103Sbostic 
ostop(inst,opcode)136338103Sbostic public ostop(inst, opcode)
136438103Sbostic long inst;
136538103Sbostic register String opcode;
136638103Sbostic {
136738103Sbostic     short w;
136838103Sbostic 
136938103Sbostic     instread(w);
137038103Sbostic     if (printing) {
137138103Sbostic 	printf(opcode, w);
137238103Sbostic     }
137338103Sbostic }
137438103Sbostic 
orts(inst,opcode)137538103Sbostic public orts(inst, opcode)
137638103Sbostic long inst;
137738103Sbostic register String opcode;
137838103Sbostic {
137938103Sbostic     Address addr;
138038103Sbostic 
138138103Sbostic     if (following) {
138238103Sbostic 	callnews(/* iscall = */ false);
138338103Sbostic     	if (inst_tracing) {
138438103Sbostic 	    addr = currtnaddr();
138538103Sbostic     	} else {
138638103Sbostic 	    addr = return_addr();
138738103Sbostic 	    if (addr == 0) {
138838103Sbostic 		stepto(instaddr - 2);
138938103Sbostic 		addr = currtnaddr();
139038103Sbostic 	    }
139138103Sbostic 	}
139238103Sbostic 	stepto(addr);
139338103Sbostic 	instaddr = pc;
139438103Sbostic     }
139538103Sbostic     if (printing) {
139638103Sbostic 	printf("\t%s",opcode);
139738103Sbostic     }
139838103Sbostic }
139938103Sbostic 
140038103Sbostic /*
140138103Sbostic  * Not used by C compiler; does an rts but before doing so, pops
140238103Sbostic  * arg bytes from the stack.
140338103Sbostic  */
140438103Sbostic 
ortspop(inst,opcode)140538103Sbostic public ortspop(inst, opcode)
140638103Sbostic long inst;
140738103Sbostic register String opcode;
140838103Sbostic {
140938103Sbostic     Address addr;
141038103Sbostic     short w;
141138103Sbostic 
141238103Sbostic     instread(w);
141338103Sbostic     if (following) {
141438103Sbostic 	callnews(/* iscall = */ false);
141538103Sbostic     	if (inst_tracing) {
141638103Sbostic 	    addr = currtnaddr();
141738103Sbostic     	} else {
141838103Sbostic 	    addr = return_addr();
141938103Sbostic 	}
142038103Sbostic 	stepto(addr);
142138103Sbostic 	instaddr = pc;
142238103Sbostic     }
142338103Sbostic     if (printing) {
142438103Sbostic 	printf(opcode, w);
142538103Sbostic     }
142638103Sbostic }
142738103Sbostic 
omovs(inst,opcode)142838103Sbostic public omovs(inst, opcode)
142938103Sbostic long inst;
143038103Sbostic String opcode;
143138103Sbostic {
143238103Sbostic     register int size;
143338103Sbostic     register unsigned int controlword;
143438103Sbostic     short w;
143538103Sbostic 
143638103Sbostic     size = mapsize(inst);
143738103Sbostic     instread(w);
143838103Sbostic     controlword = w >> 11;
143938103Sbostic     if (printing) {
144038103Sbostic 	printf("\t%s%c\t", opcode, suffix(size));
144138103Sbostic     }
144238103Sbostic     if (controlword & 1){
144338103Sbostic 	controlword >>= 1;
144438103Sbostic 	if (printing) {
144538103Sbostic 	    printf((controlword&0x8) ? "a%D," : "d%D,", controlword&7 );
144638103Sbostic 	}
144738103Sbostic 	printEA(inst&0xff, size);
144838103Sbostic     } else {
144938103Sbostic 	controlword >>= 1;
145038103Sbostic 	printEA(inst&0xff, size);
145138103Sbostic 	if (printing) {
145238103Sbostic 	    printf((controlword&0x8) ? ",a%D" : ",d%D", controlword&7);
145338103Sbostic 	}
145438103Sbostic     }
145538103Sbostic }
145638103Sbostic 
omovc(inst,opcode)145738103Sbostic public omovc(inst, opcode)
145838103Sbostic long inst;
145938103Sbostic String opcode;
146038103Sbostic {
146138103Sbostic     register unsigned int controlword;
146238103Sbostic     String creg;
146338103Sbostic     short w;
146438103Sbostic 
146538103Sbostic     instread(w);
146638103Sbostic     if (printing) {
146738103Sbostic 	controlword = w;
146838103Sbostic 	switch (controlword & 0xfff) {
146938103Sbostic 	    case 0:
147038103Sbostic 		creg = "sfc";
147138103Sbostic 		break;
147238103Sbostic 
147338103Sbostic 	    case 1:
147438103Sbostic 		creg = "dfc";
147538103Sbostic 		break;
147638103Sbostic 
147738103Sbostic 	    case 0x800:
147838103Sbostic 		creg = "usp";
147938103Sbostic 		break;
148038103Sbostic 
148138103Sbostic 	    case 0x801:
148238103Sbostic 		creg = "vbr";
148338103Sbostic 		break;
148438103Sbostic 
148538103Sbostic 	    default:
148638103Sbostic 		creg = "???";
148738103Sbostic 		break;
148838103Sbostic 	}
148938103Sbostic 	controlword >>= 12;
149038103Sbostic 	if (inst & 1){
149138103Sbostic 	    printf((controlword&0x8) ? "%sa%D,%s" : "%sd%D,%s",
149238103Sbostic 		opcode, controlword&7, creg );
149338103Sbostic 	} else {
149438103Sbostic 	    printf((controlword&0x8) ? "%s%s,a%D" : "%s%s,d%D",
149538103Sbostic 		opcode, creg, controlword&7 );
149638103Sbostic 	}
149738103Sbostic     }
149838103Sbostic }
149938103Sbostic 
150038103Sbostic /*
150138103Sbostic  * Compute the next address that will be executed from the given one.
150238103Sbostic  * If "isnext" is true then consider a procedure call as straight line code.
150338103Sbostic  *
150438103Sbostic  * Unconditional branches we just follow, for conditional branches
150538103Sbostic  * we continue execution to the current location and then single step
150638103Sbostic  * the machine.
150738103Sbostic  */
150838103Sbostic 
nextaddr(startaddr,isnext)150938103Sbostic public Address nextaddr(startaddr, isnext)
151038103Sbostic Address startaddr;
151138103Sbostic Boolean isnext;
151238103Sbostic {
151338103Sbostic     Optab *o;
151438103Sbostic     short inst;
151538103Sbostic 
151638103Sbostic     instaddr = usignal(process);
151738103Sbostic     if (instaddr == 0 or instaddr == 1) {
151838103Sbostic 	following = true;
151938103Sbostic 	followcalls = (Boolean) (not isnext);
152038103Sbostic 	printing = false;
152138103Sbostic 	iread(&inst, startaddr, sizeof(inst));
152238103Sbostic 	instaddr = startaddr + sizeof(inst);
152338103Sbostic 	o = decode(inst, startaddr);
152438103Sbostic 	if (o->mask == 0) {
152538103Sbostic 	    fprintf(stderr,
152638103Sbostic 		"[internal error: undecodable op at 0x%x]\n", startaddr);
152738103Sbostic 	    fflush(stderr);
152838103Sbostic 	} else {
152938103Sbostic 	    (*o->opfun)(inst, o->farg);
153038103Sbostic 	}
153138103Sbostic 	following = false;
153238103Sbostic     }
153338103Sbostic     return instaddr;
153438103Sbostic }
153538103Sbostic 
153638103Sbostic /*
153738103Sbostic  * Step to the given address and then execute one instruction past it.
153838103Sbostic  * Set instaddr to the new instruction address.
153938103Sbostic  */
154038103Sbostic 
steppast(addr)154138103Sbostic private steppast(addr)
154238103Sbostic Address addr;
154338103Sbostic {
154438103Sbostic     stepto(addr);
154538103Sbostic     pstep(process, DEFSIG);
154638103Sbostic     pc = reg(PROGCTR);
154738103Sbostic     instaddr = pc;
154838103Sbostic }
154938103Sbostic 
155038103Sbostic /*
155138103Sbostic  * Enter a procedure by creating and executing a call instruction.
155238103Sbostic  */
155338103Sbostic 
155438103Sbostic #define CALLSIZE 6	/* size of call instruction */
155538103Sbostic 
beginproc(p)155638103Sbostic public beginproc(p)
155738103Sbostic Symbol p;
155838103Sbostic {
155938103Sbostic     char save[CALLSIZE];
156038103Sbostic     struct {
156138103Sbostic 	short op;
156238103Sbostic 	char addr[sizeof(long)];	/* unaligned long */
156338103Sbostic     } call;
156438103Sbostic     long dest;
156538103Sbostic 
156638103Sbostic     pc = CODESTART + 6;
156738103Sbostic     iread(save, pc, sizeof(save));
156838103Sbostic     call.op = 0x4eb9;			/* jsr */
156938103Sbostic     dest = codeloc(p) - FUNCOFFSET;
157038103Sbostic     mov(&dest, call.addr, sizeof(call.addr));
157138103Sbostic     iwrite(&call, pc, sizeof(call));
157238103Sbostic     setreg(PROGCTR, pc);
157338103Sbostic     pstep(process, DEFSIG);
157438103Sbostic     iwrite(save, pc, sizeof(save));
157538103Sbostic     pc = reg(PROGCTR);
157638103Sbostic     if (not isbperr()) {
157738103Sbostic 	printstatus();
157838103Sbostic     }
157938103Sbostic     /*
158038103Sbostic      * Execute link instruction so the return addr is visible.
158138103Sbostic      */
158238103Sbostic     pstep(process, DEFSIG);
158338103Sbostic     pc = reg(PROGCTR);
158438103Sbostic     if (not isbperr()) {
158538103Sbostic 	printstatus();
158638103Sbostic     }
158738103Sbostic }
158838103Sbostic 
158938103Sbostic /*
159038103Sbostic  * Special variables for debugging the kernel.
159138103Sbostic  */
159238103Sbostic 
159338103Sbostic public integer masterpcbb;
159438103Sbostic public integer slr;
159538103Sbostic public struct pte *sbr;
159638103Sbostic private struct pcb pcb;
159738103Sbostic 
getpcb()159838103Sbostic public getpcb ()
159938103Sbostic {
160038103Sbostic     integer i;
160138103Sbostic 
160238103Sbostic     fseek(corefile, masterpcbb & ~0x80000000, 0);
160338103Sbostic     get(corefile, pcb);
160438103Sbostic     pcb.pcb_p0lr &= ~AST_CLR;
160538103Sbostic     printf("p0br %lx p0lr %lx p1br %lx p1lr %lx\n",
160638103Sbostic 	pcb.pcb_p0br, pcb.pcb_p0lr, pcb.pcb_p1br, pcb.pcb_p1lr
160738103Sbostic     );
160838103Sbostic #   ifdef sun
160938103Sbostic     for (i = 0; i < 14; i++) {
161038103Sbostic 	setreg(i, pcb.pcb_regs.val[i]);
161138103Sbostic     }
161238103Sbostic #   else /* IRIS */
161338103Sbostic     for (i = 0; i < 14; i++) {
161438103Sbostic 	setreg(i, pcb.pcb_regs[i]);
161538103Sbostic     }
161638103Sbostic #   endif
161738103Sbostic }
161838103Sbostic 
copyregs(savreg,reg)161938103Sbostic public copyregs (savreg, reg)
162038103Sbostic Word savreg[], reg[];
162138103Sbostic {
162238103Sbostic     reg[0] = savreg[R0];
162338103Sbostic     reg[1] = savreg[R1];
162438103Sbostic     reg[2] = savreg[R2];
162538103Sbostic     reg[3] = savreg[R3];
162638103Sbostic     reg[4] = savreg[R4];
162738103Sbostic     reg[5] = savreg[R5];
162838103Sbostic     reg[6] = savreg[R6];
162938103Sbostic     reg[7] = savreg[R7];
163038103Sbostic     reg[8] = savreg[AR0];
163138103Sbostic     reg[9] = savreg[AR1];
163238103Sbostic     reg[10] = savreg[AR2];
163338103Sbostic     reg[11] = savreg[AR3];
163438103Sbostic     reg[12] = savreg[AR4];
163538103Sbostic     reg[13] = savreg[AR5];
163638103Sbostic     reg[14] = savreg[AR6];
163738103Sbostic     reg[15] = savreg[AR7];
163838103Sbostic     reg[PROGCTR] = savreg[PC];
163938103Sbostic }
164038103Sbostic 
164138103Sbostic /*
164238103Sbostic  * Map a virtual address to a physical address.
164338103Sbostic  * XXX THIS CAN'T BE RIGHT... XXX
164438103Sbostic  */
164538103Sbostic 
vmap(addr)164638103Sbostic public Address vmap (addr)
164738103Sbostic Address addr;
164838103Sbostic {
164938103Sbostic     Address r;
165038103Sbostic     integer v, n;
165138103Sbostic     struct pte pte;
165238103Sbostic 
165338103Sbostic     r = addr & ~0xc0000000;
165438103Sbostic     v = btop(r);
165538103Sbostic     switch (addr&0xc0000000) {
165638103Sbostic 	case 0xc0000000:
165738103Sbostic 	case 0x80000000:
165838103Sbostic 	    /*
165938103Sbostic 	     * In system space, so get system pte.
166038103Sbostic 	     * If it is valid or reclaimable then the physical address
166138103Sbostic 	     * is the combination of its page number and the page offset
166238103Sbostic 	     * of the original address.
166338103Sbostic 	     */
166438103Sbostic 	    if (v >= slr) {
166538103Sbostic 		error("address %x out of segment", addr);
166638103Sbostic 	    }
166738103Sbostic 	    r = ((long) (sbr + v)) & ~0x80000000;
166838103Sbostic 	    goto simple;
166938103Sbostic 
167038103Sbostic 	case 0x40000000:
167138103Sbostic 	    /*
167238103Sbostic 	     * In p1 space, must not be in shadow region.
167338103Sbostic 	     */
167438103Sbostic 	    if (v < pcb.pcb_p1lr) {
167538103Sbostic 		error("address %x out of segment", addr);
167638103Sbostic 	    }
167738103Sbostic 	    r = (Address) (pcb.pcb_p1br + v);
167838103Sbostic 	    break;
167938103Sbostic 
168038103Sbostic 	case 0x00000000:
168138103Sbostic 	    /*
168238103Sbostic 	     * In p0 space, must not be off end of region.
168338103Sbostic 	     */
168438103Sbostic 	    if (v >= pcb.pcb_p0lr) {
168538103Sbostic 		error("address %x out of segment", addr);
168638103Sbostic 	    }
168738103Sbostic 	    r = (Address) (pcb.pcb_p0br + v);
168838103Sbostic 	    break;
168938103Sbostic 
169038103Sbostic 	default:
169138103Sbostic 	    /* do nothing */
169238103Sbostic 	    break;
169338103Sbostic     }
169438103Sbostic     /*
169538103Sbostic      * For p0/p1 address, user-level page table should be in
169638103Sbostic      * kernel virtual memory.  Do second-level indirect by recursing.
169738103Sbostic      */
169838103Sbostic     if ((r & 0x80000000) == 0) {
169938103Sbostic 	error("bad p0br or p1br in pcb");
170038103Sbostic     }
170138103Sbostic     r = vmap(r);
170238103Sbostic simple:
170338103Sbostic     /*
170438103Sbostic      * "r" is now the address of the pte of the page
170538103Sbostic      * we are interested in; get the pte and paste up the physical address.
170638103Sbostic      */
170738103Sbostic     fseek(corefile, r, 0);
170838103Sbostic     n = fread(&pte, sizeof(pte), 1, corefile);
170938103Sbostic     if (n != 1) {
171038103Sbostic 	error("page table botch (fread at %x returns %d)", r, n);
171138103Sbostic     }
171238103Sbostic     if (pte.pg_v == 0 and (pte.pg_fod != 0 or pte.pg_pfnum == 0)) {
171338103Sbostic 	error("page no valid or reclamable");
171438103Sbostic     }
171538103Sbostic     return (addr&PGOFSET) + ((Address) ptob(pte.pg_pfnum));
171638103Sbostic }
171738103Sbostic 
171838103Sbostic /*
171938103Sbostic  * Extract a bit field from an integer.
172038103Sbostic  */
172138103Sbostic 
extractField(s)172238103Sbostic public integer extractField (s)
172338103Sbostic Symbol s;
172438103Sbostic {
172538103Sbostic     integer nbytes, nbits, n, r, off, len;
172638103Sbostic 
172738103Sbostic     off = s->symvalue.field.offset;
172838103Sbostic     len = s->symvalue.field.length;
172938103Sbostic     nbytes = size(s);
173038103Sbostic     n = 0;
173138103Sbostic     if (nbytes > sizeof(n)) {
173238103Sbostic 	printf("[bad size in extractField -- word assumed]\n");
173338103Sbostic 	nbytes = sizeof(n);
173438103Sbostic     }
173538103Sbostic     popn(nbytes, ((char *) &n) + (sizeof(Word) - nbytes));
173638103Sbostic     nbits = nbytes * BITSPERBYTE;
173738103Sbostic     r = n >> (nbits - ((off mod nbits) + len));
173838103Sbostic     r &= ((1 << len) - 1);
173938103Sbostic     return r;
174038103Sbostic }
174138103Sbostic 
174238103Sbostic /*
174338103Sbostic  * Change the length of a value in memory according to a given difference
174438103Sbostic  * in the lengths of its new and old types.
174538103Sbostic  */
174638103Sbostic 
loophole(oldlen,newlen)174738103Sbostic public loophole (oldlen, newlen)
174838103Sbostic integer oldlen, newlen;
174938103Sbostic {
175038103Sbostic     integer i, n;
175138103Sbostic     Stack *oldsp;
175238103Sbostic 
175338103Sbostic     n = newlen - oldlen;
175438103Sbostic     oldsp = sp - oldlen;
175538103Sbostic     if (n > 0) {
175638103Sbostic 	for (i = oldlen - 1; i >= 0; i--) {
175738103Sbostic 	    oldsp[n + i] = oldsp[i];
175838103Sbostic 	}
175938103Sbostic 	for (i = 0; i < n; i++) {
176038103Sbostic 	    oldsp[i] = '\0';
176138103Sbostic 	}
176238103Sbostic     } else {
176338103Sbostic 	for (i = 0; i < newlen; i++) {
176438103Sbostic 	    oldsp[i] = oldsp[i - n];
176538103Sbostic 	}
176638103Sbostic     }
176738103Sbostic     sp += n;
176838103Sbostic }
1769