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