xref: /csrg-svn/old/dbx/iris.c (revision 42683)
133318Sdonn /*
238105Sbostic  * Copyright (c) 1983 The Regents of the University of California.
338105Sbostic  * All rights reserved.
438105Sbostic  *
5*42683Sbostic  * %sccs.include.redist.c%
633318Sdonn  */
733318Sdonn 
833318Sdonn #ifndef lint
9*42683Sbostic static char sccsid[] = "@(#)iris.c	5.3 (Berkeley) 06/01/90";
1038105Sbostic #endif /* not lint */
1133318Sdonn 
1233318Sdonn /*
1333318Sdonn  * Target machine dependent stuff.
1433318Sdonn  */
1533318Sdonn 
1633318Sdonn #include "defs.h"
1733318Sdonn #include "machine.h"
1833318Sdonn #include "process.h"
1933318Sdonn #include "runtime.h"
2033318Sdonn #include "events.h"
2133318Sdonn #include "main.h"
2233318Sdonn #include "symbols.h"
2333318Sdonn #include "source.h"
2433318Sdonn #include "mappings.h"
2533318Sdonn #include "object.h"
2633318Sdonn #include "tree.h"
2733318Sdonn #include "eval.h"
2833318Sdonn #include "keywords.h"
2933318Sdonn #include "ops.h"
3033318Sdonn 
3133318Sdonn #ifndef public
3233318Sdonn typedef unsigned int Address;
3333318Sdonn typedef unsigned char Byte;
3433318Sdonn typedef unsigned int Word;
3533318Sdonn 
3633318Sdonn /*
3733318Sdonn  * On the 68000, the pc isn't in a register, but we make believe
3833318Sdonn  * so there's one more register.
3933318Sdonn  *
4033318Sdonn  * Note that there's also no argument pointer, this means code
4133318Sdonn  * involving "ARGP" should always be #ifdef'd.
4233318Sdonn  *
4333318Sdonn  * The address corresponding to the beginning of a function is recorded
4433318Sdonn  * as the address + FUNCOFFSET (skip the link instruction so that
4533318Sdonn  * local information is available).
4633318Sdonn  */
4733318Sdonn 
4833318Sdonn #define NREG 17
4933318Sdonn 
5033318Sdonn #define FRP 14
5133318Sdonn #define STKP 15
5233318Sdonn #define PROGCTR 16
5333318Sdonn 
5433318Sdonn #define CALL_RETADDR	0x800c		/* Return address for 'call' command */
5533318Sdonn #define FUNCOFFSET 4
5633318Sdonn 
5733318Sdonn #ifdef sun
5833318Sdonn #    define CODESTART 0x8000
5933318Sdonn #else /* IRIS */
6033318Sdonn #   define CODESTART 0x1000
6133318Sdonn #endif
6233318Sdonn 
6333318Sdonn #define optab_init()
6433318Sdonn 
6533318Sdonn #define BITSPERBYTE 8
6633318Sdonn #define BITSPERWORD (BITSPERBYTE * sizeof(Word))
6733318Sdonn 
6833318Sdonn /*
6933318Sdonn  * This magic macro enables us to look at the process' registers
7033318Sdonn  * in its user structure.
7133318Sdonn  */
7233318Sdonn 
7333318Sdonn #define regloc(reg)	(ctob(UPAGES) + (sizeof(Word) * ((reg) - PC)) - 10)
7433318Sdonn 
7533318Sdonn #include "source.h"
7633318Sdonn #include "symbols.h"
7733318Sdonn #include <signal.h>
7833318Sdonn #include <sys/param.h>
7933318Sdonn #include <sys/dir.h>
8033318Sdonn #include <machine/psl.h>
8133318Sdonn #include <machine/pte.h>
8233318Sdonn #include <sys/user.h>
8333318Sdonn #undef DELETE /* XXX */
8433318Sdonn #include <sys/vm.h>
8533318Sdonn #include <machine/reg.h>
8633318Sdonn 
8733318Sdonn Address pc;
8833318Sdonn Address prtaddr;
8933318Sdonn 
9033318Sdonn #endif
9133318Sdonn 
9233318Sdonn /*
9333318Sdonn  * Indices into u. for use in collecting registers values.
9433318Sdonn  */
9533318Sdonn public int rloc[] ={
9633318Sdonn #ifdef sun
9733318Sdonn     R0, R1, R2, R3, R4, R5, R6, R7, AR0, AR1, AR2, AR3, AR4, AR5, AR6, AR7, PC
9833318Sdonn #else /* IRIS */
9933318Sdonn     R0, R1, R2, R3, R4, R5, R6, R7, AR0, AR1, AR2, AR3, AR4, AR5, AR6, AR7, 16
10033318Sdonn #endif
10133318Sdonn };
10233318Sdonn 
10333318Sdonn private Address printop();
10433318Sdonn 
10533318Sdonn /*
10633318Sdonn  * Decode and print the instructions within the given address range.
10733318Sdonn  */
10833318Sdonn 
printinst(lowaddr,highaddr)10933318Sdonn public printinst(lowaddr, highaddr)
11033318Sdonn Address lowaddr;
11133318Sdonn Address highaddr;
11233318Sdonn {
11333318Sdonn     register Address addr;
11433318Sdonn 
11533318Sdonn     for (addr = lowaddr; addr <= highaddr; ) {
11633318Sdonn 	addr = printop(addr);
11733318Sdonn     }
11833318Sdonn     prtaddr = addr;
11933318Sdonn }
12033318Sdonn 
12133318Sdonn /*
12233318Sdonn  * Another approach:  print n instructions starting at the given address.
12333318Sdonn  */
12433318Sdonn 
printninst(count,addr)12533318Sdonn public printninst(count, addr)
12633318Sdonn int count;
12733318Sdonn Address addr;
12833318Sdonn {
12933318Sdonn     register Integer i;
13033318Sdonn     register Address newaddr;
13133318Sdonn 
13233318Sdonn     if (count <= 0) {
13333318Sdonn 	error("non-positive repetition count");
13433318Sdonn     } else {
13533318Sdonn 	newaddr = addr;
13633318Sdonn 	for (i = 0; i < count; i++) {
13733318Sdonn 	    newaddr = printop(newaddr);
13833318Sdonn 	}
13933318Sdonn 	prtaddr = newaddr;
14033318Sdonn     }
14133318Sdonn }
14233318Sdonn 
14333318Sdonn /*
14433318Sdonn  * Print the contents of the addresses within the given range
14533318Sdonn  * according to the given format.
14633318Sdonn  */
14733318Sdonn 
14833318Sdonn typedef struct {
14933318Sdonn     String name;
15033318Sdonn     String printfstring;
15133318Sdonn     int length;
15233318Sdonn } Format;
15333318Sdonn 
15433318Sdonn private Format fmt[] = {
15533318Sdonn     { "d", " %d", sizeof(short) },
15633318Sdonn     { "D", " %ld", sizeof(long) },
15733318Sdonn     { "o", " %o", sizeof(short) },
15833318Sdonn     { "O", " %lo", sizeof(long) },
15933318Sdonn     { "x", " %04x", sizeof(short) },
16033318Sdonn     { "X", " %08x", sizeof(long) },
16133318Sdonn     { "b", " \\%o", sizeof(char) },
16233318Sdonn     { "c", " '%c'", sizeof(char) },
16333318Sdonn     { "s", "%c", sizeof(char) },
16433318Sdonn     { "f", " %f", sizeof(float) },
16533318Sdonn     { "g", " %g", sizeof(double) },
16633318Sdonn     { nil, nil, 0 }
16733318Sdonn };
16833318Sdonn 
findformat(s)16933318Sdonn private Format *findformat(s)
17033318Sdonn String s;
17133318Sdonn {
17233318Sdonn     register Format *f;
17333318Sdonn 
17433318Sdonn     f = &fmt[0];
17533318Sdonn     while (f->name != nil and not streq(f->name, s)) {
17633318Sdonn 	++f;
17733318Sdonn     }
17833318Sdonn     if (f->name == nil) {
17933318Sdonn 	error("bad print format \"%s\"", s);
18033318Sdonn     }
18133318Sdonn     return f;
18233318Sdonn }
18333318Sdonn 
18433318Sdonn /*
18533318Sdonn  * Retrieve and print out the appropriate data in the given format.
18633318Sdonn  * Floats have to be handled specially to allow the compiler to
18733318Sdonn  * convert them to doubles when passing to printf.
18833318Sdonn  */
18933318Sdonn 
printformat(f,addr)19033318Sdonn private printformat (f, addr)
19133318Sdonn Format *f;
19233318Sdonn Address addr;
19333318Sdonn {
19433318Sdonn     union {
19533318Sdonn 	char charv;
19633318Sdonn 	short shortv;
19733318Sdonn 	int intv;
19833318Sdonn 	float floatv;
19933318Sdonn 	double doublev;
20033318Sdonn     } value;
20133318Sdonn 
20233318Sdonn     value.intv = 0;
20333318Sdonn     dread(&value, addr, f->length);
20433318Sdonn     if (streq(f->name, "f")) {
20533318Sdonn 	printf(f->printfstring, value.floatv);
20633318Sdonn     } else {
20733318Sdonn 	printf(f->printfstring, value);
20833318Sdonn     }
20933318Sdonn }
21033318Sdonn 
printdata(lowaddr,highaddr,format)21133318Sdonn public Address printdata(lowaddr, highaddr, format)
21233318Sdonn Address lowaddr;
21333318Sdonn Address highaddr;
21433318Sdonn String format;
21533318Sdonn {
21633318Sdonn     int n;
21733318Sdonn     register Address addr;
21833318Sdonn     Format *f;
21933318Sdonn 
22033318Sdonn     if (lowaddr > highaddr) {
22133318Sdonn 	error("first address larger than second");
22233318Sdonn     }
22333318Sdonn     f = findformat(format);
22433318Sdonn     n = 0;
22533318Sdonn     for (addr = lowaddr; addr <= highaddr; addr += f->length) {
22633318Sdonn 	if (n == 0) {
22733318Sdonn 	    printf("%08x: ", addr);
22833318Sdonn 	}
22933318Sdonn 	printformat(f, addr);
23033318Sdonn 	++n;
23133318Sdonn 	if (n >= (16 div f->length)) {
23233318Sdonn 	    printf("\n");
23333318Sdonn 	    n = 0;
23433318Sdonn 	}
23533318Sdonn     }
23633318Sdonn     if (n != 0) {
23733318Sdonn 	printf("\n");
23833318Sdonn     }
23933318Sdonn     prtaddr = addr;
24033318Sdonn     return addr;
24133318Sdonn }
24233318Sdonn 
24333318Sdonn /*
24433318Sdonn  * The other approach is to print n items starting with a given address.
24533318Sdonn  */
24633318Sdonn 
printndata(count,startaddr,format)24733318Sdonn public printndata(count, startaddr, format)
24833318Sdonn int count;
24933318Sdonn Address startaddr;
25033318Sdonn String format;
25133318Sdonn {
25233318Sdonn     int i, n;
25333318Sdonn     Address addr;
25433318Sdonn     Format *f;
25533318Sdonn     Boolean isstring;
25633318Sdonn     char c;
25733318Sdonn 
25833318Sdonn     if (count <= 0) {
25933318Sdonn 	error("non-positive repetition count");
26033318Sdonn     }
26133318Sdonn     f = findformat(format);
26233318Sdonn     isstring = (Boolean) streq(f->name, "s");
26333318Sdonn     n = 0;
26433318Sdonn     addr = startaddr;
26533318Sdonn     for (i = 0; i < count; i++) {
26633318Sdonn 	if (n == 0) {
26733318Sdonn 	    printf("%08x: ", addr);
26833318Sdonn 	}
26933318Sdonn 	if (isstring) {
27033318Sdonn 	    printf("\"");
27133318Sdonn 	    dread(&c, addr, sizeof(char));
27233318Sdonn 	    while (c != '\0') {
27333318Sdonn 		printchar(c);
27433318Sdonn 		++addr;
27533318Sdonn 		dread(&c, addr, sizeof(char));
27633318Sdonn 	    }
27733318Sdonn 	    printf("\"\n");
27833318Sdonn 	    n = 0;
27933318Sdonn 	    addr += sizeof(String);
28033318Sdonn 	} else {
28133318Sdonn 	    printformat(f, addr);
28233318Sdonn 	    ++n;
28333318Sdonn 	    if (n >= (16 div f->length)) {
28433318Sdonn 		printf("\n");
28533318Sdonn 		n = 0;
28633318Sdonn 	    }
28733318Sdonn 	    addr += f->length;
28833318Sdonn 	}
28933318Sdonn     }
29033318Sdonn     if (n != 0) {
29133318Sdonn 	printf("\n");
29233318Sdonn     }
29333318Sdonn     prtaddr = addr;
29433318Sdonn }
29533318Sdonn 
29633318Sdonn /*
29733318Sdonn  * Print out a value according to the given format.
29833318Sdonn  */
29933318Sdonn 
printvalue(v,format)30033318Sdonn public printvalue(v, format)
30133318Sdonn long v;
30233318Sdonn String format;
30333318Sdonn {
30433318Sdonn     Format *f;
30533318Sdonn     char *p, *q;
30633318Sdonn 
30733318Sdonn     f = findformat(format);
30833318Sdonn     if (streq(f->name, "s")) {
30933318Sdonn 	putchar('"');
31033318Sdonn 	p = (char *) &v;
31133318Sdonn 	q = p + sizeof(v);
31233318Sdonn 	while (p < q) {
31333318Sdonn 	    printchar(*p);
31433318Sdonn 	    ++p;
31533318Sdonn 	}
31633318Sdonn 	putchar('"');
31733318Sdonn     } else {
31833318Sdonn 	printf(f->printfstring, v);
31933318Sdonn     }
32033318Sdonn     putchar('\n');
32133318Sdonn }
32233318Sdonn 
32333318Sdonn /*
32433318Sdonn  * Print out an execution time error.
32533318Sdonn  * Assumes the source position of the error has been calculated.
32633318Sdonn  *
32733318Sdonn  * Have to check if the -r option was specified; if so then
32833318Sdonn  * the object file information hasn't been read in yet.
32933318Sdonn  */
33033318Sdonn 
printerror()33133318Sdonn public printerror()
33233318Sdonn {
33333318Sdonn     extern Integer sys_nsig;
33433318Sdonn     extern String sys_siglist[];
33533318Sdonn     integer err;
33633318Sdonn 
33733318Sdonn     if (isfinished(process)) {
33833318Sdonn 	err = exitcode(process);
33933318Sdonn 	if (err == 0) {
34033318Sdonn 	    printf("\"%s\" terminated normally\n", objname);
34133318Sdonn 	} else {
34233318Sdonn 	    printf("\"%s\" terminated abnormally (exit code %d)\n",
34333318Sdonn 		objname, err
34433318Sdonn 	    );
34533318Sdonn 	}
34633318Sdonn 	erecover();
34733318Sdonn     }
34833318Sdonn     err = errnum(process);
34933318Sdonn     putchar('\n');
35033318Sdonn     printsig(err);
35133318Sdonn     putchar(' ');
35233318Sdonn     printloc();
35333318Sdonn     putchar('\n');
35433318Sdonn     if (curline > 0) {
35533318Sdonn 	printlines(curline, curline);
35633318Sdonn     } else {
35733318Sdonn 	printinst(pc, pc);
35833318Sdonn     }
35933318Sdonn     erecover();
36033318Sdonn }
36133318Sdonn 
36233318Sdonn /*
36333318Sdonn  * Print out a signal.
36433318Sdonn  */
36533318Sdonn 
36633318Sdonn private String illinames[] = {
36733318Sdonn     "reserved addressing fault",
36833318Sdonn     "privileged instruction fault",
36933318Sdonn     "reserved operand fault"
37033318Sdonn };
37133318Sdonn 
37233318Sdonn private String fpenames[] = {
37333318Sdonn     nil,
37433318Sdonn     "integer overflow trap",
37533318Sdonn     "integer divide by zero trap",
37633318Sdonn     "floating overflow trap",
37733318Sdonn     "floating/decimal divide by zero trap",
37833318Sdonn     "floating underflow trap",
37933318Sdonn     "decimal overflow trap",
38033318Sdonn     "subscript out of range trap",
38133318Sdonn     "floating overflow fault",
38233318Sdonn     "floating divide by zero fault",
38333318Sdonn     "floating underflow fault"
38433318Sdonn };
38533318Sdonn 
printsig(signo)38633318Sdonn public printsig (signo)
38733318Sdonn integer signo;
38833318Sdonn {
38933318Sdonn     integer code;
39033318Sdonn 
39133318Sdonn     if (signo < 0 or signo > sys_nsig) {
39233318Sdonn 	printf("[signal %d]", signo);
39333318Sdonn     } else {
39433318Sdonn 	printf("%s", sys_siglist[signo]);
39533318Sdonn     }
39633318Sdonn     code = errcode(process);
39733318Sdonn     if (signo == SIGILL) {
39833318Sdonn 	if (code >= 0 and code < sizeof(illinames) / sizeof(illinames[0])) {
39933318Sdonn 	    printf(" (%s)", illinames[code]);
40033318Sdonn 	}
40133318Sdonn     } else if (signo == SIGFPE) {
40233318Sdonn 	if (code > 0 and code < sizeof(fpenames) / sizeof(fpenames[0])) {
40333318Sdonn 	    printf(" (%s)", fpenames[code]);
40433318Sdonn 	}
40533318Sdonn     }
40633318Sdonn }
40733318Sdonn 
40833318Sdonn /*
40933318Sdonn  * Note the termination of the program.  We do this so as to avoid
41033318Sdonn  * having the process exit, which would make the values of variables
41133318Sdonn  * inaccessible.  We do want to flush all output buffers here,
41233318Sdonn  * otherwise it'll never get done.
41333318Sdonn  */
41433318Sdonn 
endprogram()41533318Sdonn public endprogram()
41633318Sdonn {
41733318Sdonn     Integer exitcode;
41833318Sdonn 
41933318Sdonn     stepto(nextaddr(pc, true));
42033318Sdonn     printnews();
42133318Sdonn     exitcode = argn(1, nil);
42233318Sdonn     if (exitcode != 0) {
42333318Sdonn 	printf("\nexecution completed (exit code %d)\n", exitcode);
42433318Sdonn     } else {
42533318Sdonn 	printf("\nexecution completed\n");
42633318Sdonn     }
42733318Sdonn     getsrcpos();
42833318Sdonn     erecover();
42933318Sdonn }
43033318Sdonn 
43133318Sdonn /*
43233318Sdonn  * Single step the machine a source line (or instruction if "inst_tracing"
43333318Sdonn  * is true).  If "isnext" is true, skip over procedure calls.
43433318Sdonn  */
43533318Sdonn 
43633318Sdonn private Address getcall();
43733318Sdonn 
dostep(isnext)43833318Sdonn public dostep(isnext)
43933318Sdonn Boolean isnext;
44033318Sdonn {
44133318Sdonn     register Address addr;
44233318Sdonn     register Lineno line;
44333318Sdonn     String filename;
44433318Sdonn     Address startaddr;
44533318Sdonn 
44633318Sdonn     startaddr = pc;
44733318Sdonn     addr = nextaddr(pc, isnext);
44833318Sdonn     if (not inst_tracing and nlhdr.nlines != 0) {
44933318Sdonn 	line = linelookup(addr);
45033318Sdonn 	while (line == 0) {
45133318Sdonn 	    addr = nextaddr(addr, isnext);
45233318Sdonn 	    line = linelookup(addr);
45333318Sdonn 	}
45433318Sdonn 	curline = line;
45533318Sdonn     } else {
45633318Sdonn 	curline = 0;
45733318Sdonn     }
45833318Sdonn     stepto(addr);
45933318Sdonn     filename = srcfilename(addr);
46033318Sdonn     setsource(filename);
46133318Sdonn }
46233318Sdonn 
46333318Sdonn typedef short Bpinst;
46433318Sdonn 
46533318Sdonn extern Bpinst BP_OP;
46633318Sdonn #ifdef sun
46733318Sdonn 	asm("_BP_OP: trap #15");
46833318Sdonn #else /* IRIS */
46933318Sdonn 	asm("_BP_OP: trap #1");
47033318Sdonn #endif
47133318Sdonn 
47233318Sdonn #define BP_ERRNO    SIGTRAP     /* signal received at a breakpoint */
47333318Sdonn 
47433318Sdonn /*
47533318Sdonn  * Setting a breakpoint at a location consists of saving
47633318Sdonn  * the word at the location and poking a BP_OP there.
47733318Sdonn  *
47833318Sdonn  * We save the locations and words on a list for use in unsetting.
47933318Sdonn  */
48033318Sdonn 
48133318Sdonn typedef struct Savelist *Savelist;
48233318Sdonn 
48333318Sdonn struct Savelist {
48433318Sdonn     Address location;
48533318Sdonn     Bpinst save;
48633318Sdonn     short refcount;
48733318Sdonn     Savelist link;
48833318Sdonn };
48933318Sdonn 
49033318Sdonn private Savelist savelist;
49133318Sdonn 
49233318Sdonn /*
49333318Sdonn  * Set a breakpoint at the given address.  Only save the word there
49433318Sdonn  * if it's not already a breakpoint.
49533318Sdonn  */
49633318Sdonn 
setbp(addr)49733318Sdonn public setbp(addr)
49833318Sdonn Address addr;
49933318Sdonn {
50033318Sdonn     Bpinst w, save;
50133318Sdonn     register Savelist newsave, s;
50233318Sdonn 
50333318Sdonn     for (s = savelist; s != nil; s = s->link) {
50433318Sdonn 	if (s->location == addr) {
50533318Sdonn 	    s->refcount++;
50633318Sdonn 	    return;
50733318Sdonn 	}
50833318Sdonn     }
50933318Sdonn     iread(&save, addr, sizeof(save));
51033318Sdonn     newsave = new(Savelist);
51133318Sdonn     newsave->location = addr;
51233318Sdonn     newsave->save = save;
51333318Sdonn     newsave->refcount = 1;
51433318Sdonn     newsave->link = savelist;
51533318Sdonn     savelist = newsave;
51633318Sdonn     w = BP_OP;
51733318Sdonn     iwrite(&w, addr, sizeof(w));
51833318Sdonn }
51933318Sdonn 
52033318Sdonn /*
52133318Sdonn  * Unset a breakpoint; unfortunately we have to search the SAVELIST
52233318Sdonn  * to find the saved value.  The assumption is that the SAVELIST will
52333318Sdonn  * usually be quite small.
52433318Sdonn  */
52533318Sdonn 
unsetbp(addr)52633318Sdonn public unsetbp(addr)
52733318Sdonn Address addr;
52833318Sdonn {
52933318Sdonn     register Savelist s, prev;
53033318Sdonn 
53133318Sdonn     prev = nil;
53233318Sdonn     for (s = savelist; s != nil; s = s->link) {
53333318Sdonn 	if (s->location == addr) {
53433318Sdonn 	    iwrite(&s->save, addr, sizeof(s->save));
53533318Sdonn 	    s->refcount--;
53633318Sdonn 	    if (s->refcount == 0) {
53733318Sdonn 		if (prev == nil) {
53833318Sdonn 		    savelist = s->link;
53933318Sdonn 		} else {
54033318Sdonn 		    prev->link = s->link;
54133318Sdonn 		}
54233318Sdonn 		dispose(s);
54333318Sdonn 	    }
54433318Sdonn 	    return;
54533318Sdonn 	}
54633318Sdonn 	prev = s;
54733318Sdonn     }
54833318Sdonn     panic("unsetbp: couldn't find address %d", addr);
54933318Sdonn }
55033318Sdonn 
55133318Sdonn /*
55233318Sdonn  * Instruction decoding routines for 68000, derived from adb.
55333318Sdonn  *
55433318Sdonn  * The shared boolean variable "printing" is true if the decoded
55533318Sdonn  * instruction is to be printed, false if not.  In either case,
55633318Sdonn  * the address of the next instruction after the given one is returned.
55733318Sdonn  */
55833318Sdonn 
55933318Sdonn private Boolean printing;
56033318Sdonn private Boolean following;
56133318Sdonn private Boolean followcalls;
56233318Sdonn private Address instaddr;
56333318Sdonn 
56433318Sdonn #define instread(var) \
56533318Sdonn { \
56633318Sdonn     iread(&var, instaddr, sizeof(var)); \
56733318Sdonn     instaddr += sizeof(var); \
56833318Sdonn }
56933318Sdonn 
decode(inst,addr)57033318Sdonn private Optab *decode(inst, addr)
57133318Sdonn Word inst;
57233318Sdonn Address addr;
57333318Sdonn {
57433318Sdonn     register Optab *o;
57533318Sdonn 
57633318Sdonn     o = &optab[0];
57733318Sdonn     while (o->mask != 0 and (inst&o->mask) != o->match) {
57833318Sdonn 	++o;
57933318Sdonn     }
58033318Sdonn     return o;
58133318Sdonn }
58233318Sdonn 
printop(addr)58333318Sdonn private Address printop(addr)
58433318Sdonn Address addr;
58533318Sdonn {
58633318Sdonn     Optab *o;
58733318Sdonn     short inst;
58833318Sdonn 
58933318Sdonn     printf("%08x  ", addr);
59033318Sdonn     iread(&inst, addr, sizeof(inst));
59133318Sdonn     o = decode(inst, addr);
59233318Sdonn     if (o->mask == 0) {
59333318Sdonn 	printf("\tbadop");
59433318Sdonn 	instaddr = addr + sizeof(inst);
59533318Sdonn     } else {
59633318Sdonn 	printing = true;
59733318Sdonn 	following = false;
59833318Sdonn 	instaddr = addr + sizeof(inst);
59933318Sdonn 	(*o->opfun)(inst, o->farg);
60033318Sdonn 	printing = false;
60133318Sdonn     }
60233318Sdonn     printf("\n");
60333318Sdonn     return instaddr;
60433318Sdonn }
60533318Sdonn 
60633318Sdonn /*
60733318Sdonn  * Quickly find the return address of the current procedure or function
60833318Sdonn  * while single stepping.  Just get the word pointed at by sp.
60933318Sdonn  */
61033318Sdonn 
currtnaddr()61133318Sdonn private Address currtnaddr ()
61233318Sdonn {
61333318Sdonn     Address retaddr;
61433318Sdonn 
61533318Sdonn     dread(&retaddr, reg(STKP), sizeof(retaddr));
61633318Sdonn     return retaddr;
61733318Sdonn }
61833318Sdonn 
61933318Sdonn /*
62033318Sdonn  * Print out the effective address for the given parameters.
62133318Sdonn  */
62233318Sdonn 
printea(mode,reg,size)62333318Sdonn private printea(mode, reg, size)
62433318Sdonn long mode, reg;
62533318Sdonn int size;
62633318Sdonn {
62733318Sdonn     long index, disp;
62833318Sdonn     static char *aregs[] = { "a0", "a1", "a2", "a3", "a4", "a5", "a6", "sp" };
62933318Sdonn     Byte b;
63033318Sdonn     short w;
63133318Sdonn     long l;
63233318Sdonn 
63333318Sdonn     switch ((int)(mode)) {
63433318Sdonn 	case 0:
63533318Sdonn 	    if (printing) {
63633318Sdonn 		printf("d%D", reg);
63733318Sdonn 	    }
63833318Sdonn 	    break;
63933318Sdonn 
64033318Sdonn 	case 1:
64133318Sdonn 	    if (printing) {
64233318Sdonn 		printf("%s", aregs[reg]);
64333318Sdonn 	    }
64433318Sdonn 	    break;
64533318Sdonn 
64633318Sdonn 	case 2:
64733318Sdonn 	    if (printing) {
64833318Sdonn 		printf("%s@", aregs[reg]);
64933318Sdonn 	    }
65033318Sdonn 	    break;
65133318Sdonn 
65233318Sdonn 	case 3:
65333318Sdonn 	    if (printing) {
65433318Sdonn 		printf("%s@+", aregs[reg]);
65533318Sdonn 	    }
65633318Sdonn 	    break;
65733318Sdonn 
65833318Sdonn 	case 4:
65933318Sdonn 	    if (printing) {
66033318Sdonn 		printf("%s@-", aregs[reg]);
66133318Sdonn 	    }
66233318Sdonn 	    break;
66333318Sdonn 
66433318Sdonn 	case 5:
66533318Sdonn 	    instread(w);
66633318Sdonn 	    if (printing) {
66733318Sdonn 		printf("%s@(%D)", aregs[reg], w);
66833318Sdonn 	    }
66933318Sdonn 	    break;
67033318Sdonn 
67133318Sdonn 	case 6:
67233318Sdonn 	    instread(w);
67333318Sdonn 	    if (printing) {
67433318Sdonn 		index = w;
67533318Sdonn 		disp = (char)(index&0377);
67633318Sdonn 		printf("%s@(%d,%c%D:%c)", aregs[reg], disp,
67733318Sdonn 		    (index&0100000)?'a':'d',(index>>12)&07,
67833318Sdonn 		    (index&04000)?'l':'w');
67933318Sdonn 	    }
68033318Sdonn 	    break;
68133318Sdonn 
68233318Sdonn 	case 7:
68333318Sdonn 	    switch ((int)(reg)) {
68433318Sdonn 		case 0:
68533318Sdonn 		    instread(w);
68633318Sdonn 		    if (printing) {
68733318Sdonn 			index = w;
68833318Sdonn 			psymoff(index);
68933318Sdonn 		    }
69033318Sdonn 		    break;
69133318Sdonn 
69233318Sdonn 		case 1:
69333318Sdonn 		    instread(l);
69433318Sdonn 		    if (printing) {
69533318Sdonn 			index = l;
69633318Sdonn 			psymoff(index);
69733318Sdonn 		    }
69833318Sdonn 		    break;
69933318Sdonn 
70033318Sdonn 		case 2:
70133318Sdonn 		    instread(w);
70233318Sdonn 		    if (printing) {
70333318Sdonn 			disp = w;
70433318Sdonn 			psymoff(disp + instaddr);
70533318Sdonn 		    }
70633318Sdonn 		    break;
70733318Sdonn 
70833318Sdonn 		case 3:
70933318Sdonn 		    instread(w);
71033318Sdonn 		    if (printing) {
71133318Sdonn 			index = w;
71233318Sdonn 			disp = (char)(index&0377);
71333318Sdonn 			printf("pc@(%D,%c%D:%c)", disp,
71433318Sdonn 			    (index&0100000)?'a':'d',(index>>12)&07,
71533318Sdonn 			    (index&04000)?'l':'w');
71633318Sdonn 		    }
71733318Sdonn 		    break;
71833318Sdonn 
71933318Sdonn 		case 4:
72033318Sdonn 		    switch (size) {
72133318Sdonn 			case sizeof(b):
72233318Sdonn 			    instread(w);
72333318Sdonn 			    index = (w&0xff);
72433318Sdonn 			    break;
72533318Sdonn 
72633318Sdonn 			case sizeof(w):
72733318Sdonn 			    instread(w);
72833318Sdonn 			    index = w;
72933318Sdonn 			    break;
73033318Sdonn 
73133318Sdonn 			case sizeof(l):
73233318Sdonn 			    instread(l);
73333318Sdonn 			    index = l;
73433318Sdonn 			    break;
73533318Sdonn 
73633318Sdonn 			default:
73733318Sdonn 			    if (printing) {
73833318Sdonn 			    	printf("unexpected size %d in printea\n", size);
73933318Sdonn 			    }
74033318Sdonn 			    instread(l);
74133318Sdonn 			    index = l;
74233318Sdonn 			    break;
74333318Sdonn 		    }
74433318Sdonn 		    if (printing) {
74533318Sdonn 			printf(IMDF, index);
74633318Sdonn 		    }
74733318Sdonn 		    break;
74833318Sdonn 
74933318Sdonn 		default:
75033318Sdonn 		    if (printing) {
75133318Sdonn 			printf("???");
75233318Sdonn 		    }
75333318Sdonn 		    break;
75433318Sdonn 	    }
75533318Sdonn 	    break;
75633318Sdonn 
75733318Sdonn 	default:
75833318Sdonn 	    if (printing) {
75933318Sdonn 		printf("???");
76033318Sdonn 	    }
76133318Sdonn 	    break;
76233318Sdonn     }
76333318Sdonn }
76433318Sdonn 
printEA(ea,size)76533318Sdonn private printEA(ea, size)
76633318Sdonn long ea;
76733318Sdonn int size;
76833318Sdonn {
76933318Sdonn     printea((ea>>3)&07, ea&07, size);
77033318Sdonn }
77133318Sdonn 
mapsize(inst)77233318Sdonn private mapsize(inst)
77333318Sdonn register long inst;
77433318Sdonn {
77533318Sdonn     int m;
77633318Sdonn 
77733318Sdonn     inst >>= 6;
77833318Sdonn     inst &= 03;
77933318Sdonn     switch (inst) {
78033318Sdonn 	case 0:
78133318Sdonn 	    m = 1;
78233318Sdonn 	    break;
78333318Sdonn 
78433318Sdonn 	case 1:
78533318Sdonn 	    m = 2;
78633318Sdonn 	    break;
78733318Sdonn 
78833318Sdonn 	case 2:
78933318Sdonn 	    m = 4;
79033318Sdonn 	    break;
79133318Sdonn 
79233318Sdonn 	default:
79333318Sdonn 	    m = -1;
79433318Sdonn 	    break;
79533318Sdonn     }
79633318Sdonn     return m;
79733318Sdonn }
79833318Sdonn 
suffix(size)79933318Sdonn private char suffix(size)
80033318Sdonn int size;
80133318Sdonn {
80233318Sdonn     char c;
80333318Sdonn 
80433318Sdonn     switch (size) {
80533318Sdonn 	case 1:
80633318Sdonn 	    c = 'b';
80733318Sdonn 	    break;
80833318Sdonn 
80933318Sdonn 	case 2:
81033318Sdonn 	    c = 'w';
81133318Sdonn 	    break;
81233318Sdonn 
81333318Sdonn 	case 4:
81433318Sdonn 	    c = 'l';
81533318Sdonn 	    break;
81633318Sdonn 
81733318Sdonn 	default:
81833318Sdonn 	    panic("bad size %d in suffix", size);
81933318Sdonn     }
82033318Sdonn     return c;
82133318Sdonn }
82233318Sdonn 
82333318Sdonn /*
82433318Sdonn  * Print an address offset.  Eventually this should attempt to be symbolic,
82533318Sdonn  * but for now its just printed in hex.
82633318Sdonn  */
82733318Sdonn 
psymoff(off)82833318Sdonn private psymoff (off)
82933318Sdonn Word off;
83033318Sdonn {
83133318Sdonn     Symbol f;
83233318Sdonn 
83333318Sdonn     f = whatblock((Address) (off + FUNCOFFSET));
83433318Sdonn     if (codeloc(f) == off + FUNCOFFSET) {
83533318Sdonn 	printf("%s", symname(f));
83633318Sdonn     } else {
83733318Sdonn 	printf("0x%x", off);
83833318Sdonn     }
83933318Sdonn }
84033318Sdonn 
84133318Sdonn /*
84233318Sdonn  * Instruction class specific routines.
84333318Sdonn  */
84433318Sdonn 
omove(inst,s)84533318Sdonn public omove(inst, s)
84633318Sdonn long inst;
84733318Sdonn String s;
84833318Sdonn {
84933318Sdonn     register int c;
85033318Sdonn     int size;
85133318Sdonn 
85233318Sdonn     c = s[0];
85333318Sdonn     if (printing) {
85433318Sdonn 	printf("\tmov%c\t", c);
85533318Sdonn     }
85633318Sdonn     size = ((c == 'b') ? 1 : (c == 'w') ? 2 : 4);
85733318Sdonn     printea((inst>>3)&07, inst&07, size);
85833318Sdonn     if (printing) {
85933318Sdonn 	printf(",");
86033318Sdonn     }
86133318Sdonn     printea((inst>>6)&07, (inst>>9)&07, size);
86233318Sdonn }
86333318Sdonn 
86433318Sdonn /*
86533318Sdonn  * Two types: bsr (4 bytes) and bsrs (2 bytes)
86633318Sdonn  */
86733318Sdonn 
obranch(inst,dummy)86833318Sdonn public obranch(inst, dummy)
86933318Sdonn long inst;
87033318Sdonn {
87133318Sdonn     long disp;
87233318Sdonn     String s;
87333318Sdonn     short w;
87433318Sdonn     Address startingaddr;	/* address of branch instruction */
87533318Sdonn     int branchtype;		/* type of branch (0 = unconditional) */
87633318Sdonn     Address dest;
87733318Sdonn     Address retaddr;		/* for bsr instruction */
87833318Sdonn 
87933318Sdonn     startingaddr = instaddr - 2;
88033318Sdonn     disp = inst&0377;
88133318Sdonn     s = "s ";
88233318Sdonn     if (disp == 0) {
88333318Sdonn 	retaddr = startingaddr + 4;
88433318Sdonn     } else {
88533318Sdonn 	retaddr = startingaddr + 2;
88633318Sdonn     }
88733318Sdonn     if (disp > 127) {
88833318Sdonn 	disp |= ~0377;
88933318Sdonn     } else if (disp == 0){
89033318Sdonn 	s = " ";
89133318Sdonn 	instread(w);
89233318Sdonn 	disp = w;
89333318Sdonn     }
89433318Sdonn     branchtype = (int)((inst>>8)&017);
89533318Sdonn     dest = startingaddr + 2 + disp;
89633318Sdonn     if (printing) {
89733318Sdonn 	printf("\tb%s%s\t", bname[branchtype], s);
89833318Sdonn 	psymoff(dest);
89933318Sdonn     }
90033318Sdonn     if (following) {
90133318Sdonn 	/*
90233318Sdonn 	 * If we're to follow the dynamic flow of instructions,
90333318Sdonn 	 * we must see where the branch leads.  A branchtype of 0
90433318Sdonn 	 * indicates an unconditional branch which we simply take
90533318Sdonn 	 * as the new instruction address.  For a conditional branch,
90633318Sdonn 	 * we continue execution up to the current address, single step,
90733318Sdonn 	 * and keep going.
90833318Sdonn 	 */
90933318Sdonn 	if (branchtype == 0) {
91033318Sdonn 	    instaddr = dest;
91133318Sdonn 	} else if (branchtype == 01) {		/* bsr */
91233318Sdonn 	    if (followcalls) {
91333318Sdonn 		steppast(startingaddr);
91433318Sdonn 		curfunc = whatblock(pc, true);
91533318Sdonn 		if (not isbperr()) {
91633318Sdonn 		    printstatus();
91733318Sdonn 		    /* NOTREACHED */
91833318Sdonn 		}
91933318Sdonn 		bpact();
92033318Sdonn 		if (nosource(curfunc) and canskip(curfunc) and
92133318Sdonn 		  nlhdr.nlines != 0) {
92233318Sdonn 		    stepto(retaddr);
92333318Sdonn 		    instaddr = pc;
92433318Sdonn 		    bpact();
92533318Sdonn 		} else {
92633318Sdonn 		    callnews(/* iscall = */ true);
92733318Sdonn 		}
92833318Sdonn 	    }
92933318Sdonn 	} else {
93033318Sdonn 	    steppast(startingaddr);
93133318Sdonn 	}
93233318Sdonn     }
93333318Sdonn }
93433318Sdonn 
odbcc(inst,form)93533318Sdonn public odbcc(inst, form)
93633318Sdonn long inst;
93733318Sdonn String form;
93833318Sdonn {
93933318Sdonn     long disp;
94033318Sdonn     short w;
94133318Sdonn 
94233318Sdonn     instread(w);
94333318Sdonn     if (printing) {
94433318Sdonn     	printf(form, dbname[(int)((inst>>8)&017)], inst&07);
94533318Sdonn 	psymoff(w + sizeof(w));
94633318Sdonn     }
94733318Sdonn }
94833318Sdonn 
oscc(inst,dummy)94933318Sdonn public oscc(inst, dummy)
95033318Sdonn long inst;
95133318Sdonn long dummy;
95233318Sdonn {
95333318Sdonn     if (printing) {
95433318Sdonn 	printf("\ts%s\t", cname[(int)((inst>>8)&017)]);
95533318Sdonn     }
95633318Sdonn     printea((inst>>3)&07, inst&07, 1);
95733318Sdonn }
95833318Sdonn 
biti(inst,dummy)95933318Sdonn public biti(inst, dummy)
96033318Sdonn long inst;
96133318Sdonn long dummy;
96233318Sdonn {
96333318Sdonn     short w;
96433318Sdonn 
96533318Sdonn     if (printing) {
96633318Sdonn 	printf("\t%s\t", bit[(int)((inst>>6)&03)]);
96733318Sdonn     }
96833318Sdonn     if (inst&0x0100) {
96933318Sdonn 	if (printing) {
97033318Sdonn 	    printf("d%D,", inst>>9);
97133318Sdonn 	}
97233318Sdonn     } else {
97333318Sdonn 	instread(w);
97433318Sdonn 	if (printing) {
97533318Sdonn 	    printf(IMDF, w);
97633318Sdonn 	    printf(",");
97733318Sdonn 	}
97833318Sdonn     }
97933318Sdonn     printEA(inst);
98033318Sdonn }
98133318Sdonn 
opmode(inst,opcode)98233318Sdonn public opmode(inst, opcode)
98333318Sdonn long inst;
98433318Sdonn long opcode;
98533318Sdonn {
98633318Sdonn     register int opmode;
98733318Sdonn     register int reg;
98833318Sdonn     int size;
98933318Sdonn 
99033318Sdonn     opmode = (int)((inst>>6) & 07);
99133318Sdonn     reg = (int)((inst>>9) & 07);
99233318Sdonn     if (opmode == 0 or opmode == 4) {
99333318Sdonn 	size = 1;
99433318Sdonn     } else if (opmode == 1 or opmode == 3 or opmode == 5) {
99533318Sdonn 	size = 2;
99633318Sdonn     } else {
99733318Sdonn 	size = 4;
99833318Sdonn     }
99933318Sdonn     if (printing) {
100033318Sdonn 	printf("\t%s%c\t", opcode, suffix(size));
100133318Sdonn     }
100233318Sdonn     if (opmode >= 4 and opmode <= 6) {
100333318Sdonn 	if (printing) {
100433318Sdonn 	    printf("d%d,", reg);
100533318Sdonn 	}
100633318Sdonn 	printea((inst>>3)&07, inst&07, size);
100733318Sdonn     } else {
100833318Sdonn 	printea((inst>>3)&07, inst&07, size);
100933318Sdonn 	if (printing) {
101033318Sdonn 	    printf(",%c%d",(opmode<=2) ? 'd' : 'a', reg);
101133318Sdonn 	}
101233318Sdonn     }
101333318Sdonn }
101433318Sdonn 
shroi(inst,ds)101533318Sdonn public shroi(inst, ds)
101633318Sdonn long inst;
101733318Sdonn String ds;
101833318Sdonn {
101933318Sdonn     int rx, ry;
102033318Sdonn     String opcode;
102133318Sdonn 
102233318Sdonn     if ((inst & 0xC0) == 0xC0) {
102333318Sdonn 	opcode = shro[(int)((inst>>9)&03)];
102433318Sdonn 	if (printing) {
102533318Sdonn 	    printf("\t%s%s\t", opcode, ds);
102633318Sdonn 	}
102733318Sdonn 	printEA(inst);
102833318Sdonn     } else {
102933318Sdonn 	if (printing) {
103033318Sdonn 	    opcode = shro[(int)((inst>>3)&03)];
103133318Sdonn 	    printf("\t%s%s%c\t", opcode, ds, suffix(mapsize(inst)));
103233318Sdonn 	    rx = (int)((inst>>9)&07); ry = (int)(inst&07);
103333318Sdonn 	    if ((inst>>5)&01) {
103433318Sdonn 		printf("d%d,d%d", rx, ry);
103533318Sdonn 	    } else {
103633318Sdonn 		printf(IMDF, (rx ? rx : 8));
103733318Sdonn 		printf(",d%d", ry);
103833318Sdonn 	    }
103933318Sdonn 	}
104033318Sdonn     }
104133318Sdonn }
104233318Sdonn 
oimmed(inst,opcode)104333318Sdonn public oimmed(inst, opcode)
104433318Sdonn long inst;
104533318Sdonn register String opcode;
104633318Sdonn {
104733318Sdonn     register int size;
104833318Sdonn     long const;
104933318Sdonn     short w;
105033318Sdonn 
105133318Sdonn     size = mapsize(inst);
105233318Sdonn     if (size > 0) {
105333318Sdonn 	if (size == 4) {
105433318Sdonn 	    instread(const);
105533318Sdonn 	} else {
105633318Sdonn 	    instread(w);
105733318Sdonn 	    const = w;
105833318Sdonn 	}
105933318Sdonn 	if (printing) {
106033318Sdonn 	    printf("\t%s%c\t", opcode, suffix(size));
106133318Sdonn 	    printf(IMDF, const);
106233318Sdonn 	    printf(",");
106333318Sdonn 	}
106433318Sdonn 	printEA(inst, size);
106533318Sdonn     } else {
106633318Sdonn 	if (printing) {
106733318Sdonn 	    printf("\tbadop");
106833318Sdonn 	}
106933318Sdonn     }
107033318Sdonn }
107133318Sdonn 
oreg(inst,opcode)107233318Sdonn public oreg(inst, opcode)
107333318Sdonn long inst;
107433318Sdonn register String opcode;
107533318Sdonn {
107633318Sdonn     if (printing) {
107733318Sdonn 	printf(opcode, (inst & 07));
107833318Sdonn     }
107933318Sdonn }
108033318Sdonn 
extend(inst,opcode)108133318Sdonn public extend(inst, opcode)
108233318Sdonn long inst;
108333318Sdonn String opcode;
108433318Sdonn {
108533318Sdonn     register int size;
108633318Sdonn     int ry, rx;
108733318Sdonn     char c;
108833318Sdonn 
108933318Sdonn     if (printing) {
109033318Sdonn 	size = mapsize(inst);
109133318Sdonn 	ry = (inst&07);
109233318Sdonn 	rx = ((inst>>9)&07);
109333318Sdonn 	c = ((inst & 0x1000) ? suffix(size) : ' ');
109433318Sdonn 	printf("\t%s%c\t", opcode, c);
109533318Sdonn 	if (opcode[0] == 'e') {
109633318Sdonn 	    if (inst & 0x0080) {
109733318Sdonn 		printf("d%D,a%D", rx, ry);
109833318Sdonn 	    } else if (inst & 0x0008) {
109933318Sdonn 		printf("a%D,a%D", rx, ry);
110033318Sdonn 	    } else {
110133318Sdonn 		printf("d%D,d%D", rx, ry);
110233318Sdonn 	    }
110333318Sdonn 	} else if ((inst & 0xF000) == 0xB000) {
110433318Sdonn 	    printf("a%D@+,a%D@+", ry, rx);
110533318Sdonn 	} else if (inst & 0x8) {
110633318Sdonn 	    printf("a%D@-,a%D@-", ry, rx);
110733318Sdonn 	} else {
110833318Sdonn 	    printf("d%D,d%D", ry, rx);
110933318Sdonn 	}
111033318Sdonn     }
111133318Sdonn }
111233318Sdonn 
olink(inst,dummy)111333318Sdonn public olink(inst, dummy)
111433318Sdonn long inst;
111533318Sdonn long dummy;
111633318Sdonn {
111733318Sdonn     short w;
111833318Sdonn 
111933318Sdonn     instread(w);
112033318Sdonn     if (printing) {
112133318Sdonn 	printf("\tlink\ta%D,", inst&07);
112233318Sdonn 	printf(IMDF, w);
112333318Sdonn     }
112433318Sdonn }
112533318Sdonn 
otrap(inst,dummy)112633318Sdonn public otrap(inst, dummy)
112733318Sdonn long inst;
112833318Sdonn {
112933318Sdonn     if (printing) {
113033318Sdonn 	printf("\ttrap\t");
113133318Sdonn 	printf(IMDF, inst&017);
113233318Sdonn     }
113333318Sdonn }
113433318Sdonn 
oneop(inst,opcode)113533318Sdonn public oneop(inst, opcode)
113633318Sdonn long inst;
113733318Sdonn register String opcode;
113833318Sdonn {
113933318Sdonn     if (printing) {
114033318Sdonn 	printf("\t%s",opcode);
114133318Sdonn     }
114233318Sdonn     printEA(inst);
114333318Sdonn }
114433318Sdonn 
jsrop(inst,opcode)114533318Sdonn public jsrop(inst, opcode)
114633318Sdonn long inst;
114733318Sdonn register String opcode;
114833318Sdonn {
114933318Sdonn     Address startingaddr;	/* beginning of jsr instruction */
115033318Sdonn     Address retaddr; /* can't call return_addr (frame not set up yet) */
115133318Sdonn 
115233318Sdonn     startingaddr = instaddr - 2;
115333318Sdonn     switch ((inst >> 3) & 07) {
115433318Sdonn 	case 2:
115533318Sdonn 	    retaddr = instaddr;		/* two byte instruction */
115633318Sdonn 	    break;
115733318Sdonn 	case 5:
115833318Sdonn 	case 6:
115933318Sdonn 	    retaddr = instaddr + 2;	/* four byte instruction */
116033318Sdonn 	    break;
116133318Sdonn 	case 7:
116233318Sdonn 	default:
116333318Sdonn 	    switch (inst & 07) {
116433318Sdonn 		case 0:
116533318Sdonn 		case 2:
116633318Sdonn 		case 3:
116733318Sdonn 		    retaddr = instaddr + 2;
116833318Sdonn 		    break;
116933318Sdonn 		case 1:
117033318Sdonn 		default:
117133318Sdonn 		    retaddr = instaddr + 4;	/* six byte instruction */
117233318Sdonn 		    break;
117333318Sdonn 	    }
117433318Sdonn 	    break;
117533318Sdonn     }
117633318Sdonn     if (printing) {
117733318Sdonn 	printf("\t%s",opcode);
117833318Sdonn     }
117933318Sdonn     printEA(inst);
118033318Sdonn     if (following and followcalls) {
118133318Sdonn 	steppast(startingaddr);
118233318Sdonn 	curfunc = whatblock(pc, true);
118333318Sdonn 	if (not isbperr()) {
118433318Sdonn 	    printstatus();
118533318Sdonn 	    /* NOTREACHED */
118633318Sdonn 	}
118733318Sdonn 	bpact();
118833318Sdonn 	if (nosource(curfunc) and canskip(curfunc) and nlhdr.nlines != 0) {
118933318Sdonn 	    stepto(retaddr);
119033318Sdonn 	    instaddr = pc;
119133318Sdonn 	    bpact();
119233318Sdonn 	} else {
119333318Sdonn 	    callnews(/* iscall = */ true);
119433318Sdonn 	}
119533318Sdonn     }
119633318Sdonn }
119733318Sdonn 
jmpop(inst,opcode)119833318Sdonn public jmpop(inst, opcode)
119933318Sdonn long inst;
120033318Sdonn register String opcode;
120133318Sdonn {
120233318Sdonn     Address startingaddr;	/* beginning of jump instruction */
120333318Sdonn 
120433318Sdonn     startingaddr = instaddr - 2;
120533318Sdonn     if (printing) {
120633318Sdonn 	printf("\t%s",opcode);
120733318Sdonn     }
120833318Sdonn     printEA(inst);
120933318Sdonn     if (following) {
121033318Sdonn 	steppast(startingaddr);
121133318Sdonn     }
121233318Sdonn }
121333318Sdonn 
pregmask(mask)121433318Sdonn public pregmask(mask)
121533318Sdonn register int mask;
121633318Sdonn {
121733318Sdonn     register int i;
121833318Sdonn     register int flag = 0;
121933318Sdonn 
122033318Sdonn     if (printing) {
122133318Sdonn 	printf("#<");
122233318Sdonn 	for (i=0; i<16; i++) {
122333318Sdonn 	    if (mask&1) {
122433318Sdonn 		if (flag) {
122533318Sdonn 		    printf(",");
122633318Sdonn 		} else {
122733318Sdonn 		    ++flag;
122833318Sdonn 		}
122933318Sdonn 		printf("%c%d",(i<8) ? 'd' : 'a', i&07);
123033318Sdonn 	    }
123133318Sdonn 	    mask >>= 1;
123233318Sdonn 	}
123333318Sdonn 	printf(">");
123433318Sdonn     }
123533318Sdonn }
123633318Sdonn 
omovem(inst,dummy)123733318Sdonn public omovem(inst, dummy)
123833318Sdonn long inst;
123933318Sdonn long dummy;
124033318Sdonn {
124133318Sdonn     register int i, list, mask;
124233318Sdonn     register int reglist;
124333318Sdonn     short w;
124433318Sdonn 
124533318Sdonn     i = 0;
124633318Sdonn     list = 0;
124733318Sdonn     mask = 0100000;
124833318Sdonn     instread(w);
124933318Sdonn     reglist = w;
125033318Sdonn     if ((inst & 070) == 040) {	/* predecrement */
125133318Sdonn 	for (i = 15; i > 0; i -= 2) {
125233318Sdonn 	    list |= ((mask & reglist) >> i);
125333318Sdonn 	    mask >>= 1;
125433318Sdonn 	}
125533318Sdonn 	for (i = 1; i < 16; i += 2) {
125633318Sdonn 	    list |= ((mask & reglist) << i);
125733318Sdonn 	    mask >>= 1;
125833318Sdonn 	}
125933318Sdonn 	reglist = list;
126033318Sdonn     }
126133318Sdonn     if (printing) {
126233318Sdonn 	printf("\tmovem%c\t",(inst&100)?'l':'w');
126333318Sdonn     }
126433318Sdonn     if (inst&02000) {
126533318Sdonn 	printEA(inst);
126633318Sdonn 	if (printing) {
126733318Sdonn 	    printf(",");
126833318Sdonn 	}
126933318Sdonn 	pregmask(reglist);
127033318Sdonn     } else {
127133318Sdonn 	pregmask(reglist);
127233318Sdonn 	if (printing) {
127333318Sdonn 	    printf(",");
127433318Sdonn 	}
127533318Sdonn 	printEA(inst);
127633318Sdonn     }
127733318Sdonn }
127833318Sdonn 
ochk(inst,opcode)127933318Sdonn public ochk(inst, opcode)
128033318Sdonn long inst;
128133318Sdonn register String opcode;
128233318Sdonn {
128333318Sdonn     if (printing) {
128433318Sdonn 	printf("\t%s\t", opcode);
128533318Sdonn     }
128633318Sdonn     printEA(inst, sizeof(Byte));
128733318Sdonn     if (printing) {
128833318Sdonn 	printf(",%c%D", (opcode[0] == 'l') ? 'a' : 'd', (inst>>9)&07);
128933318Sdonn     }
129033318Sdonn }
129133318Sdonn 
soneop(inst,opcode)129233318Sdonn public soneop(inst, opcode)
129333318Sdonn long inst;
129433318Sdonn register String opcode;
129533318Sdonn {
129633318Sdonn     register int size;
129733318Sdonn 
129833318Sdonn     size = mapsize(inst);
129933318Sdonn     if (size > 0) {
130033318Sdonn 	if (printing) {
130133318Sdonn 	    printf("\t%s%c\t", opcode, suffix(size));
130233318Sdonn 	}
130333318Sdonn 	printEA(inst);
130433318Sdonn     } else {
130533318Sdonn 	if (printing) {
130633318Sdonn 	    printf("\tbadop");
130733318Sdonn 	}
130833318Sdonn     }
130933318Sdonn }
131033318Sdonn 
oquick(inst,opcode)131133318Sdonn public oquick(inst, opcode)
131233318Sdonn long inst;
131333318Sdonn register String opcode;
131433318Sdonn {
131533318Sdonn     register int size;
131633318Sdonn     register int data;
131733318Sdonn 
131833318Sdonn     size = mapsize(inst);
131933318Sdonn     data = (int)((inst>>9) & 07);
132033318Sdonn     if (data == 0) {
132133318Sdonn 	data = 8;
132233318Sdonn     }
132333318Sdonn     if (size > 0) {
132433318Sdonn 	if (printing) {
132533318Sdonn 	    printf("\t%s%c\t", opcode, suffix(size));
132633318Sdonn 	    printf(IMDF, data);
132733318Sdonn 	    printf(",");
132833318Sdonn 	}
132933318Sdonn 	printEA(inst);
133033318Sdonn     } else {
133133318Sdonn 	if (printing) {
133233318Sdonn 	    printf("\tbadop");
133333318Sdonn 	}
133433318Sdonn     }
133533318Sdonn }
133633318Sdonn 
omoveq(inst,dummy)133733318Sdonn public omoveq(inst, dummy)
133833318Sdonn long inst;
133933318Sdonn long dummy;
134033318Sdonn {
134133318Sdonn     register int data;
134233318Sdonn 
134333318Sdonn     if (printing) {
134433318Sdonn 	data = (int)(inst & 0377);
134533318Sdonn 	if (data > 127) {
134633318Sdonn 	    data |= ~0377;
134733318Sdonn 	}
134833318Sdonn 	printf("\tmoveq\t");
134933318Sdonn 	printf(IMDF, data);
135033318Sdonn 	printf(",d%D", (inst>>9)&07);
135133318Sdonn     }
135233318Sdonn }
135333318Sdonn 
oprint(inst,opcode)135433318Sdonn public oprint(inst, opcode)
135533318Sdonn long inst;
135633318Sdonn register String opcode;
135733318Sdonn {
135833318Sdonn     if (printing) {
135933318Sdonn 	printf("\t%s",opcode);
136033318Sdonn     }
136133318Sdonn }
136233318Sdonn 
ostop(inst,opcode)136333318Sdonn public ostop(inst, opcode)
136433318Sdonn long inst;
136533318Sdonn register String opcode;
136633318Sdonn {
136733318Sdonn     short w;
136833318Sdonn 
136933318Sdonn     instread(w);
137033318Sdonn     if (printing) {
137133318Sdonn 	printf(opcode, w);
137233318Sdonn     }
137333318Sdonn }
137433318Sdonn 
orts(inst,opcode)137533318Sdonn public orts(inst, opcode)
137633318Sdonn long inst;
137733318Sdonn register String opcode;
137833318Sdonn {
137933318Sdonn     Address addr;
138033318Sdonn 
138133318Sdonn     if (following) {
138233318Sdonn 	callnews(/* iscall = */ false);
138333318Sdonn     	if (inst_tracing) {
138433318Sdonn 	    addr = currtnaddr();
138533318Sdonn     	} else {
138633318Sdonn 	    addr = return_addr();
138733318Sdonn 	    if (addr == 0) {
138833318Sdonn 		stepto(instaddr - 2);
138933318Sdonn 		addr = currtnaddr();
139033318Sdonn 	    }
139133318Sdonn 	}
139233318Sdonn 	stepto(addr);
139333318Sdonn 	instaddr = pc;
139433318Sdonn     }
139533318Sdonn     if (printing) {
139633318Sdonn 	printf("\t%s",opcode);
139733318Sdonn     }
139833318Sdonn }
139933318Sdonn 
140033318Sdonn /*
140133318Sdonn  * Not used by C compiler; does an rts but before doing so, pops
140233318Sdonn  * arg bytes from the stack.
140333318Sdonn  */
140433318Sdonn 
ortspop(inst,opcode)140533318Sdonn public ortspop(inst, opcode)
140633318Sdonn long inst;
140733318Sdonn register String opcode;
140833318Sdonn {
140933318Sdonn     Address addr;
141033318Sdonn     short w;
141133318Sdonn 
141233318Sdonn     instread(w);
141333318Sdonn     if (following) {
141433318Sdonn 	callnews(/* iscall = */ false);
141533318Sdonn     	if (inst_tracing) {
141633318Sdonn 	    addr = currtnaddr();
141733318Sdonn     	} else {
141833318Sdonn 	    addr = return_addr();
141933318Sdonn 	}
142033318Sdonn 	stepto(addr);
142133318Sdonn 	instaddr = pc;
142233318Sdonn     }
142333318Sdonn     if (printing) {
142433318Sdonn 	printf(opcode, w);
142533318Sdonn     }
142633318Sdonn }
142733318Sdonn 
omovs(inst,opcode)142833318Sdonn public omovs(inst, opcode)
142933318Sdonn long inst;
143033318Sdonn String opcode;
143133318Sdonn {
143233318Sdonn     register int size;
143333318Sdonn     register unsigned int controlword;
143433318Sdonn     short w;
143533318Sdonn 
143633318Sdonn     size = mapsize(inst);
143733318Sdonn     instread(w);
143833318Sdonn     controlword = w >> 11;
143933318Sdonn     if (printing) {
144033318Sdonn 	printf("\t%s%c\t", opcode, suffix(size));
144133318Sdonn     }
144233318Sdonn     if (controlword & 1){
144333318Sdonn 	controlword >>= 1;
144433318Sdonn 	if (printing) {
144533318Sdonn 	    printf((controlword&0x8) ? "a%D," : "d%D,", controlword&7 );
144633318Sdonn 	}
144733318Sdonn 	printEA(inst&0xff, size);
144833318Sdonn     } else {
144933318Sdonn 	controlword >>= 1;
145033318Sdonn 	printEA(inst&0xff, size);
145133318Sdonn 	if (printing) {
145233318Sdonn 	    printf((controlword&0x8) ? ",a%D" : ",d%D", controlword&7);
145333318Sdonn 	}
145433318Sdonn     }
145533318Sdonn }
145633318Sdonn 
omovc(inst,opcode)145733318Sdonn public omovc(inst, opcode)
145833318Sdonn long inst;
145933318Sdonn String opcode;
146033318Sdonn {
146133318Sdonn     register unsigned int controlword;
146233318Sdonn     String creg;
146333318Sdonn     short w;
146433318Sdonn 
146533318Sdonn     instread(w);
146633318Sdonn     if (printing) {
146733318Sdonn 	controlword = w;
146833318Sdonn 	switch (controlword & 0xfff) {
146933318Sdonn 	    case 0:
147033318Sdonn 		creg = "sfc";
147133318Sdonn 		break;
147233318Sdonn 
147333318Sdonn 	    case 1:
147433318Sdonn 		creg = "dfc";
147533318Sdonn 		break;
147633318Sdonn 
147733318Sdonn 	    case 0x800:
147833318Sdonn 		creg = "usp";
147933318Sdonn 		break;
148033318Sdonn 
148133318Sdonn 	    case 0x801:
148233318Sdonn 		creg = "vbr";
148333318Sdonn 		break;
148433318Sdonn 
148533318Sdonn 	    default:
148633318Sdonn 		creg = "???";
148733318Sdonn 		break;
148833318Sdonn 	}
148933318Sdonn 	controlword >>= 12;
149033318Sdonn 	if (inst & 1){
149133318Sdonn 	    printf((controlword&0x8) ? "%sa%D,%s" : "%sd%D,%s",
149233318Sdonn 		opcode, controlword&7, creg );
149333318Sdonn 	} else {
149433318Sdonn 	    printf((controlword&0x8) ? "%s%s,a%D" : "%s%s,d%D",
149533318Sdonn 		opcode, creg, controlword&7 );
149633318Sdonn 	}
149733318Sdonn     }
149833318Sdonn }
149933318Sdonn 
150033318Sdonn /*
150133318Sdonn  * Compute the next address that will be executed from the given one.
150233318Sdonn  * If "isnext" is true then consider a procedure call as straight line code.
150333318Sdonn  *
150433318Sdonn  * Unconditional branches we just follow, for conditional branches
150533318Sdonn  * we continue execution to the current location and then single step
150633318Sdonn  * the machine.
150733318Sdonn  */
150833318Sdonn 
nextaddr(startaddr,isnext)150933318Sdonn public Address nextaddr(startaddr, isnext)
151033318Sdonn Address startaddr;
151133318Sdonn Boolean isnext;
151233318Sdonn {
151333318Sdonn     Optab *o;
151433318Sdonn     short inst;
151533318Sdonn 
151633318Sdonn     instaddr = usignal(process);
151733318Sdonn     if (instaddr == 0 or instaddr == 1) {
151833318Sdonn 	following = true;
151933318Sdonn 	followcalls = (Boolean) (not isnext);
152033318Sdonn 	printing = false;
152133318Sdonn 	iread(&inst, startaddr, sizeof(inst));
152233318Sdonn 	instaddr = startaddr + sizeof(inst);
152333318Sdonn 	o = decode(inst, startaddr);
152433318Sdonn 	if (o->mask == 0) {
152533318Sdonn 	    fprintf(stderr,
152633318Sdonn 		"[internal error: undecodable op at 0x%x]\n", startaddr);
152733318Sdonn 	    fflush(stderr);
152833318Sdonn 	} else {
152933318Sdonn 	    (*o->opfun)(inst, o->farg);
153033318Sdonn 	}
153133318Sdonn 	following = false;
153233318Sdonn     }
153333318Sdonn     return instaddr;
153433318Sdonn }
153533318Sdonn 
153633318Sdonn /*
153733318Sdonn  * Step to the given address and then execute one instruction past it.
153833318Sdonn  * Set instaddr to the new instruction address.
153933318Sdonn  */
154033318Sdonn 
steppast(addr)154133318Sdonn private steppast(addr)
154233318Sdonn Address addr;
154333318Sdonn {
154433318Sdonn     stepto(addr);
154533318Sdonn     pstep(process, DEFSIG);
154633318Sdonn     pc = reg(PROGCTR);
154733318Sdonn     instaddr = pc;
154833318Sdonn }
154933318Sdonn 
155033318Sdonn /*
155133318Sdonn  * Enter a procedure by creating and executing a call instruction.
155233318Sdonn  */
155333318Sdonn 
155433318Sdonn #define CALLSIZE 6	/* size of call instruction */
155533318Sdonn 
beginproc(p)155633318Sdonn public beginproc(p)
155733318Sdonn Symbol p;
155833318Sdonn {
155933318Sdonn     char save[CALLSIZE];
156033318Sdonn     struct {
156133318Sdonn 	short op;
156233318Sdonn 	char addr[sizeof(long)];	/* unaligned long */
156333318Sdonn     } call;
156433318Sdonn     long dest;
156533318Sdonn 
156633318Sdonn     pc = CODESTART + 6;
156733318Sdonn     iread(save, pc, sizeof(save));
156833318Sdonn     call.op = 0x4eb9;			/* jsr */
156933318Sdonn     dest = codeloc(p) - FUNCOFFSET;
157033318Sdonn     mov(&dest, call.addr, sizeof(call.addr));
157133318Sdonn     iwrite(&call, pc, sizeof(call));
157233318Sdonn     setreg(PROGCTR, pc);
157333318Sdonn     pstep(process, DEFSIG);
157433318Sdonn     iwrite(save, pc, sizeof(save));
157533318Sdonn     pc = reg(PROGCTR);
157633318Sdonn     if (not isbperr()) {
157733318Sdonn 	printstatus();
157833318Sdonn     }
157933318Sdonn     /*
158033318Sdonn      * Execute link instruction so the return addr is visible.
158133318Sdonn      */
158233318Sdonn     pstep(process, DEFSIG);
158333318Sdonn     pc = reg(PROGCTR);
158433318Sdonn     if (not isbperr()) {
158533318Sdonn 	printstatus();
158633318Sdonn     }
158733318Sdonn }
158833318Sdonn 
158933318Sdonn /*
159033318Sdonn  * Special variables for debugging the kernel.
159133318Sdonn  */
159233318Sdonn 
159333318Sdonn public integer masterpcbb;
159433318Sdonn public integer slr;
159533318Sdonn public struct pte *sbr;
159633318Sdonn private struct pcb pcb;
159733318Sdonn 
getpcb()159833318Sdonn public getpcb ()
159933318Sdonn {
160033318Sdonn     integer i;
160133318Sdonn 
160233318Sdonn     fseek(corefile, masterpcbb & ~0x80000000, 0);
160333318Sdonn     get(corefile, pcb);
160433318Sdonn     pcb.pcb_p0lr &= ~AST_CLR;
160533318Sdonn     printf("p0br %lx p0lr %lx p1br %lx p1lr %lx\n",
160633318Sdonn 	pcb.pcb_p0br, pcb.pcb_p0lr, pcb.pcb_p1br, pcb.pcb_p1lr
160733318Sdonn     );
160833318Sdonn #   ifdef sun
160933318Sdonn     for (i = 0; i < 14; i++) {
161033318Sdonn 	setreg(i, pcb.pcb_regs.val[i]);
161133318Sdonn     }
161233318Sdonn #   else /* IRIS */
161333318Sdonn     for (i = 0; i < 14; i++) {
161433318Sdonn 	setreg(i, pcb.pcb_regs[i]);
161533318Sdonn     }
161633318Sdonn #   endif
161733318Sdonn }
161833318Sdonn 
copyregs(savreg,reg)161933318Sdonn public copyregs (savreg, reg)
162033318Sdonn Word savreg[], reg[];
162133318Sdonn {
162233318Sdonn     reg[0] = savreg[R0];
162333318Sdonn     reg[1] = savreg[R1];
162433318Sdonn     reg[2] = savreg[R2];
162533318Sdonn     reg[3] = savreg[R3];
162633318Sdonn     reg[4] = savreg[R4];
162733318Sdonn     reg[5] = savreg[R5];
162833318Sdonn     reg[6] = savreg[R6];
162933318Sdonn     reg[7] = savreg[R7];
163033318Sdonn     reg[8] = savreg[AR0];
163133318Sdonn     reg[9] = savreg[AR1];
163233318Sdonn     reg[10] = savreg[AR2];
163333318Sdonn     reg[11] = savreg[AR3];
163433318Sdonn     reg[12] = savreg[AR4];
163533318Sdonn     reg[13] = savreg[AR5];
163633318Sdonn     reg[14] = savreg[AR6];
163733318Sdonn     reg[15] = savreg[AR7];
163833318Sdonn     reg[PROGCTR] = savreg[PC];
163933318Sdonn }
164033318Sdonn 
164133318Sdonn /*
164233318Sdonn  * Map a virtual address to a physical address.
164333318Sdonn  * XXX THIS CAN'T BE RIGHT... XXX
164433318Sdonn  */
164533318Sdonn 
vmap(addr)164633318Sdonn public Address vmap (addr)
164733318Sdonn Address addr;
164833318Sdonn {
164933318Sdonn     Address r;
165033318Sdonn     integer v, n;
165133318Sdonn     struct pte pte;
165233318Sdonn 
165333318Sdonn     r = addr & ~0xc0000000;
165433318Sdonn     v = btop(r);
165533318Sdonn     switch (addr&0xc0000000) {
165633318Sdonn 	case 0xc0000000:
165733318Sdonn 	case 0x80000000:
165833318Sdonn 	    /*
165933318Sdonn 	     * In system space, so get system pte.
166033318Sdonn 	     * If it is valid or reclaimable then the physical address
166133318Sdonn 	     * is the combination of its page number and the page offset
166233318Sdonn 	     * of the original address.
166333318Sdonn 	     */
166433318Sdonn 	    if (v >= slr) {
166533318Sdonn 		error("address %x out of segment", addr);
166633318Sdonn 	    }
166733318Sdonn 	    r = ((long) (sbr + v)) & ~0x80000000;
166833318Sdonn 	    goto simple;
166933318Sdonn 
167033318Sdonn 	case 0x40000000:
167133318Sdonn 	    /*
167233318Sdonn 	     * In p1 space, must not be in shadow region.
167333318Sdonn 	     */
167433318Sdonn 	    if (v < pcb.pcb_p1lr) {
167533318Sdonn 		error("address %x out of segment", addr);
167633318Sdonn 	    }
167733318Sdonn 	    r = (Address) (pcb.pcb_p1br + v);
167833318Sdonn 	    break;
167933318Sdonn 
168033318Sdonn 	case 0x00000000:
168133318Sdonn 	    /*
168233318Sdonn 	     * In p0 space, must not be off end of region.
168333318Sdonn 	     */
168433318Sdonn 	    if (v >= pcb.pcb_p0lr) {
168533318Sdonn 		error("address %x out of segment", addr);
168633318Sdonn 	    }
168733318Sdonn 	    r = (Address) (pcb.pcb_p0br + v);
168833318Sdonn 	    break;
168933318Sdonn 
169033318Sdonn 	default:
169133318Sdonn 	    /* do nothing */
169233318Sdonn 	    break;
169333318Sdonn     }
169433318Sdonn     /*
169533318Sdonn      * For p0/p1 address, user-level page table should be in
169633318Sdonn      * kernel virtual memory.  Do second-level indirect by recursing.
169733318Sdonn      */
169833318Sdonn     if ((r & 0x80000000) == 0) {
169933318Sdonn 	error("bad p0br or p1br in pcb");
170033318Sdonn     }
170133318Sdonn     r = vmap(r);
170233318Sdonn simple:
170333318Sdonn     /*
170433318Sdonn      * "r" is now the address of the pte of the page
170533318Sdonn      * we are interested in; get the pte and paste up the physical address.
170633318Sdonn      */
170733318Sdonn     fseek(corefile, r, 0);
170833318Sdonn     n = fread(&pte, sizeof(pte), 1, corefile);
170933318Sdonn     if (n != 1) {
171033318Sdonn 	error("page table botch (fread at %x returns %d)", r, n);
171133318Sdonn     }
171233318Sdonn     if (pte.pg_v == 0 and (pte.pg_fod != 0 or pte.pg_pfnum == 0)) {
171333318Sdonn 	error("page no valid or reclamable");
171433318Sdonn     }
171533318Sdonn     return (addr&PGOFSET) + ((Address) ptob(pte.pg_pfnum));
171633318Sdonn }
171733318Sdonn 
171833318Sdonn /*
171933318Sdonn  * Extract a bit field from an integer.
172033318Sdonn  */
172133318Sdonn 
extractField(s)172233318Sdonn public integer extractField (s)
172333318Sdonn Symbol s;
172433318Sdonn {
172533318Sdonn     integer nbytes, nbits, n, r, off, len;
172633318Sdonn 
172733318Sdonn     off = s->symvalue.field.offset;
172833318Sdonn     len = s->symvalue.field.length;
172933318Sdonn     nbytes = size(s);
173033318Sdonn     n = 0;
173133318Sdonn     if (nbytes > sizeof(n)) {
173233318Sdonn 	printf("[bad size in extractField -- word assumed]\n");
173333318Sdonn 	nbytes = sizeof(n);
173433318Sdonn     }
173533318Sdonn     popn(nbytes, ((char *) &n) + (sizeof(Word) - nbytes));
173633318Sdonn     nbits = nbytes * BITSPERBYTE;
173733318Sdonn     r = n >> (nbits - ((off mod nbits) + len));
173833318Sdonn     r &= ((1 << len) - 1);
173933318Sdonn     return r;
174033318Sdonn }
174133318Sdonn 
174233318Sdonn /*
174333318Sdonn  * Change the length of a value in memory according to a given difference
174433318Sdonn  * in the lengths of its new and old types.
174533318Sdonn  */
174633318Sdonn 
loophole(oldlen,newlen)174733318Sdonn public loophole (oldlen, newlen)
174833318Sdonn integer oldlen, newlen;
174933318Sdonn {
175033318Sdonn     integer i, n;
175133318Sdonn     Stack *oldsp;
175233318Sdonn 
175333318Sdonn     n = newlen - oldlen;
175433318Sdonn     oldsp = sp - oldlen;
175533318Sdonn     if (n > 0) {
175633318Sdonn 	for (i = oldlen - 1; i >= 0; i--) {
175733318Sdonn 	    oldsp[n + i] = oldsp[i];
175833318Sdonn 	}
175933318Sdonn 	for (i = 0; i < n; i++) {
176033318Sdonn 	    oldsp[i] = '\0';
176133318Sdonn 	}
176233318Sdonn     } else {
176333318Sdonn 	for (i = 0; i < newlen; i++) {
176433318Sdonn 	    oldsp[i] = oldsp[i - n];
176533318Sdonn 	}
176633318Sdonn     }
176733318Sdonn     sp += n;
176833318Sdonn }
1769