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