xref: /original-bsd/old/dbx/iris.c (revision 1808f06c)
12f00b088Sdonn /*
2be26f981Sbostic  * Copyright (c) 1983 The Regents of the University of California.
3be26f981Sbostic  * All rights reserved.
4be26f981Sbostic  *
5*1808f06cSbostic  * %sccs.include.redist.c%
62f00b088Sdonn  */
72f00b088Sdonn 
82f00b088Sdonn #ifndef lint
9*1808f06cSbostic static char sccsid[] = "@(#)iris.c	5.3 (Berkeley) 06/01/90";
10be26f981Sbostic #endif /* not lint */
112f00b088Sdonn 
122f00b088Sdonn /*
132f00b088Sdonn  * Target machine dependent stuff.
142f00b088Sdonn  */
152f00b088Sdonn 
162f00b088Sdonn #include "defs.h"
172f00b088Sdonn #include "machine.h"
182f00b088Sdonn #include "process.h"
192f00b088Sdonn #include "runtime.h"
202f00b088Sdonn #include "events.h"
212f00b088Sdonn #include "main.h"
222f00b088Sdonn #include "symbols.h"
232f00b088Sdonn #include "source.h"
242f00b088Sdonn #include "mappings.h"
252f00b088Sdonn #include "object.h"
262f00b088Sdonn #include "tree.h"
272f00b088Sdonn #include "eval.h"
282f00b088Sdonn #include "keywords.h"
292f00b088Sdonn #include "ops.h"
302f00b088Sdonn 
312f00b088Sdonn #ifndef public
322f00b088Sdonn typedef unsigned int Address;
332f00b088Sdonn typedef unsigned char Byte;
342f00b088Sdonn typedef unsigned int Word;
352f00b088Sdonn 
362f00b088Sdonn /*
372f00b088Sdonn  * On the 68000, the pc isn't in a register, but we make believe
382f00b088Sdonn  * so there's one more register.
392f00b088Sdonn  *
402f00b088Sdonn  * Note that there's also no argument pointer, this means code
412f00b088Sdonn  * involving "ARGP" should always be #ifdef'd.
422f00b088Sdonn  *
432f00b088Sdonn  * The address corresponding to the beginning of a function is recorded
442f00b088Sdonn  * as the address + FUNCOFFSET (skip the link instruction so that
452f00b088Sdonn  * local information is available).
462f00b088Sdonn  */
472f00b088Sdonn 
482f00b088Sdonn #define NREG 17
492f00b088Sdonn 
502f00b088Sdonn #define FRP 14
512f00b088Sdonn #define STKP 15
522f00b088Sdonn #define PROGCTR 16
532f00b088Sdonn 
542f00b088Sdonn #define CALL_RETADDR	0x800c		/* Return address for 'call' command */
552f00b088Sdonn #define FUNCOFFSET 4
562f00b088Sdonn 
572f00b088Sdonn #ifdef sun
582f00b088Sdonn #    define CODESTART 0x8000
592f00b088Sdonn #else /* IRIS */
602f00b088Sdonn #   define CODESTART 0x1000
612f00b088Sdonn #endif
622f00b088Sdonn 
632f00b088Sdonn #define optab_init()
642f00b088Sdonn 
652f00b088Sdonn #define BITSPERBYTE 8
662f00b088Sdonn #define BITSPERWORD (BITSPERBYTE * sizeof(Word))
672f00b088Sdonn 
682f00b088Sdonn /*
692f00b088Sdonn  * This magic macro enables us to look at the process' registers
702f00b088Sdonn  * in its user structure.
712f00b088Sdonn  */
722f00b088Sdonn 
732f00b088Sdonn #define regloc(reg)	(ctob(UPAGES) + (sizeof(Word) * ((reg) - PC)) - 10)
742f00b088Sdonn 
752f00b088Sdonn #include "source.h"
762f00b088Sdonn #include "symbols.h"
772f00b088Sdonn #include <signal.h>
782f00b088Sdonn #include <sys/param.h>
792f00b088Sdonn #include <sys/dir.h>
802f00b088Sdonn #include <machine/psl.h>
812f00b088Sdonn #include <machine/pte.h>
822f00b088Sdonn #include <sys/user.h>
832f00b088Sdonn #undef DELETE /* XXX */
842f00b088Sdonn #include <sys/vm.h>
852f00b088Sdonn #include <machine/reg.h>
862f00b088Sdonn 
872f00b088Sdonn Address pc;
882f00b088Sdonn Address prtaddr;
892f00b088Sdonn 
902f00b088Sdonn #endif
912f00b088Sdonn 
922f00b088Sdonn /*
932f00b088Sdonn  * Indices into u. for use in collecting registers values.
942f00b088Sdonn  */
952f00b088Sdonn public int rloc[] ={
962f00b088Sdonn #ifdef sun
972f00b088Sdonn     R0, R1, R2, R3, R4, R5, R6, R7, AR0, AR1, AR2, AR3, AR4, AR5, AR6, AR7, PC
982f00b088Sdonn #else /* IRIS */
992f00b088Sdonn     R0, R1, R2, R3, R4, R5, R6, R7, AR0, AR1, AR2, AR3, AR4, AR5, AR6, AR7, 16
1002f00b088Sdonn #endif
1012f00b088Sdonn };
1022f00b088Sdonn 
1032f00b088Sdonn private Address printop();
1042f00b088Sdonn 
1052f00b088Sdonn /*
1062f00b088Sdonn  * Decode and print the instructions within the given address range.
1072f00b088Sdonn  */
1082f00b088Sdonn 
printinst(lowaddr,highaddr)1092f00b088Sdonn public printinst(lowaddr, highaddr)
1102f00b088Sdonn Address lowaddr;
1112f00b088Sdonn Address highaddr;
1122f00b088Sdonn {
1132f00b088Sdonn     register Address addr;
1142f00b088Sdonn 
1152f00b088Sdonn     for (addr = lowaddr; addr <= highaddr; ) {
1162f00b088Sdonn 	addr = printop(addr);
1172f00b088Sdonn     }
1182f00b088Sdonn     prtaddr = addr;
1192f00b088Sdonn }
1202f00b088Sdonn 
1212f00b088Sdonn /*
1222f00b088Sdonn  * Another approach:  print n instructions starting at the given address.
1232f00b088Sdonn  */
1242f00b088Sdonn 
printninst(count,addr)1252f00b088Sdonn public printninst(count, addr)
1262f00b088Sdonn int count;
1272f00b088Sdonn Address addr;
1282f00b088Sdonn {
1292f00b088Sdonn     register Integer i;
1302f00b088Sdonn     register Address newaddr;
1312f00b088Sdonn 
1322f00b088Sdonn     if (count <= 0) {
1332f00b088Sdonn 	error("non-positive repetition count");
1342f00b088Sdonn     } else {
1352f00b088Sdonn 	newaddr = addr;
1362f00b088Sdonn 	for (i = 0; i < count; i++) {
1372f00b088Sdonn 	    newaddr = printop(newaddr);
1382f00b088Sdonn 	}
1392f00b088Sdonn 	prtaddr = newaddr;
1402f00b088Sdonn     }
1412f00b088Sdonn }
1422f00b088Sdonn 
1432f00b088Sdonn /*
1442f00b088Sdonn  * Print the contents of the addresses within the given range
1452f00b088Sdonn  * according to the given format.
1462f00b088Sdonn  */
1472f00b088Sdonn 
1482f00b088Sdonn typedef struct {
1492f00b088Sdonn     String name;
1502f00b088Sdonn     String printfstring;
1512f00b088Sdonn     int length;
1522f00b088Sdonn } Format;
1532f00b088Sdonn 
1542f00b088Sdonn private Format fmt[] = {
1552f00b088Sdonn     { "d", " %d", sizeof(short) },
1562f00b088Sdonn     { "D", " %ld", sizeof(long) },
1572f00b088Sdonn     { "o", " %o", sizeof(short) },
1582f00b088Sdonn     { "O", " %lo", sizeof(long) },
1592f00b088Sdonn     { "x", " %04x", sizeof(short) },
1602f00b088Sdonn     { "X", " %08x", sizeof(long) },
1612f00b088Sdonn     { "b", " \\%o", sizeof(char) },
1622f00b088Sdonn     { "c", " '%c'", sizeof(char) },
1632f00b088Sdonn     { "s", "%c", sizeof(char) },
1642f00b088Sdonn     { "f", " %f", sizeof(float) },
1652f00b088Sdonn     { "g", " %g", sizeof(double) },
1662f00b088Sdonn     { nil, nil, 0 }
1672f00b088Sdonn };
1682f00b088Sdonn 
findformat(s)1692f00b088Sdonn private Format *findformat(s)
1702f00b088Sdonn String s;
1712f00b088Sdonn {
1722f00b088Sdonn     register Format *f;
1732f00b088Sdonn 
1742f00b088Sdonn     f = &fmt[0];
1752f00b088Sdonn     while (f->name != nil and not streq(f->name, s)) {
1762f00b088Sdonn 	++f;
1772f00b088Sdonn     }
1782f00b088Sdonn     if (f->name == nil) {
1792f00b088Sdonn 	error("bad print format \"%s\"", s);
1802f00b088Sdonn     }
1812f00b088Sdonn     return f;
1822f00b088Sdonn }
1832f00b088Sdonn 
1842f00b088Sdonn /*
1852f00b088Sdonn  * Retrieve and print out the appropriate data in the given format.
1862f00b088Sdonn  * Floats have to be handled specially to allow the compiler to
1872f00b088Sdonn  * convert them to doubles when passing to printf.
1882f00b088Sdonn  */
1892f00b088Sdonn 
printformat(f,addr)1902f00b088Sdonn private printformat (f, addr)
1912f00b088Sdonn Format *f;
1922f00b088Sdonn Address addr;
1932f00b088Sdonn {
1942f00b088Sdonn     union {
1952f00b088Sdonn 	char charv;
1962f00b088Sdonn 	short shortv;
1972f00b088Sdonn 	int intv;
1982f00b088Sdonn 	float floatv;
1992f00b088Sdonn 	double doublev;
2002f00b088Sdonn     } value;
2012f00b088Sdonn 
2022f00b088Sdonn     value.intv = 0;
2032f00b088Sdonn     dread(&value, addr, f->length);
2042f00b088Sdonn     if (streq(f->name, "f")) {
2052f00b088Sdonn 	printf(f->printfstring, value.floatv);
2062f00b088Sdonn     } else {
2072f00b088Sdonn 	printf(f->printfstring, value);
2082f00b088Sdonn     }
2092f00b088Sdonn }
2102f00b088Sdonn 
printdata(lowaddr,highaddr,format)2112f00b088Sdonn public Address printdata(lowaddr, highaddr, format)
2122f00b088Sdonn Address lowaddr;
2132f00b088Sdonn Address highaddr;
2142f00b088Sdonn String format;
2152f00b088Sdonn {
2162f00b088Sdonn     int n;
2172f00b088Sdonn     register Address addr;
2182f00b088Sdonn     Format *f;
2192f00b088Sdonn 
2202f00b088Sdonn     if (lowaddr > highaddr) {
2212f00b088Sdonn 	error("first address larger than second");
2222f00b088Sdonn     }
2232f00b088Sdonn     f = findformat(format);
2242f00b088Sdonn     n = 0;
2252f00b088Sdonn     for (addr = lowaddr; addr <= highaddr; addr += f->length) {
2262f00b088Sdonn 	if (n == 0) {
2272f00b088Sdonn 	    printf("%08x: ", addr);
2282f00b088Sdonn 	}
2292f00b088Sdonn 	printformat(f, addr);
2302f00b088Sdonn 	++n;
2312f00b088Sdonn 	if (n >= (16 div f->length)) {
2322f00b088Sdonn 	    printf("\n");
2332f00b088Sdonn 	    n = 0;
2342f00b088Sdonn 	}
2352f00b088Sdonn     }
2362f00b088Sdonn     if (n != 0) {
2372f00b088Sdonn 	printf("\n");
2382f00b088Sdonn     }
2392f00b088Sdonn     prtaddr = addr;
2402f00b088Sdonn     return addr;
2412f00b088Sdonn }
2422f00b088Sdonn 
2432f00b088Sdonn /*
2442f00b088Sdonn  * The other approach is to print n items starting with a given address.
2452f00b088Sdonn  */
2462f00b088Sdonn 
printndata(count,startaddr,format)2472f00b088Sdonn public printndata(count, startaddr, format)
2482f00b088Sdonn int count;
2492f00b088Sdonn Address startaddr;
2502f00b088Sdonn String format;
2512f00b088Sdonn {
2522f00b088Sdonn     int i, n;
2532f00b088Sdonn     Address addr;
2542f00b088Sdonn     Format *f;
2552f00b088Sdonn     Boolean isstring;
2562f00b088Sdonn     char c;
2572f00b088Sdonn 
2582f00b088Sdonn     if (count <= 0) {
2592f00b088Sdonn 	error("non-positive repetition count");
2602f00b088Sdonn     }
2612f00b088Sdonn     f = findformat(format);
2622f00b088Sdonn     isstring = (Boolean) streq(f->name, "s");
2632f00b088Sdonn     n = 0;
2642f00b088Sdonn     addr = startaddr;
2652f00b088Sdonn     for (i = 0; i < count; i++) {
2662f00b088Sdonn 	if (n == 0) {
2672f00b088Sdonn 	    printf("%08x: ", addr);
2682f00b088Sdonn 	}
2692f00b088Sdonn 	if (isstring) {
2702f00b088Sdonn 	    printf("\"");
2712f00b088Sdonn 	    dread(&c, addr, sizeof(char));
2722f00b088Sdonn 	    while (c != '\0') {
2732f00b088Sdonn 		printchar(c);
2742f00b088Sdonn 		++addr;
2752f00b088Sdonn 		dread(&c, addr, sizeof(char));
2762f00b088Sdonn 	    }
2772f00b088Sdonn 	    printf("\"\n");
2782f00b088Sdonn 	    n = 0;
2792f00b088Sdonn 	    addr += sizeof(String);
2802f00b088Sdonn 	} else {
2812f00b088Sdonn 	    printformat(f, addr);
2822f00b088Sdonn 	    ++n;
2832f00b088Sdonn 	    if (n >= (16 div f->length)) {
2842f00b088Sdonn 		printf("\n");
2852f00b088Sdonn 		n = 0;
2862f00b088Sdonn 	    }
2872f00b088Sdonn 	    addr += f->length;
2882f00b088Sdonn 	}
2892f00b088Sdonn     }
2902f00b088Sdonn     if (n != 0) {
2912f00b088Sdonn 	printf("\n");
2922f00b088Sdonn     }
2932f00b088Sdonn     prtaddr = addr;
2942f00b088Sdonn }
2952f00b088Sdonn 
2962f00b088Sdonn /*
2972f00b088Sdonn  * Print out a value according to the given format.
2982f00b088Sdonn  */
2992f00b088Sdonn 
printvalue(v,format)3002f00b088Sdonn public printvalue(v, format)
3012f00b088Sdonn long v;
3022f00b088Sdonn String format;
3032f00b088Sdonn {
3042f00b088Sdonn     Format *f;
3052f00b088Sdonn     char *p, *q;
3062f00b088Sdonn 
3072f00b088Sdonn     f = findformat(format);
3082f00b088Sdonn     if (streq(f->name, "s")) {
3092f00b088Sdonn 	putchar('"');
3102f00b088Sdonn 	p = (char *) &v;
3112f00b088Sdonn 	q = p + sizeof(v);
3122f00b088Sdonn 	while (p < q) {
3132f00b088Sdonn 	    printchar(*p);
3142f00b088Sdonn 	    ++p;
3152f00b088Sdonn 	}
3162f00b088Sdonn 	putchar('"');
3172f00b088Sdonn     } else {
3182f00b088Sdonn 	printf(f->printfstring, v);
3192f00b088Sdonn     }
3202f00b088Sdonn     putchar('\n');
3212f00b088Sdonn }
3222f00b088Sdonn 
3232f00b088Sdonn /*
3242f00b088Sdonn  * Print out an execution time error.
3252f00b088Sdonn  * Assumes the source position of the error has been calculated.
3262f00b088Sdonn  *
3272f00b088Sdonn  * Have to check if the -r option was specified; if so then
3282f00b088Sdonn  * the object file information hasn't been read in yet.
3292f00b088Sdonn  */
3302f00b088Sdonn 
printerror()3312f00b088Sdonn public printerror()
3322f00b088Sdonn {
3332f00b088Sdonn     extern Integer sys_nsig;
3342f00b088Sdonn     extern String sys_siglist[];
3352f00b088Sdonn     integer err;
3362f00b088Sdonn 
3372f00b088Sdonn     if (isfinished(process)) {
3382f00b088Sdonn 	err = exitcode(process);
3392f00b088Sdonn 	if (err == 0) {
3402f00b088Sdonn 	    printf("\"%s\" terminated normally\n", objname);
3412f00b088Sdonn 	} else {
3422f00b088Sdonn 	    printf("\"%s\" terminated abnormally (exit code %d)\n",
3432f00b088Sdonn 		objname, err
3442f00b088Sdonn 	    );
3452f00b088Sdonn 	}
3462f00b088Sdonn 	erecover();
3472f00b088Sdonn     }
3482f00b088Sdonn     err = errnum(process);
3492f00b088Sdonn     putchar('\n');
3502f00b088Sdonn     printsig(err);
3512f00b088Sdonn     putchar(' ');
3522f00b088Sdonn     printloc();
3532f00b088Sdonn     putchar('\n');
3542f00b088Sdonn     if (curline > 0) {
3552f00b088Sdonn 	printlines(curline, curline);
3562f00b088Sdonn     } else {
3572f00b088Sdonn 	printinst(pc, pc);
3582f00b088Sdonn     }
3592f00b088Sdonn     erecover();
3602f00b088Sdonn }
3612f00b088Sdonn 
3622f00b088Sdonn /*
3632f00b088Sdonn  * Print out a signal.
3642f00b088Sdonn  */
3652f00b088Sdonn 
3662f00b088Sdonn private String illinames[] = {
3672f00b088Sdonn     "reserved addressing fault",
3682f00b088Sdonn     "privileged instruction fault",
3692f00b088Sdonn     "reserved operand fault"
3702f00b088Sdonn };
3712f00b088Sdonn 
3722f00b088Sdonn private String fpenames[] = {
3732f00b088Sdonn     nil,
3742f00b088Sdonn     "integer overflow trap",
3752f00b088Sdonn     "integer divide by zero trap",
3762f00b088Sdonn     "floating overflow trap",
3772f00b088Sdonn     "floating/decimal divide by zero trap",
3782f00b088Sdonn     "floating underflow trap",
3792f00b088Sdonn     "decimal overflow trap",
3802f00b088Sdonn     "subscript out of range trap",
3812f00b088Sdonn     "floating overflow fault",
3822f00b088Sdonn     "floating divide by zero fault",
3832f00b088Sdonn     "floating underflow fault"
3842f00b088Sdonn };
3852f00b088Sdonn 
printsig(signo)3862f00b088Sdonn public printsig (signo)
3872f00b088Sdonn integer signo;
3882f00b088Sdonn {
3892f00b088Sdonn     integer code;
3902f00b088Sdonn 
3912f00b088Sdonn     if (signo < 0 or signo > sys_nsig) {
3922f00b088Sdonn 	printf("[signal %d]", signo);
3932f00b088Sdonn     } else {
3942f00b088Sdonn 	printf("%s", sys_siglist[signo]);
3952f00b088Sdonn     }
3962f00b088Sdonn     code = errcode(process);
3972f00b088Sdonn     if (signo == SIGILL) {
3982f00b088Sdonn 	if (code >= 0 and code < sizeof(illinames) / sizeof(illinames[0])) {
3992f00b088Sdonn 	    printf(" (%s)", illinames[code]);
4002f00b088Sdonn 	}
4012f00b088Sdonn     } else if (signo == SIGFPE) {
4022f00b088Sdonn 	if (code > 0 and code < sizeof(fpenames) / sizeof(fpenames[0])) {
4032f00b088Sdonn 	    printf(" (%s)", fpenames[code]);
4042f00b088Sdonn 	}
4052f00b088Sdonn     }
4062f00b088Sdonn }
4072f00b088Sdonn 
4082f00b088Sdonn /*
4092f00b088Sdonn  * Note the termination of the program.  We do this so as to avoid
4102f00b088Sdonn  * having the process exit, which would make the values of variables
4112f00b088Sdonn  * inaccessible.  We do want to flush all output buffers here,
4122f00b088Sdonn  * otherwise it'll never get done.
4132f00b088Sdonn  */
4142f00b088Sdonn 
endprogram()4152f00b088Sdonn public endprogram()
4162f00b088Sdonn {
4172f00b088Sdonn     Integer exitcode;
4182f00b088Sdonn 
4192f00b088Sdonn     stepto(nextaddr(pc, true));
4202f00b088Sdonn     printnews();
4212f00b088Sdonn     exitcode = argn(1, nil);
4222f00b088Sdonn     if (exitcode != 0) {
4232f00b088Sdonn 	printf("\nexecution completed (exit code %d)\n", exitcode);
4242f00b088Sdonn     } else {
4252f00b088Sdonn 	printf("\nexecution completed\n");
4262f00b088Sdonn     }
4272f00b088Sdonn     getsrcpos();
4282f00b088Sdonn     erecover();
4292f00b088Sdonn }
4302f00b088Sdonn 
4312f00b088Sdonn /*
4322f00b088Sdonn  * Single step the machine a source line (or instruction if "inst_tracing"
4332f00b088Sdonn  * is true).  If "isnext" is true, skip over procedure calls.
4342f00b088Sdonn  */
4352f00b088Sdonn 
4362f00b088Sdonn private Address getcall();
4372f00b088Sdonn 
dostep(isnext)4382f00b088Sdonn public dostep(isnext)
4392f00b088Sdonn Boolean isnext;
4402f00b088Sdonn {
4412f00b088Sdonn     register Address addr;
4422f00b088Sdonn     register Lineno line;
4432f00b088Sdonn     String filename;
4442f00b088Sdonn     Address startaddr;
4452f00b088Sdonn 
4462f00b088Sdonn     startaddr = pc;
4472f00b088Sdonn     addr = nextaddr(pc, isnext);
4482f00b088Sdonn     if (not inst_tracing and nlhdr.nlines != 0) {
4492f00b088Sdonn 	line = linelookup(addr);
4502f00b088Sdonn 	while (line == 0) {
4512f00b088Sdonn 	    addr = nextaddr(addr, isnext);
4522f00b088Sdonn 	    line = linelookup(addr);
4532f00b088Sdonn 	}
4542f00b088Sdonn 	curline = line;
4552f00b088Sdonn     } else {
4562f00b088Sdonn 	curline = 0;
4572f00b088Sdonn     }
4582f00b088Sdonn     stepto(addr);
4592f00b088Sdonn     filename = srcfilename(addr);
4602f00b088Sdonn     setsource(filename);
4612f00b088Sdonn }
4622f00b088Sdonn 
4632f00b088Sdonn typedef short Bpinst;
4642f00b088Sdonn 
4652f00b088Sdonn extern Bpinst BP_OP;
4662f00b088Sdonn #ifdef sun
4672f00b088Sdonn 	asm("_BP_OP: trap #15");
4682f00b088Sdonn #else /* IRIS */
4692f00b088Sdonn 	asm("_BP_OP: trap #1");
4702f00b088Sdonn #endif
4712f00b088Sdonn 
4722f00b088Sdonn #define BP_ERRNO    SIGTRAP     /* signal received at a breakpoint */
4732f00b088Sdonn 
4742f00b088Sdonn /*
4752f00b088Sdonn  * Setting a breakpoint at a location consists of saving
4762f00b088Sdonn  * the word at the location and poking a BP_OP there.
4772f00b088Sdonn  *
4782f00b088Sdonn  * We save the locations and words on a list for use in unsetting.
4792f00b088Sdonn  */
4802f00b088Sdonn 
4812f00b088Sdonn typedef struct Savelist *Savelist;
4822f00b088Sdonn 
4832f00b088Sdonn struct Savelist {
4842f00b088Sdonn     Address location;
4852f00b088Sdonn     Bpinst save;
4862f00b088Sdonn     short refcount;
4872f00b088Sdonn     Savelist link;
4882f00b088Sdonn };
4892f00b088Sdonn 
4902f00b088Sdonn private Savelist savelist;
4912f00b088Sdonn 
4922f00b088Sdonn /*
4932f00b088Sdonn  * Set a breakpoint at the given address.  Only save the word there
4942f00b088Sdonn  * if it's not already a breakpoint.
4952f00b088Sdonn  */
4962f00b088Sdonn 
setbp(addr)4972f00b088Sdonn public setbp(addr)
4982f00b088Sdonn Address addr;
4992f00b088Sdonn {
5002f00b088Sdonn     Bpinst w, save;
5012f00b088Sdonn     register Savelist newsave, s;
5022f00b088Sdonn 
5032f00b088Sdonn     for (s = savelist; s != nil; s = s->link) {
5042f00b088Sdonn 	if (s->location == addr) {
5052f00b088Sdonn 	    s->refcount++;
5062f00b088Sdonn 	    return;
5072f00b088Sdonn 	}
5082f00b088Sdonn     }
5092f00b088Sdonn     iread(&save, addr, sizeof(save));
5102f00b088Sdonn     newsave = new(Savelist);
5112f00b088Sdonn     newsave->location = addr;
5122f00b088Sdonn     newsave->save = save;
5132f00b088Sdonn     newsave->refcount = 1;
5142f00b088Sdonn     newsave->link = savelist;
5152f00b088Sdonn     savelist = newsave;
5162f00b088Sdonn     w = BP_OP;
5172f00b088Sdonn     iwrite(&w, addr, sizeof(w));
5182f00b088Sdonn }
5192f00b088Sdonn 
5202f00b088Sdonn /*
5212f00b088Sdonn  * Unset a breakpoint; unfortunately we have to search the SAVELIST
5222f00b088Sdonn  * to find the saved value.  The assumption is that the SAVELIST will
5232f00b088Sdonn  * usually be quite small.
5242f00b088Sdonn  */
5252f00b088Sdonn 
unsetbp(addr)5262f00b088Sdonn public unsetbp(addr)
5272f00b088Sdonn Address addr;
5282f00b088Sdonn {
5292f00b088Sdonn     register Savelist s, prev;
5302f00b088Sdonn 
5312f00b088Sdonn     prev = nil;
5322f00b088Sdonn     for (s = savelist; s != nil; s = s->link) {
5332f00b088Sdonn 	if (s->location == addr) {
5342f00b088Sdonn 	    iwrite(&s->save, addr, sizeof(s->save));
5352f00b088Sdonn 	    s->refcount--;
5362f00b088Sdonn 	    if (s->refcount == 0) {
5372f00b088Sdonn 		if (prev == nil) {
5382f00b088Sdonn 		    savelist = s->link;
5392f00b088Sdonn 		} else {
5402f00b088Sdonn 		    prev->link = s->link;
5412f00b088Sdonn 		}
5422f00b088Sdonn 		dispose(s);
5432f00b088Sdonn 	    }
5442f00b088Sdonn 	    return;
5452f00b088Sdonn 	}
5462f00b088Sdonn 	prev = s;
5472f00b088Sdonn     }
5482f00b088Sdonn     panic("unsetbp: couldn't find address %d", addr);
5492f00b088Sdonn }
5502f00b088Sdonn 
5512f00b088Sdonn /*
5522f00b088Sdonn  * Instruction decoding routines for 68000, derived from adb.
5532f00b088Sdonn  *
5542f00b088Sdonn  * The shared boolean variable "printing" is true if the decoded
5552f00b088Sdonn  * instruction is to be printed, false if not.  In either case,
5562f00b088Sdonn  * the address of the next instruction after the given one is returned.
5572f00b088Sdonn  */
5582f00b088Sdonn 
5592f00b088Sdonn private Boolean printing;
5602f00b088Sdonn private Boolean following;
5612f00b088Sdonn private Boolean followcalls;
5622f00b088Sdonn private Address instaddr;
5632f00b088Sdonn 
5642f00b088Sdonn #define instread(var) \
5652f00b088Sdonn { \
5662f00b088Sdonn     iread(&var, instaddr, sizeof(var)); \
5672f00b088Sdonn     instaddr += sizeof(var); \
5682f00b088Sdonn }
5692f00b088Sdonn 
decode(inst,addr)5702f00b088Sdonn private Optab *decode(inst, addr)
5712f00b088Sdonn Word inst;
5722f00b088Sdonn Address addr;
5732f00b088Sdonn {
5742f00b088Sdonn     register Optab *o;
5752f00b088Sdonn 
5762f00b088Sdonn     o = &optab[0];
5772f00b088Sdonn     while (o->mask != 0 and (inst&o->mask) != o->match) {
5782f00b088Sdonn 	++o;
5792f00b088Sdonn     }
5802f00b088Sdonn     return o;
5812f00b088Sdonn }
5822f00b088Sdonn 
printop(addr)5832f00b088Sdonn private Address printop(addr)
5842f00b088Sdonn Address addr;
5852f00b088Sdonn {
5862f00b088Sdonn     Optab *o;
5872f00b088Sdonn     short inst;
5882f00b088Sdonn 
5892f00b088Sdonn     printf("%08x  ", addr);
5902f00b088Sdonn     iread(&inst, addr, sizeof(inst));
5912f00b088Sdonn     o = decode(inst, addr);
5922f00b088Sdonn     if (o->mask == 0) {
5932f00b088Sdonn 	printf("\tbadop");
5942f00b088Sdonn 	instaddr = addr + sizeof(inst);
5952f00b088Sdonn     } else {
5962f00b088Sdonn 	printing = true;
5972f00b088Sdonn 	following = false;
5982f00b088Sdonn 	instaddr = addr + sizeof(inst);
5992f00b088Sdonn 	(*o->opfun)(inst, o->farg);
6002f00b088Sdonn 	printing = false;
6012f00b088Sdonn     }
6022f00b088Sdonn     printf("\n");
6032f00b088Sdonn     return instaddr;
6042f00b088Sdonn }
6052f00b088Sdonn 
6062f00b088Sdonn /*
6072f00b088Sdonn  * Quickly find the return address of the current procedure or function
6082f00b088Sdonn  * while single stepping.  Just get the word pointed at by sp.
6092f00b088Sdonn  */
6102f00b088Sdonn 
currtnaddr()6112f00b088Sdonn private Address currtnaddr ()
6122f00b088Sdonn {
6132f00b088Sdonn     Address retaddr;
6142f00b088Sdonn 
6152f00b088Sdonn     dread(&retaddr, reg(STKP), sizeof(retaddr));
6162f00b088Sdonn     return retaddr;
6172f00b088Sdonn }
6182f00b088Sdonn 
6192f00b088Sdonn /*
6202f00b088Sdonn  * Print out the effective address for the given parameters.
6212f00b088Sdonn  */
6222f00b088Sdonn 
printea(mode,reg,size)6232f00b088Sdonn private printea(mode, reg, size)
6242f00b088Sdonn long mode, reg;
6252f00b088Sdonn int size;
6262f00b088Sdonn {
6272f00b088Sdonn     long index, disp;
6282f00b088Sdonn     static char *aregs[] = { "a0", "a1", "a2", "a3", "a4", "a5", "a6", "sp" };
6292f00b088Sdonn     Byte b;
6302f00b088Sdonn     short w;
6312f00b088Sdonn     long l;
6322f00b088Sdonn 
6332f00b088Sdonn     switch ((int)(mode)) {
6342f00b088Sdonn 	case 0:
6352f00b088Sdonn 	    if (printing) {
6362f00b088Sdonn 		printf("d%D", reg);
6372f00b088Sdonn 	    }
6382f00b088Sdonn 	    break;
6392f00b088Sdonn 
6402f00b088Sdonn 	case 1:
6412f00b088Sdonn 	    if (printing) {
6422f00b088Sdonn 		printf("%s", aregs[reg]);
6432f00b088Sdonn 	    }
6442f00b088Sdonn 	    break;
6452f00b088Sdonn 
6462f00b088Sdonn 	case 2:
6472f00b088Sdonn 	    if (printing) {
6482f00b088Sdonn 		printf("%s@", aregs[reg]);
6492f00b088Sdonn 	    }
6502f00b088Sdonn 	    break;
6512f00b088Sdonn 
6522f00b088Sdonn 	case 3:
6532f00b088Sdonn 	    if (printing) {
6542f00b088Sdonn 		printf("%s@+", aregs[reg]);
6552f00b088Sdonn 	    }
6562f00b088Sdonn 	    break;
6572f00b088Sdonn 
6582f00b088Sdonn 	case 4:
6592f00b088Sdonn 	    if (printing) {
6602f00b088Sdonn 		printf("%s@-", aregs[reg]);
6612f00b088Sdonn 	    }
6622f00b088Sdonn 	    break;
6632f00b088Sdonn 
6642f00b088Sdonn 	case 5:
6652f00b088Sdonn 	    instread(w);
6662f00b088Sdonn 	    if (printing) {
6672f00b088Sdonn 		printf("%s@(%D)", aregs[reg], w);
6682f00b088Sdonn 	    }
6692f00b088Sdonn 	    break;
6702f00b088Sdonn 
6712f00b088Sdonn 	case 6:
6722f00b088Sdonn 	    instread(w);
6732f00b088Sdonn 	    if (printing) {
6742f00b088Sdonn 		index = w;
6752f00b088Sdonn 		disp = (char)(index&0377);
6762f00b088Sdonn 		printf("%s@(%d,%c%D:%c)", aregs[reg], disp,
6772f00b088Sdonn 		    (index&0100000)?'a':'d',(index>>12)&07,
6782f00b088Sdonn 		    (index&04000)?'l':'w');
6792f00b088Sdonn 	    }
6802f00b088Sdonn 	    break;
6812f00b088Sdonn 
6822f00b088Sdonn 	case 7:
6832f00b088Sdonn 	    switch ((int)(reg)) {
6842f00b088Sdonn 		case 0:
6852f00b088Sdonn 		    instread(w);
6862f00b088Sdonn 		    if (printing) {
6872f00b088Sdonn 			index = w;
6882f00b088Sdonn 			psymoff(index);
6892f00b088Sdonn 		    }
6902f00b088Sdonn 		    break;
6912f00b088Sdonn 
6922f00b088Sdonn 		case 1:
6932f00b088Sdonn 		    instread(l);
6942f00b088Sdonn 		    if (printing) {
6952f00b088Sdonn 			index = l;
6962f00b088Sdonn 			psymoff(index);
6972f00b088Sdonn 		    }
6982f00b088Sdonn 		    break;
6992f00b088Sdonn 
7002f00b088Sdonn 		case 2:
7012f00b088Sdonn 		    instread(w);
7022f00b088Sdonn 		    if (printing) {
7032f00b088Sdonn 			disp = w;
7042f00b088Sdonn 			psymoff(disp + instaddr);
7052f00b088Sdonn 		    }
7062f00b088Sdonn 		    break;
7072f00b088Sdonn 
7082f00b088Sdonn 		case 3:
7092f00b088Sdonn 		    instread(w);
7102f00b088Sdonn 		    if (printing) {
7112f00b088Sdonn 			index = w;
7122f00b088Sdonn 			disp = (char)(index&0377);
7132f00b088Sdonn 			printf("pc@(%D,%c%D:%c)", disp,
7142f00b088Sdonn 			    (index&0100000)?'a':'d',(index>>12)&07,
7152f00b088Sdonn 			    (index&04000)?'l':'w');
7162f00b088Sdonn 		    }
7172f00b088Sdonn 		    break;
7182f00b088Sdonn 
7192f00b088Sdonn 		case 4:
7202f00b088Sdonn 		    switch (size) {
7212f00b088Sdonn 			case sizeof(b):
7222f00b088Sdonn 			    instread(w);
7232f00b088Sdonn 			    index = (w&0xff);
7242f00b088Sdonn 			    break;
7252f00b088Sdonn 
7262f00b088Sdonn 			case sizeof(w):
7272f00b088Sdonn 			    instread(w);
7282f00b088Sdonn 			    index = w;
7292f00b088Sdonn 			    break;
7302f00b088Sdonn 
7312f00b088Sdonn 			case sizeof(l):
7322f00b088Sdonn 			    instread(l);
7332f00b088Sdonn 			    index = l;
7342f00b088Sdonn 			    break;
7352f00b088Sdonn 
7362f00b088Sdonn 			default:
7372f00b088Sdonn 			    if (printing) {
7382f00b088Sdonn 			    	printf("unexpected size %d in printea\n", size);
7392f00b088Sdonn 			    }
7402f00b088Sdonn 			    instread(l);
7412f00b088Sdonn 			    index = l;
7422f00b088Sdonn 			    break;
7432f00b088Sdonn 		    }
7442f00b088Sdonn 		    if (printing) {
7452f00b088Sdonn 			printf(IMDF, index);
7462f00b088Sdonn 		    }
7472f00b088Sdonn 		    break;
7482f00b088Sdonn 
7492f00b088Sdonn 		default:
7502f00b088Sdonn 		    if (printing) {
7512f00b088Sdonn 			printf("???");
7522f00b088Sdonn 		    }
7532f00b088Sdonn 		    break;
7542f00b088Sdonn 	    }
7552f00b088Sdonn 	    break;
7562f00b088Sdonn 
7572f00b088Sdonn 	default:
7582f00b088Sdonn 	    if (printing) {
7592f00b088Sdonn 		printf("???");
7602f00b088Sdonn 	    }
7612f00b088Sdonn 	    break;
7622f00b088Sdonn     }
7632f00b088Sdonn }
7642f00b088Sdonn 
printEA(ea,size)7652f00b088Sdonn private printEA(ea, size)
7662f00b088Sdonn long ea;
7672f00b088Sdonn int size;
7682f00b088Sdonn {
7692f00b088Sdonn     printea((ea>>3)&07, ea&07, size);
7702f00b088Sdonn }
7712f00b088Sdonn 
mapsize(inst)7722f00b088Sdonn private mapsize(inst)
7732f00b088Sdonn register long inst;
7742f00b088Sdonn {
7752f00b088Sdonn     int m;
7762f00b088Sdonn 
7772f00b088Sdonn     inst >>= 6;
7782f00b088Sdonn     inst &= 03;
7792f00b088Sdonn     switch (inst) {
7802f00b088Sdonn 	case 0:
7812f00b088Sdonn 	    m = 1;
7822f00b088Sdonn 	    break;
7832f00b088Sdonn 
7842f00b088Sdonn 	case 1:
7852f00b088Sdonn 	    m = 2;
7862f00b088Sdonn 	    break;
7872f00b088Sdonn 
7882f00b088Sdonn 	case 2:
7892f00b088Sdonn 	    m = 4;
7902f00b088Sdonn 	    break;
7912f00b088Sdonn 
7922f00b088Sdonn 	default:
7932f00b088Sdonn 	    m = -1;
7942f00b088Sdonn 	    break;
7952f00b088Sdonn     }
7962f00b088Sdonn     return m;
7972f00b088Sdonn }
7982f00b088Sdonn 
suffix(size)7992f00b088Sdonn private char suffix(size)
8002f00b088Sdonn int size;
8012f00b088Sdonn {
8022f00b088Sdonn     char c;
8032f00b088Sdonn 
8042f00b088Sdonn     switch (size) {
8052f00b088Sdonn 	case 1:
8062f00b088Sdonn 	    c = 'b';
8072f00b088Sdonn 	    break;
8082f00b088Sdonn 
8092f00b088Sdonn 	case 2:
8102f00b088Sdonn 	    c = 'w';
8112f00b088Sdonn 	    break;
8122f00b088Sdonn 
8132f00b088Sdonn 	case 4:
8142f00b088Sdonn 	    c = 'l';
8152f00b088Sdonn 	    break;
8162f00b088Sdonn 
8172f00b088Sdonn 	default:
8182f00b088Sdonn 	    panic("bad size %d in suffix", size);
8192f00b088Sdonn     }
8202f00b088Sdonn     return c;
8212f00b088Sdonn }
8222f00b088Sdonn 
8232f00b088Sdonn /*
8242f00b088Sdonn  * Print an address offset.  Eventually this should attempt to be symbolic,
8252f00b088Sdonn  * but for now its just printed in hex.
8262f00b088Sdonn  */
8272f00b088Sdonn 
psymoff(off)8282f00b088Sdonn private psymoff (off)
8292f00b088Sdonn Word off;
8302f00b088Sdonn {
8312f00b088Sdonn     Symbol f;
8322f00b088Sdonn 
8332f00b088Sdonn     f = whatblock((Address) (off + FUNCOFFSET));
8342f00b088Sdonn     if (codeloc(f) == off + FUNCOFFSET) {
8352f00b088Sdonn 	printf("%s", symname(f));
8362f00b088Sdonn     } else {
8372f00b088Sdonn 	printf("0x%x", off);
8382f00b088Sdonn     }
8392f00b088Sdonn }
8402f00b088Sdonn 
8412f00b088Sdonn /*
8422f00b088Sdonn  * Instruction class specific routines.
8432f00b088Sdonn  */
8442f00b088Sdonn 
omove(inst,s)8452f00b088Sdonn public omove(inst, s)
8462f00b088Sdonn long inst;
8472f00b088Sdonn String s;
8482f00b088Sdonn {
8492f00b088Sdonn     register int c;
8502f00b088Sdonn     int size;
8512f00b088Sdonn 
8522f00b088Sdonn     c = s[0];
8532f00b088Sdonn     if (printing) {
8542f00b088Sdonn 	printf("\tmov%c\t", c);
8552f00b088Sdonn     }
8562f00b088Sdonn     size = ((c == 'b') ? 1 : (c == 'w') ? 2 : 4);
8572f00b088Sdonn     printea((inst>>3)&07, inst&07, size);
8582f00b088Sdonn     if (printing) {
8592f00b088Sdonn 	printf(",");
8602f00b088Sdonn     }
8612f00b088Sdonn     printea((inst>>6)&07, (inst>>9)&07, size);
8622f00b088Sdonn }
8632f00b088Sdonn 
8642f00b088Sdonn /*
8652f00b088Sdonn  * Two types: bsr (4 bytes) and bsrs (2 bytes)
8662f00b088Sdonn  */
8672f00b088Sdonn 
obranch(inst,dummy)8682f00b088Sdonn public obranch(inst, dummy)
8692f00b088Sdonn long inst;
8702f00b088Sdonn {
8712f00b088Sdonn     long disp;
8722f00b088Sdonn     String s;
8732f00b088Sdonn     short w;
8742f00b088Sdonn     Address startingaddr;	/* address of branch instruction */
8752f00b088Sdonn     int branchtype;		/* type of branch (0 = unconditional) */
8762f00b088Sdonn     Address dest;
8772f00b088Sdonn     Address retaddr;		/* for bsr instruction */
8782f00b088Sdonn 
8792f00b088Sdonn     startingaddr = instaddr - 2;
8802f00b088Sdonn     disp = inst&0377;
8812f00b088Sdonn     s = "s ";
8822f00b088Sdonn     if (disp == 0) {
8832f00b088Sdonn 	retaddr = startingaddr + 4;
8842f00b088Sdonn     } else {
8852f00b088Sdonn 	retaddr = startingaddr + 2;
8862f00b088Sdonn     }
8872f00b088Sdonn     if (disp > 127) {
8882f00b088Sdonn 	disp |= ~0377;
8892f00b088Sdonn     } else if (disp == 0){
8902f00b088Sdonn 	s = " ";
8912f00b088Sdonn 	instread(w);
8922f00b088Sdonn 	disp = w;
8932f00b088Sdonn     }
8942f00b088Sdonn     branchtype = (int)((inst>>8)&017);
8952f00b088Sdonn     dest = startingaddr + 2 + disp;
8962f00b088Sdonn     if (printing) {
8972f00b088Sdonn 	printf("\tb%s%s\t", bname[branchtype], s);
8982f00b088Sdonn 	psymoff(dest);
8992f00b088Sdonn     }
9002f00b088Sdonn     if (following) {
9012f00b088Sdonn 	/*
9022f00b088Sdonn 	 * If we're to follow the dynamic flow of instructions,
9032f00b088Sdonn 	 * we must see where the branch leads.  A branchtype of 0
9042f00b088Sdonn 	 * indicates an unconditional branch which we simply take
9052f00b088Sdonn 	 * as the new instruction address.  For a conditional branch,
9062f00b088Sdonn 	 * we continue execution up to the current address, single step,
9072f00b088Sdonn 	 * and keep going.
9082f00b088Sdonn 	 */
9092f00b088Sdonn 	if (branchtype == 0) {
9102f00b088Sdonn 	    instaddr = dest;
9112f00b088Sdonn 	} else if (branchtype == 01) {		/* bsr */
9122f00b088Sdonn 	    if (followcalls) {
9132f00b088Sdonn 		steppast(startingaddr);
9142f00b088Sdonn 		curfunc = whatblock(pc, true);
9152f00b088Sdonn 		if (not isbperr()) {
9162f00b088Sdonn 		    printstatus();
9172f00b088Sdonn 		    /* NOTREACHED */
9182f00b088Sdonn 		}
9192f00b088Sdonn 		bpact();
9202f00b088Sdonn 		if (nosource(curfunc) and canskip(curfunc) and
9212f00b088Sdonn 		  nlhdr.nlines != 0) {
9222f00b088Sdonn 		    stepto(retaddr);
9232f00b088Sdonn 		    instaddr = pc;
9242f00b088Sdonn 		    bpact();
9252f00b088Sdonn 		} else {
9262f00b088Sdonn 		    callnews(/* iscall = */ true);
9272f00b088Sdonn 		}
9282f00b088Sdonn 	    }
9292f00b088Sdonn 	} else {
9302f00b088Sdonn 	    steppast(startingaddr);
9312f00b088Sdonn 	}
9322f00b088Sdonn     }
9332f00b088Sdonn }
9342f00b088Sdonn 
odbcc(inst,form)9352f00b088Sdonn public odbcc(inst, form)
9362f00b088Sdonn long inst;
9372f00b088Sdonn String form;
9382f00b088Sdonn {
9392f00b088Sdonn     long disp;
9402f00b088Sdonn     short w;
9412f00b088Sdonn 
9422f00b088Sdonn     instread(w);
9432f00b088Sdonn     if (printing) {
9442f00b088Sdonn     	printf(form, dbname[(int)((inst>>8)&017)], inst&07);
9452f00b088Sdonn 	psymoff(w + sizeof(w));
9462f00b088Sdonn     }
9472f00b088Sdonn }
9482f00b088Sdonn 
oscc(inst,dummy)9492f00b088Sdonn public oscc(inst, dummy)
9502f00b088Sdonn long inst;
9512f00b088Sdonn long dummy;
9522f00b088Sdonn {
9532f00b088Sdonn     if (printing) {
9542f00b088Sdonn 	printf("\ts%s\t", cname[(int)((inst>>8)&017)]);
9552f00b088Sdonn     }
9562f00b088Sdonn     printea((inst>>3)&07, inst&07, 1);
9572f00b088Sdonn }
9582f00b088Sdonn 
biti(inst,dummy)9592f00b088Sdonn public biti(inst, dummy)
9602f00b088Sdonn long inst;
9612f00b088Sdonn long dummy;
9622f00b088Sdonn {
9632f00b088Sdonn     short w;
9642f00b088Sdonn 
9652f00b088Sdonn     if (printing) {
9662f00b088Sdonn 	printf("\t%s\t", bit[(int)((inst>>6)&03)]);
9672f00b088Sdonn     }
9682f00b088Sdonn     if (inst&0x0100) {
9692f00b088Sdonn 	if (printing) {
9702f00b088Sdonn 	    printf("d%D,", inst>>9);
9712f00b088Sdonn 	}
9722f00b088Sdonn     } else {
9732f00b088Sdonn 	instread(w);
9742f00b088Sdonn 	if (printing) {
9752f00b088Sdonn 	    printf(IMDF, w);
9762f00b088Sdonn 	    printf(",");
9772f00b088Sdonn 	}
9782f00b088Sdonn     }
9792f00b088Sdonn     printEA(inst);
9802f00b088Sdonn }
9812f00b088Sdonn 
opmode(inst,opcode)9822f00b088Sdonn public opmode(inst, opcode)
9832f00b088Sdonn long inst;
9842f00b088Sdonn long opcode;
9852f00b088Sdonn {
9862f00b088Sdonn     register int opmode;
9872f00b088Sdonn     register int reg;
9882f00b088Sdonn     int size;
9892f00b088Sdonn 
9902f00b088Sdonn     opmode = (int)((inst>>6) & 07);
9912f00b088Sdonn     reg = (int)((inst>>9) & 07);
9922f00b088Sdonn     if (opmode == 0 or opmode == 4) {
9932f00b088Sdonn 	size = 1;
9942f00b088Sdonn     } else if (opmode == 1 or opmode == 3 or opmode == 5) {
9952f00b088Sdonn 	size = 2;
9962f00b088Sdonn     } else {
9972f00b088Sdonn 	size = 4;
9982f00b088Sdonn     }
9992f00b088Sdonn     if (printing) {
10002f00b088Sdonn 	printf("\t%s%c\t", opcode, suffix(size));
10012f00b088Sdonn     }
10022f00b088Sdonn     if (opmode >= 4 and opmode <= 6) {
10032f00b088Sdonn 	if (printing) {
10042f00b088Sdonn 	    printf("d%d,", reg);
10052f00b088Sdonn 	}
10062f00b088Sdonn 	printea((inst>>3)&07, inst&07, size);
10072f00b088Sdonn     } else {
10082f00b088Sdonn 	printea((inst>>3)&07, inst&07, size);
10092f00b088Sdonn 	if (printing) {
10102f00b088Sdonn 	    printf(",%c%d",(opmode<=2) ? 'd' : 'a', reg);
10112f00b088Sdonn 	}
10122f00b088Sdonn     }
10132f00b088Sdonn }
10142f00b088Sdonn 
shroi(inst,ds)10152f00b088Sdonn public shroi(inst, ds)
10162f00b088Sdonn long inst;
10172f00b088Sdonn String ds;
10182f00b088Sdonn {
10192f00b088Sdonn     int rx, ry;
10202f00b088Sdonn     String opcode;
10212f00b088Sdonn 
10222f00b088Sdonn     if ((inst & 0xC0) == 0xC0) {
10232f00b088Sdonn 	opcode = shro[(int)((inst>>9)&03)];
10242f00b088Sdonn 	if (printing) {
10252f00b088Sdonn 	    printf("\t%s%s\t", opcode, ds);
10262f00b088Sdonn 	}
10272f00b088Sdonn 	printEA(inst);
10282f00b088Sdonn     } else {
10292f00b088Sdonn 	if (printing) {
10302f00b088Sdonn 	    opcode = shro[(int)((inst>>3)&03)];
10312f00b088Sdonn 	    printf("\t%s%s%c\t", opcode, ds, suffix(mapsize(inst)));
10322f00b088Sdonn 	    rx = (int)((inst>>9)&07); ry = (int)(inst&07);
10332f00b088Sdonn 	    if ((inst>>5)&01) {
10342f00b088Sdonn 		printf("d%d,d%d", rx, ry);
10352f00b088Sdonn 	    } else {
10362f00b088Sdonn 		printf(IMDF, (rx ? rx : 8));
10372f00b088Sdonn 		printf(",d%d", ry);
10382f00b088Sdonn 	    }
10392f00b088Sdonn 	}
10402f00b088Sdonn     }
10412f00b088Sdonn }
10422f00b088Sdonn 
oimmed(inst,opcode)10432f00b088Sdonn public oimmed(inst, opcode)
10442f00b088Sdonn long inst;
10452f00b088Sdonn register String opcode;
10462f00b088Sdonn {
10472f00b088Sdonn     register int size;
10482f00b088Sdonn     long const;
10492f00b088Sdonn     short w;
10502f00b088Sdonn 
10512f00b088Sdonn     size = mapsize(inst);
10522f00b088Sdonn     if (size > 0) {
10532f00b088Sdonn 	if (size == 4) {
10542f00b088Sdonn 	    instread(const);
10552f00b088Sdonn 	} else {
10562f00b088Sdonn 	    instread(w);
10572f00b088Sdonn 	    const = w;
10582f00b088Sdonn 	}
10592f00b088Sdonn 	if (printing) {
10602f00b088Sdonn 	    printf("\t%s%c\t", opcode, suffix(size));
10612f00b088Sdonn 	    printf(IMDF, const);
10622f00b088Sdonn 	    printf(",");
10632f00b088Sdonn 	}
10642f00b088Sdonn 	printEA(inst, size);
10652f00b088Sdonn     } else {
10662f00b088Sdonn 	if (printing) {
10672f00b088Sdonn 	    printf("\tbadop");
10682f00b088Sdonn 	}
10692f00b088Sdonn     }
10702f00b088Sdonn }
10712f00b088Sdonn 
oreg(inst,opcode)10722f00b088Sdonn public oreg(inst, opcode)
10732f00b088Sdonn long inst;
10742f00b088Sdonn register String opcode;
10752f00b088Sdonn {
10762f00b088Sdonn     if (printing) {
10772f00b088Sdonn 	printf(opcode, (inst & 07));
10782f00b088Sdonn     }
10792f00b088Sdonn }
10802f00b088Sdonn 
extend(inst,opcode)10812f00b088Sdonn public extend(inst, opcode)
10822f00b088Sdonn long inst;
10832f00b088Sdonn String opcode;
10842f00b088Sdonn {
10852f00b088Sdonn     register int size;
10862f00b088Sdonn     int ry, rx;
10872f00b088Sdonn     char c;
10882f00b088Sdonn 
10892f00b088Sdonn     if (printing) {
10902f00b088Sdonn 	size = mapsize(inst);
10912f00b088Sdonn 	ry = (inst&07);
10922f00b088Sdonn 	rx = ((inst>>9)&07);
10932f00b088Sdonn 	c = ((inst & 0x1000) ? suffix(size) : ' ');
10942f00b088Sdonn 	printf("\t%s%c\t", opcode, c);
10952f00b088Sdonn 	if (opcode[0] == 'e') {
10962f00b088Sdonn 	    if (inst & 0x0080) {
10972f00b088Sdonn 		printf("d%D,a%D", rx, ry);
10982f00b088Sdonn 	    } else if (inst & 0x0008) {
10992f00b088Sdonn 		printf("a%D,a%D", rx, ry);
11002f00b088Sdonn 	    } else {
11012f00b088Sdonn 		printf("d%D,d%D", rx, ry);
11022f00b088Sdonn 	    }
11032f00b088Sdonn 	} else if ((inst & 0xF000) == 0xB000) {
11042f00b088Sdonn 	    printf("a%D@+,a%D@+", ry, rx);
11052f00b088Sdonn 	} else if (inst & 0x8) {
11062f00b088Sdonn 	    printf("a%D@-,a%D@-", ry, rx);
11072f00b088Sdonn 	} else {
11082f00b088Sdonn 	    printf("d%D,d%D", ry, rx);
11092f00b088Sdonn 	}
11102f00b088Sdonn     }
11112f00b088Sdonn }
11122f00b088Sdonn 
olink(inst,dummy)11132f00b088Sdonn public olink(inst, dummy)
11142f00b088Sdonn long inst;
11152f00b088Sdonn long dummy;
11162f00b088Sdonn {
11172f00b088Sdonn     short w;
11182f00b088Sdonn 
11192f00b088Sdonn     instread(w);
11202f00b088Sdonn     if (printing) {
11212f00b088Sdonn 	printf("\tlink\ta%D,", inst&07);
11222f00b088Sdonn 	printf(IMDF, w);
11232f00b088Sdonn     }
11242f00b088Sdonn }
11252f00b088Sdonn 
otrap(inst,dummy)11262f00b088Sdonn public otrap(inst, dummy)
11272f00b088Sdonn long inst;
11282f00b088Sdonn {
11292f00b088Sdonn     if (printing) {
11302f00b088Sdonn 	printf("\ttrap\t");
11312f00b088Sdonn 	printf(IMDF, inst&017);
11322f00b088Sdonn     }
11332f00b088Sdonn }
11342f00b088Sdonn 
oneop(inst,opcode)11352f00b088Sdonn public oneop(inst, opcode)
11362f00b088Sdonn long inst;
11372f00b088Sdonn register String opcode;
11382f00b088Sdonn {
11392f00b088Sdonn     if (printing) {
11402f00b088Sdonn 	printf("\t%s",opcode);
11412f00b088Sdonn     }
11422f00b088Sdonn     printEA(inst);
11432f00b088Sdonn }
11442f00b088Sdonn 
jsrop(inst,opcode)11452f00b088Sdonn public jsrop(inst, opcode)
11462f00b088Sdonn long inst;
11472f00b088Sdonn register String opcode;
11482f00b088Sdonn {
11492f00b088Sdonn     Address startingaddr;	/* beginning of jsr instruction */
11502f00b088Sdonn     Address retaddr; /* can't call return_addr (frame not set up yet) */
11512f00b088Sdonn 
11522f00b088Sdonn     startingaddr = instaddr - 2;
11532f00b088Sdonn     switch ((inst >> 3) & 07) {
11542f00b088Sdonn 	case 2:
11552f00b088Sdonn 	    retaddr = instaddr;		/* two byte instruction */
11562f00b088Sdonn 	    break;
11572f00b088Sdonn 	case 5:
11582f00b088Sdonn 	case 6:
11592f00b088Sdonn 	    retaddr = instaddr + 2;	/* four byte instruction */
11602f00b088Sdonn 	    break;
11612f00b088Sdonn 	case 7:
11622f00b088Sdonn 	default:
11632f00b088Sdonn 	    switch (inst & 07) {
11642f00b088Sdonn 		case 0:
11652f00b088Sdonn 		case 2:
11662f00b088Sdonn 		case 3:
11672f00b088Sdonn 		    retaddr = instaddr + 2;
11682f00b088Sdonn 		    break;
11692f00b088Sdonn 		case 1:
11702f00b088Sdonn 		default:
11712f00b088Sdonn 		    retaddr = instaddr + 4;	/* six byte instruction */
11722f00b088Sdonn 		    break;
11732f00b088Sdonn 	    }
11742f00b088Sdonn 	    break;
11752f00b088Sdonn     }
11762f00b088Sdonn     if (printing) {
11772f00b088Sdonn 	printf("\t%s",opcode);
11782f00b088Sdonn     }
11792f00b088Sdonn     printEA(inst);
11802f00b088Sdonn     if (following and followcalls) {
11812f00b088Sdonn 	steppast(startingaddr);
11822f00b088Sdonn 	curfunc = whatblock(pc, true);
11832f00b088Sdonn 	if (not isbperr()) {
11842f00b088Sdonn 	    printstatus();
11852f00b088Sdonn 	    /* NOTREACHED */
11862f00b088Sdonn 	}
11872f00b088Sdonn 	bpact();
11882f00b088Sdonn 	if (nosource(curfunc) and canskip(curfunc) and nlhdr.nlines != 0) {
11892f00b088Sdonn 	    stepto(retaddr);
11902f00b088Sdonn 	    instaddr = pc;
11912f00b088Sdonn 	    bpact();
11922f00b088Sdonn 	} else {
11932f00b088Sdonn 	    callnews(/* iscall = */ true);
11942f00b088Sdonn 	}
11952f00b088Sdonn     }
11962f00b088Sdonn }
11972f00b088Sdonn 
jmpop(inst,opcode)11982f00b088Sdonn public jmpop(inst, opcode)
11992f00b088Sdonn long inst;
12002f00b088Sdonn register String opcode;
12012f00b088Sdonn {
12022f00b088Sdonn     Address startingaddr;	/* beginning of jump instruction */
12032f00b088Sdonn 
12042f00b088Sdonn     startingaddr = instaddr - 2;
12052f00b088Sdonn     if (printing) {
12062f00b088Sdonn 	printf("\t%s",opcode);
12072f00b088Sdonn     }
12082f00b088Sdonn     printEA(inst);
12092f00b088Sdonn     if (following) {
12102f00b088Sdonn 	steppast(startingaddr);
12112f00b088Sdonn     }
12122f00b088Sdonn }
12132f00b088Sdonn 
pregmask(mask)12142f00b088Sdonn public pregmask(mask)
12152f00b088Sdonn register int mask;
12162f00b088Sdonn {
12172f00b088Sdonn     register int i;
12182f00b088Sdonn     register int flag = 0;
12192f00b088Sdonn 
12202f00b088Sdonn     if (printing) {
12212f00b088Sdonn 	printf("#<");
12222f00b088Sdonn 	for (i=0; i<16; i++) {
12232f00b088Sdonn 	    if (mask&1) {
12242f00b088Sdonn 		if (flag) {
12252f00b088Sdonn 		    printf(",");
12262f00b088Sdonn 		} else {
12272f00b088Sdonn 		    ++flag;
12282f00b088Sdonn 		}
12292f00b088Sdonn 		printf("%c%d",(i<8) ? 'd' : 'a', i&07);
12302f00b088Sdonn 	    }
12312f00b088Sdonn 	    mask >>= 1;
12322f00b088Sdonn 	}
12332f00b088Sdonn 	printf(">");
12342f00b088Sdonn     }
12352f00b088Sdonn }
12362f00b088Sdonn 
omovem(inst,dummy)12372f00b088Sdonn public omovem(inst, dummy)
12382f00b088Sdonn long inst;
12392f00b088Sdonn long dummy;
12402f00b088Sdonn {
12412f00b088Sdonn     register int i, list, mask;
12422f00b088Sdonn     register int reglist;
12432f00b088Sdonn     short w;
12442f00b088Sdonn 
12452f00b088Sdonn     i = 0;
12462f00b088Sdonn     list = 0;
12472f00b088Sdonn     mask = 0100000;
12482f00b088Sdonn     instread(w);
12492f00b088Sdonn     reglist = w;
12502f00b088Sdonn     if ((inst & 070) == 040) {	/* predecrement */
12512f00b088Sdonn 	for (i = 15; i > 0; i -= 2) {
12522f00b088Sdonn 	    list |= ((mask & reglist) >> i);
12532f00b088Sdonn 	    mask >>= 1;
12542f00b088Sdonn 	}
12552f00b088Sdonn 	for (i = 1; i < 16; i += 2) {
12562f00b088Sdonn 	    list |= ((mask & reglist) << i);
12572f00b088Sdonn 	    mask >>= 1;
12582f00b088Sdonn 	}
12592f00b088Sdonn 	reglist = list;
12602f00b088Sdonn     }
12612f00b088Sdonn     if (printing) {
12622f00b088Sdonn 	printf("\tmovem%c\t",(inst&100)?'l':'w');
12632f00b088Sdonn     }
12642f00b088Sdonn     if (inst&02000) {
12652f00b088Sdonn 	printEA(inst);
12662f00b088Sdonn 	if (printing) {
12672f00b088Sdonn 	    printf(",");
12682f00b088Sdonn 	}
12692f00b088Sdonn 	pregmask(reglist);
12702f00b088Sdonn     } else {
12712f00b088Sdonn 	pregmask(reglist);
12722f00b088Sdonn 	if (printing) {
12732f00b088Sdonn 	    printf(",");
12742f00b088Sdonn 	}
12752f00b088Sdonn 	printEA(inst);
12762f00b088Sdonn     }
12772f00b088Sdonn }
12782f00b088Sdonn 
ochk(inst,opcode)12792f00b088Sdonn public ochk(inst, opcode)
12802f00b088Sdonn long inst;
12812f00b088Sdonn register String opcode;
12822f00b088Sdonn {
12832f00b088Sdonn     if (printing) {
12842f00b088Sdonn 	printf("\t%s\t", opcode);
12852f00b088Sdonn     }
12862f00b088Sdonn     printEA(inst, sizeof(Byte));
12872f00b088Sdonn     if (printing) {
12882f00b088Sdonn 	printf(",%c%D", (opcode[0] == 'l') ? 'a' : 'd', (inst>>9)&07);
12892f00b088Sdonn     }
12902f00b088Sdonn }
12912f00b088Sdonn 
soneop(inst,opcode)12922f00b088Sdonn public soneop(inst, opcode)
12932f00b088Sdonn long inst;
12942f00b088Sdonn register String opcode;
12952f00b088Sdonn {
12962f00b088Sdonn     register int size;
12972f00b088Sdonn 
12982f00b088Sdonn     size = mapsize(inst);
12992f00b088Sdonn     if (size > 0) {
13002f00b088Sdonn 	if (printing) {
13012f00b088Sdonn 	    printf("\t%s%c\t", opcode, suffix(size));
13022f00b088Sdonn 	}
13032f00b088Sdonn 	printEA(inst);
13042f00b088Sdonn     } else {
13052f00b088Sdonn 	if (printing) {
13062f00b088Sdonn 	    printf("\tbadop");
13072f00b088Sdonn 	}
13082f00b088Sdonn     }
13092f00b088Sdonn }
13102f00b088Sdonn 
oquick(inst,opcode)13112f00b088Sdonn public oquick(inst, opcode)
13122f00b088Sdonn long inst;
13132f00b088Sdonn register String opcode;
13142f00b088Sdonn {
13152f00b088Sdonn     register int size;
13162f00b088Sdonn     register int data;
13172f00b088Sdonn 
13182f00b088Sdonn     size = mapsize(inst);
13192f00b088Sdonn     data = (int)((inst>>9) & 07);
13202f00b088Sdonn     if (data == 0) {
13212f00b088Sdonn 	data = 8;
13222f00b088Sdonn     }
13232f00b088Sdonn     if (size > 0) {
13242f00b088Sdonn 	if (printing) {
13252f00b088Sdonn 	    printf("\t%s%c\t", opcode, suffix(size));
13262f00b088Sdonn 	    printf(IMDF, data);
13272f00b088Sdonn 	    printf(",");
13282f00b088Sdonn 	}
13292f00b088Sdonn 	printEA(inst);
13302f00b088Sdonn     } else {
13312f00b088Sdonn 	if (printing) {
13322f00b088Sdonn 	    printf("\tbadop");
13332f00b088Sdonn 	}
13342f00b088Sdonn     }
13352f00b088Sdonn }
13362f00b088Sdonn 
omoveq(inst,dummy)13372f00b088Sdonn public omoveq(inst, dummy)
13382f00b088Sdonn long inst;
13392f00b088Sdonn long dummy;
13402f00b088Sdonn {
13412f00b088Sdonn     register int data;
13422f00b088Sdonn 
13432f00b088Sdonn     if (printing) {
13442f00b088Sdonn 	data = (int)(inst & 0377);
13452f00b088Sdonn 	if (data > 127) {
13462f00b088Sdonn 	    data |= ~0377;
13472f00b088Sdonn 	}
13482f00b088Sdonn 	printf("\tmoveq\t");
13492f00b088Sdonn 	printf(IMDF, data);
13502f00b088Sdonn 	printf(",d%D", (inst>>9)&07);
13512f00b088Sdonn     }
13522f00b088Sdonn }
13532f00b088Sdonn 
oprint(inst,opcode)13542f00b088Sdonn public oprint(inst, opcode)
13552f00b088Sdonn long inst;
13562f00b088Sdonn register String opcode;
13572f00b088Sdonn {
13582f00b088Sdonn     if (printing) {
13592f00b088Sdonn 	printf("\t%s",opcode);
13602f00b088Sdonn     }
13612f00b088Sdonn }
13622f00b088Sdonn 
ostop(inst,opcode)13632f00b088Sdonn public ostop(inst, opcode)
13642f00b088Sdonn long inst;
13652f00b088Sdonn register String opcode;
13662f00b088Sdonn {
13672f00b088Sdonn     short w;
13682f00b088Sdonn 
13692f00b088Sdonn     instread(w);
13702f00b088Sdonn     if (printing) {
13712f00b088Sdonn 	printf(opcode, w);
13722f00b088Sdonn     }
13732f00b088Sdonn }
13742f00b088Sdonn 
orts(inst,opcode)13752f00b088Sdonn public orts(inst, opcode)
13762f00b088Sdonn long inst;
13772f00b088Sdonn register String opcode;
13782f00b088Sdonn {
13792f00b088Sdonn     Address addr;
13802f00b088Sdonn 
13812f00b088Sdonn     if (following) {
13822f00b088Sdonn 	callnews(/* iscall = */ false);
13832f00b088Sdonn     	if (inst_tracing) {
13842f00b088Sdonn 	    addr = currtnaddr();
13852f00b088Sdonn     	} else {
13862f00b088Sdonn 	    addr = return_addr();
13872f00b088Sdonn 	    if (addr == 0) {
13882f00b088Sdonn 		stepto(instaddr - 2);
13892f00b088Sdonn 		addr = currtnaddr();
13902f00b088Sdonn 	    }
13912f00b088Sdonn 	}
13922f00b088Sdonn 	stepto(addr);
13932f00b088Sdonn 	instaddr = pc;
13942f00b088Sdonn     }
13952f00b088Sdonn     if (printing) {
13962f00b088Sdonn 	printf("\t%s",opcode);
13972f00b088Sdonn     }
13982f00b088Sdonn }
13992f00b088Sdonn 
14002f00b088Sdonn /*
14012f00b088Sdonn  * Not used by C compiler; does an rts but before doing so, pops
14022f00b088Sdonn  * arg bytes from the stack.
14032f00b088Sdonn  */
14042f00b088Sdonn 
ortspop(inst,opcode)14052f00b088Sdonn public ortspop(inst, opcode)
14062f00b088Sdonn long inst;
14072f00b088Sdonn register String opcode;
14082f00b088Sdonn {
14092f00b088Sdonn     Address addr;
14102f00b088Sdonn     short w;
14112f00b088Sdonn 
14122f00b088Sdonn     instread(w);
14132f00b088Sdonn     if (following) {
14142f00b088Sdonn 	callnews(/* iscall = */ false);
14152f00b088Sdonn     	if (inst_tracing) {
14162f00b088Sdonn 	    addr = currtnaddr();
14172f00b088Sdonn     	} else {
14182f00b088Sdonn 	    addr = return_addr();
14192f00b088Sdonn 	}
14202f00b088Sdonn 	stepto(addr);
14212f00b088Sdonn 	instaddr = pc;
14222f00b088Sdonn     }
14232f00b088Sdonn     if (printing) {
14242f00b088Sdonn 	printf(opcode, w);
14252f00b088Sdonn     }
14262f00b088Sdonn }
14272f00b088Sdonn 
omovs(inst,opcode)14282f00b088Sdonn public omovs(inst, opcode)
14292f00b088Sdonn long inst;
14302f00b088Sdonn String opcode;
14312f00b088Sdonn {
14322f00b088Sdonn     register int size;
14332f00b088Sdonn     register unsigned int controlword;
14342f00b088Sdonn     short w;
14352f00b088Sdonn 
14362f00b088Sdonn     size = mapsize(inst);
14372f00b088Sdonn     instread(w);
14382f00b088Sdonn     controlword = w >> 11;
14392f00b088Sdonn     if (printing) {
14402f00b088Sdonn 	printf("\t%s%c\t", opcode, suffix(size));
14412f00b088Sdonn     }
14422f00b088Sdonn     if (controlword & 1){
14432f00b088Sdonn 	controlword >>= 1;
14442f00b088Sdonn 	if (printing) {
14452f00b088Sdonn 	    printf((controlword&0x8) ? "a%D," : "d%D,", controlword&7 );
14462f00b088Sdonn 	}
14472f00b088Sdonn 	printEA(inst&0xff, size);
14482f00b088Sdonn     } else {
14492f00b088Sdonn 	controlword >>= 1;
14502f00b088Sdonn 	printEA(inst&0xff, size);
14512f00b088Sdonn 	if (printing) {
14522f00b088Sdonn 	    printf((controlword&0x8) ? ",a%D" : ",d%D", controlword&7);
14532f00b088Sdonn 	}
14542f00b088Sdonn     }
14552f00b088Sdonn }
14562f00b088Sdonn 
omovc(inst,opcode)14572f00b088Sdonn public omovc(inst, opcode)
14582f00b088Sdonn long inst;
14592f00b088Sdonn String opcode;
14602f00b088Sdonn {
14612f00b088Sdonn     register unsigned int controlword;
14622f00b088Sdonn     String creg;
14632f00b088Sdonn     short w;
14642f00b088Sdonn 
14652f00b088Sdonn     instread(w);
14662f00b088Sdonn     if (printing) {
14672f00b088Sdonn 	controlword = w;
14682f00b088Sdonn 	switch (controlword & 0xfff) {
14692f00b088Sdonn 	    case 0:
14702f00b088Sdonn 		creg = "sfc";
14712f00b088Sdonn 		break;
14722f00b088Sdonn 
14732f00b088Sdonn 	    case 1:
14742f00b088Sdonn 		creg = "dfc";
14752f00b088Sdonn 		break;
14762f00b088Sdonn 
14772f00b088Sdonn 	    case 0x800:
14782f00b088Sdonn 		creg = "usp";
14792f00b088Sdonn 		break;
14802f00b088Sdonn 
14812f00b088Sdonn 	    case 0x801:
14822f00b088Sdonn 		creg = "vbr";
14832f00b088Sdonn 		break;
14842f00b088Sdonn 
14852f00b088Sdonn 	    default:
14862f00b088Sdonn 		creg = "???";
14872f00b088Sdonn 		break;
14882f00b088Sdonn 	}
14892f00b088Sdonn 	controlword >>= 12;
14902f00b088Sdonn 	if (inst & 1){
14912f00b088Sdonn 	    printf((controlword&0x8) ? "%sa%D,%s" : "%sd%D,%s",
14922f00b088Sdonn 		opcode, controlword&7, creg );
14932f00b088Sdonn 	} else {
14942f00b088Sdonn 	    printf((controlword&0x8) ? "%s%s,a%D" : "%s%s,d%D",
14952f00b088Sdonn 		opcode, creg, controlword&7 );
14962f00b088Sdonn 	}
14972f00b088Sdonn     }
14982f00b088Sdonn }
14992f00b088Sdonn 
15002f00b088Sdonn /*
15012f00b088Sdonn  * Compute the next address that will be executed from the given one.
15022f00b088Sdonn  * If "isnext" is true then consider a procedure call as straight line code.
15032f00b088Sdonn  *
15042f00b088Sdonn  * Unconditional branches we just follow, for conditional branches
15052f00b088Sdonn  * we continue execution to the current location and then single step
15062f00b088Sdonn  * the machine.
15072f00b088Sdonn  */
15082f00b088Sdonn 
nextaddr(startaddr,isnext)15092f00b088Sdonn public Address nextaddr(startaddr, isnext)
15102f00b088Sdonn Address startaddr;
15112f00b088Sdonn Boolean isnext;
15122f00b088Sdonn {
15132f00b088Sdonn     Optab *o;
15142f00b088Sdonn     short inst;
15152f00b088Sdonn 
15162f00b088Sdonn     instaddr = usignal(process);
15172f00b088Sdonn     if (instaddr == 0 or instaddr == 1) {
15182f00b088Sdonn 	following = true;
15192f00b088Sdonn 	followcalls = (Boolean) (not isnext);
15202f00b088Sdonn 	printing = false;
15212f00b088Sdonn 	iread(&inst, startaddr, sizeof(inst));
15222f00b088Sdonn 	instaddr = startaddr + sizeof(inst);
15232f00b088Sdonn 	o = decode(inst, startaddr);
15242f00b088Sdonn 	if (o->mask == 0) {
15252f00b088Sdonn 	    fprintf(stderr,
15262f00b088Sdonn 		"[internal error: undecodable op at 0x%x]\n", startaddr);
15272f00b088Sdonn 	    fflush(stderr);
15282f00b088Sdonn 	} else {
15292f00b088Sdonn 	    (*o->opfun)(inst, o->farg);
15302f00b088Sdonn 	}
15312f00b088Sdonn 	following = false;
15322f00b088Sdonn     }
15332f00b088Sdonn     return instaddr;
15342f00b088Sdonn }
15352f00b088Sdonn 
15362f00b088Sdonn /*
15372f00b088Sdonn  * Step to the given address and then execute one instruction past it.
15382f00b088Sdonn  * Set instaddr to the new instruction address.
15392f00b088Sdonn  */
15402f00b088Sdonn 
steppast(addr)15412f00b088Sdonn private steppast(addr)
15422f00b088Sdonn Address addr;
15432f00b088Sdonn {
15442f00b088Sdonn     stepto(addr);
15452f00b088Sdonn     pstep(process, DEFSIG);
15462f00b088Sdonn     pc = reg(PROGCTR);
15472f00b088Sdonn     instaddr = pc;
15482f00b088Sdonn }
15492f00b088Sdonn 
15502f00b088Sdonn /*
15512f00b088Sdonn  * Enter a procedure by creating and executing a call instruction.
15522f00b088Sdonn  */
15532f00b088Sdonn 
15542f00b088Sdonn #define CALLSIZE 6	/* size of call instruction */
15552f00b088Sdonn 
beginproc(p)15562f00b088Sdonn public beginproc(p)
15572f00b088Sdonn Symbol p;
15582f00b088Sdonn {
15592f00b088Sdonn     char save[CALLSIZE];
15602f00b088Sdonn     struct {
15612f00b088Sdonn 	short op;
15622f00b088Sdonn 	char addr[sizeof(long)];	/* unaligned long */
15632f00b088Sdonn     } call;
15642f00b088Sdonn     long dest;
15652f00b088Sdonn 
15662f00b088Sdonn     pc = CODESTART + 6;
15672f00b088Sdonn     iread(save, pc, sizeof(save));
15682f00b088Sdonn     call.op = 0x4eb9;			/* jsr */
15692f00b088Sdonn     dest = codeloc(p) - FUNCOFFSET;
15702f00b088Sdonn     mov(&dest, call.addr, sizeof(call.addr));
15712f00b088Sdonn     iwrite(&call, pc, sizeof(call));
15722f00b088Sdonn     setreg(PROGCTR, pc);
15732f00b088Sdonn     pstep(process, DEFSIG);
15742f00b088Sdonn     iwrite(save, pc, sizeof(save));
15752f00b088Sdonn     pc = reg(PROGCTR);
15762f00b088Sdonn     if (not isbperr()) {
15772f00b088Sdonn 	printstatus();
15782f00b088Sdonn     }
15792f00b088Sdonn     /*
15802f00b088Sdonn      * Execute link instruction so the return addr is visible.
15812f00b088Sdonn      */
15822f00b088Sdonn     pstep(process, DEFSIG);
15832f00b088Sdonn     pc = reg(PROGCTR);
15842f00b088Sdonn     if (not isbperr()) {
15852f00b088Sdonn 	printstatus();
15862f00b088Sdonn     }
15872f00b088Sdonn }
15882f00b088Sdonn 
15892f00b088Sdonn /*
15902f00b088Sdonn  * Special variables for debugging the kernel.
15912f00b088Sdonn  */
15922f00b088Sdonn 
15932f00b088Sdonn public integer masterpcbb;
15942f00b088Sdonn public integer slr;
15952f00b088Sdonn public struct pte *sbr;
15962f00b088Sdonn private struct pcb pcb;
15972f00b088Sdonn 
getpcb()15982f00b088Sdonn public getpcb ()
15992f00b088Sdonn {
16002f00b088Sdonn     integer i;
16012f00b088Sdonn 
16022f00b088Sdonn     fseek(corefile, masterpcbb & ~0x80000000, 0);
16032f00b088Sdonn     get(corefile, pcb);
16042f00b088Sdonn     pcb.pcb_p0lr &= ~AST_CLR;
16052f00b088Sdonn     printf("p0br %lx p0lr %lx p1br %lx p1lr %lx\n",
16062f00b088Sdonn 	pcb.pcb_p0br, pcb.pcb_p0lr, pcb.pcb_p1br, pcb.pcb_p1lr
16072f00b088Sdonn     );
16082f00b088Sdonn #   ifdef sun
16092f00b088Sdonn     for (i = 0; i < 14; i++) {
16102f00b088Sdonn 	setreg(i, pcb.pcb_regs.val[i]);
16112f00b088Sdonn     }
16122f00b088Sdonn #   else /* IRIS */
16132f00b088Sdonn     for (i = 0; i < 14; i++) {
16142f00b088Sdonn 	setreg(i, pcb.pcb_regs[i]);
16152f00b088Sdonn     }
16162f00b088Sdonn #   endif
16172f00b088Sdonn }
16182f00b088Sdonn 
copyregs(savreg,reg)16192f00b088Sdonn public copyregs (savreg, reg)
16202f00b088Sdonn Word savreg[], reg[];
16212f00b088Sdonn {
16222f00b088Sdonn     reg[0] = savreg[R0];
16232f00b088Sdonn     reg[1] = savreg[R1];
16242f00b088Sdonn     reg[2] = savreg[R2];
16252f00b088Sdonn     reg[3] = savreg[R3];
16262f00b088Sdonn     reg[4] = savreg[R4];
16272f00b088Sdonn     reg[5] = savreg[R5];
16282f00b088Sdonn     reg[6] = savreg[R6];
16292f00b088Sdonn     reg[7] = savreg[R7];
16302f00b088Sdonn     reg[8] = savreg[AR0];
16312f00b088Sdonn     reg[9] = savreg[AR1];
16322f00b088Sdonn     reg[10] = savreg[AR2];
16332f00b088Sdonn     reg[11] = savreg[AR3];
16342f00b088Sdonn     reg[12] = savreg[AR4];
16352f00b088Sdonn     reg[13] = savreg[AR5];
16362f00b088Sdonn     reg[14] = savreg[AR6];
16372f00b088Sdonn     reg[15] = savreg[AR7];
16382f00b088Sdonn     reg[PROGCTR] = savreg[PC];
16392f00b088Sdonn }
16402f00b088Sdonn 
16412f00b088Sdonn /*
16422f00b088Sdonn  * Map a virtual address to a physical address.
16432f00b088Sdonn  * XXX THIS CAN'T BE RIGHT... XXX
16442f00b088Sdonn  */
16452f00b088Sdonn 
vmap(addr)16462f00b088Sdonn public Address vmap (addr)
16472f00b088Sdonn Address addr;
16482f00b088Sdonn {
16492f00b088Sdonn     Address r;
16502f00b088Sdonn     integer v, n;
16512f00b088Sdonn     struct pte pte;
16522f00b088Sdonn 
16532f00b088Sdonn     r = addr & ~0xc0000000;
16542f00b088Sdonn     v = btop(r);
16552f00b088Sdonn     switch (addr&0xc0000000) {
16562f00b088Sdonn 	case 0xc0000000:
16572f00b088Sdonn 	case 0x80000000:
16582f00b088Sdonn 	    /*
16592f00b088Sdonn 	     * In system space, so get system pte.
16602f00b088Sdonn 	     * If it is valid or reclaimable then the physical address
16612f00b088Sdonn 	     * is the combination of its page number and the page offset
16622f00b088Sdonn 	     * of the original address.
16632f00b088Sdonn 	     */
16642f00b088Sdonn 	    if (v >= slr) {
16652f00b088Sdonn 		error("address %x out of segment", addr);
16662f00b088Sdonn 	    }
16672f00b088Sdonn 	    r = ((long) (sbr + v)) & ~0x80000000;
16682f00b088Sdonn 	    goto simple;
16692f00b088Sdonn 
16702f00b088Sdonn 	case 0x40000000:
16712f00b088Sdonn 	    /*
16722f00b088Sdonn 	     * In p1 space, must not be in shadow region.
16732f00b088Sdonn 	     */
16742f00b088Sdonn 	    if (v < pcb.pcb_p1lr) {
16752f00b088Sdonn 		error("address %x out of segment", addr);
16762f00b088Sdonn 	    }
16772f00b088Sdonn 	    r = (Address) (pcb.pcb_p1br + v);
16782f00b088Sdonn 	    break;
16792f00b088Sdonn 
16802f00b088Sdonn 	case 0x00000000:
16812f00b088Sdonn 	    /*
16822f00b088Sdonn 	     * In p0 space, must not be off end of region.
16832f00b088Sdonn 	     */
16842f00b088Sdonn 	    if (v >= pcb.pcb_p0lr) {
16852f00b088Sdonn 		error("address %x out of segment", addr);
16862f00b088Sdonn 	    }
16872f00b088Sdonn 	    r = (Address) (pcb.pcb_p0br + v);
16882f00b088Sdonn 	    break;
16892f00b088Sdonn 
16902f00b088Sdonn 	default:
16912f00b088Sdonn 	    /* do nothing */
16922f00b088Sdonn 	    break;
16932f00b088Sdonn     }
16942f00b088Sdonn     /*
16952f00b088Sdonn      * For p0/p1 address, user-level page table should be in
16962f00b088Sdonn      * kernel virtual memory.  Do second-level indirect by recursing.
16972f00b088Sdonn      */
16982f00b088Sdonn     if ((r & 0x80000000) == 0) {
16992f00b088Sdonn 	error("bad p0br or p1br in pcb");
17002f00b088Sdonn     }
17012f00b088Sdonn     r = vmap(r);
17022f00b088Sdonn simple:
17032f00b088Sdonn     /*
17042f00b088Sdonn      * "r" is now the address of the pte of the page
17052f00b088Sdonn      * we are interested in; get the pte and paste up the physical address.
17062f00b088Sdonn      */
17072f00b088Sdonn     fseek(corefile, r, 0);
17082f00b088Sdonn     n = fread(&pte, sizeof(pte), 1, corefile);
17092f00b088Sdonn     if (n != 1) {
17102f00b088Sdonn 	error("page table botch (fread at %x returns %d)", r, n);
17112f00b088Sdonn     }
17122f00b088Sdonn     if (pte.pg_v == 0 and (pte.pg_fod != 0 or pte.pg_pfnum == 0)) {
17132f00b088Sdonn 	error("page no valid or reclamable");
17142f00b088Sdonn     }
17152f00b088Sdonn     return (addr&PGOFSET) + ((Address) ptob(pte.pg_pfnum));
17162f00b088Sdonn }
17172f00b088Sdonn 
17182f00b088Sdonn /*
17192f00b088Sdonn  * Extract a bit field from an integer.
17202f00b088Sdonn  */
17212f00b088Sdonn 
extractField(s)17222f00b088Sdonn public integer extractField (s)
17232f00b088Sdonn Symbol s;
17242f00b088Sdonn {
17252f00b088Sdonn     integer nbytes, nbits, n, r, off, len;
17262f00b088Sdonn 
17272f00b088Sdonn     off = s->symvalue.field.offset;
17282f00b088Sdonn     len = s->symvalue.field.length;
17292f00b088Sdonn     nbytes = size(s);
17302f00b088Sdonn     n = 0;
17312f00b088Sdonn     if (nbytes > sizeof(n)) {
17322f00b088Sdonn 	printf("[bad size in extractField -- word assumed]\n");
17332f00b088Sdonn 	nbytes = sizeof(n);
17342f00b088Sdonn     }
17352f00b088Sdonn     popn(nbytes, ((char *) &n) + (sizeof(Word) - nbytes));
17362f00b088Sdonn     nbits = nbytes * BITSPERBYTE;
17372f00b088Sdonn     r = n >> (nbits - ((off mod nbits) + len));
17382f00b088Sdonn     r &= ((1 << len) - 1);
17392f00b088Sdonn     return r;
17402f00b088Sdonn }
17412f00b088Sdonn 
17422f00b088Sdonn /*
17432f00b088Sdonn  * Change the length of a value in memory according to a given difference
17442f00b088Sdonn  * in the lengths of its new and old types.
17452f00b088Sdonn  */
17462f00b088Sdonn 
loophole(oldlen,newlen)17472f00b088Sdonn public loophole (oldlen, newlen)
17482f00b088Sdonn integer oldlen, newlen;
17492f00b088Sdonn {
17502f00b088Sdonn     integer i, n;
17512f00b088Sdonn     Stack *oldsp;
17522f00b088Sdonn 
17532f00b088Sdonn     n = newlen - oldlen;
17542f00b088Sdonn     oldsp = sp - oldlen;
17552f00b088Sdonn     if (n > 0) {
17562f00b088Sdonn 	for (i = oldlen - 1; i >= 0; i--) {
17572f00b088Sdonn 	    oldsp[n + i] = oldsp[i];
17582f00b088Sdonn 	}
17592f00b088Sdonn 	for (i = 0; i < n; i++) {
17602f00b088Sdonn 	    oldsp[i] = '\0';
17612f00b088Sdonn 	}
17622f00b088Sdonn     } else {
17632f00b088Sdonn 	for (i = 0; i < newlen; i++) {
17642f00b088Sdonn 	    oldsp[i] = oldsp[i - n];
17652f00b088Sdonn 	}
17662f00b088Sdonn     }
17672f00b088Sdonn     sp += n;
17682f00b088Sdonn }
1769