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