xref: /csrg-svn/old/dbx/iris.c (revision 33318)
1*33318Sdonn /*
2*33318Sdonn  * Copyright (c) 1983 Regents of the University of California.
3*33318Sdonn  * All rights reserved.  The Berkeley software License Agreement
4*33318Sdonn  * specifies the terms and conditions for redistribution.
5*33318Sdonn  */
6*33318Sdonn 
7*33318Sdonn #ifndef lint
8*33318Sdonn static char sccsid[] = "@(#)iris.c	5.1 (Berkeley) 01/12/88";
9*33318Sdonn #endif not lint
10*33318Sdonn 
11*33318Sdonn static char rcsid[] = "$Header: machine.c,v 1.2 87/03/26 14:54:55 donn Exp $";
12*33318Sdonn 
13*33318Sdonn /*
14*33318Sdonn  * Target machine dependent stuff.
15*33318Sdonn  */
16*33318Sdonn 
17*33318Sdonn #include "defs.h"
18*33318Sdonn #include "machine.h"
19*33318Sdonn #include "process.h"
20*33318Sdonn #include "runtime.h"
21*33318Sdonn #include "events.h"
22*33318Sdonn #include "main.h"
23*33318Sdonn #include "symbols.h"
24*33318Sdonn #include "source.h"
25*33318Sdonn #include "mappings.h"
26*33318Sdonn #include "object.h"
27*33318Sdonn #include "tree.h"
28*33318Sdonn #include "eval.h"
29*33318Sdonn #include "keywords.h"
30*33318Sdonn #include "ops.h"
31*33318Sdonn 
32*33318Sdonn #ifndef public
33*33318Sdonn typedef unsigned int Address;
34*33318Sdonn typedef unsigned char Byte;
35*33318Sdonn typedef unsigned int Word;
36*33318Sdonn 
37*33318Sdonn /*
38*33318Sdonn  * On the 68000, the pc isn't in a register, but we make believe
39*33318Sdonn  * so there's one more register.
40*33318Sdonn  *
41*33318Sdonn  * Note that there's also no argument pointer, this means code
42*33318Sdonn  * involving "ARGP" should always be #ifdef'd.
43*33318Sdonn  *
44*33318Sdonn  * The address corresponding to the beginning of a function is recorded
45*33318Sdonn  * as the address + FUNCOFFSET (skip the link instruction so that
46*33318Sdonn  * local information is available).
47*33318Sdonn  */
48*33318Sdonn 
49*33318Sdonn #define NREG 17
50*33318Sdonn 
51*33318Sdonn #define FRP 14
52*33318Sdonn #define STKP 15
53*33318Sdonn #define PROGCTR 16
54*33318Sdonn 
55*33318Sdonn #define CALL_RETADDR	0x800c		/* Return address for 'call' command */
56*33318Sdonn #define FUNCOFFSET 4
57*33318Sdonn 
58*33318Sdonn #ifdef sun
59*33318Sdonn #    define CODESTART 0x8000
60*33318Sdonn #else /* IRIS */
61*33318Sdonn #   define CODESTART 0x1000
62*33318Sdonn #endif
63*33318Sdonn 
64*33318Sdonn #define optab_init()
65*33318Sdonn 
66*33318Sdonn #define BITSPERBYTE 8
67*33318Sdonn #define BITSPERWORD (BITSPERBYTE * sizeof(Word))
68*33318Sdonn 
69*33318Sdonn /*
70*33318Sdonn  * This magic macro enables us to look at the process' registers
71*33318Sdonn  * in its user structure.
72*33318Sdonn  */
73*33318Sdonn 
74*33318Sdonn #define regloc(reg)	(ctob(UPAGES) + (sizeof(Word) * ((reg) - PC)) - 10)
75*33318Sdonn 
76*33318Sdonn #include "source.h"
77*33318Sdonn #include "symbols.h"
78*33318Sdonn #include <signal.h>
79*33318Sdonn #include <sys/param.h>
80*33318Sdonn #include <sys/dir.h>
81*33318Sdonn #include <machine/psl.h>
82*33318Sdonn #include <machine/pte.h>
83*33318Sdonn #include <sys/user.h>
84*33318Sdonn #undef DELETE /* XXX */
85*33318Sdonn #include <sys/vm.h>
86*33318Sdonn #include <machine/reg.h>
87*33318Sdonn 
88*33318Sdonn Address pc;
89*33318Sdonn Address prtaddr;
90*33318Sdonn 
91*33318Sdonn #endif
92*33318Sdonn 
93*33318Sdonn /*
94*33318Sdonn  * Indices into u. for use in collecting registers values.
95*33318Sdonn  */
96*33318Sdonn public int rloc[] ={
97*33318Sdonn #ifdef sun
98*33318Sdonn     R0, R1, R2, R3, R4, R5, R6, R7, AR0, AR1, AR2, AR3, AR4, AR5, AR6, AR7, PC
99*33318Sdonn #else /* IRIS */
100*33318Sdonn     R0, R1, R2, R3, R4, R5, R6, R7, AR0, AR1, AR2, AR3, AR4, AR5, AR6, AR7, 16
101*33318Sdonn #endif
102*33318Sdonn };
103*33318Sdonn 
104*33318Sdonn private Address printop();
105*33318Sdonn 
106*33318Sdonn /*
107*33318Sdonn  * Decode and print the instructions within the given address range.
108*33318Sdonn  */
109*33318Sdonn 
110*33318Sdonn public printinst(lowaddr, highaddr)
111*33318Sdonn Address lowaddr;
112*33318Sdonn Address highaddr;
113*33318Sdonn {
114*33318Sdonn     register Address addr;
115*33318Sdonn 
116*33318Sdonn     for (addr = lowaddr; addr <= highaddr; ) {
117*33318Sdonn 	addr = printop(addr);
118*33318Sdonn     }
119*33318Sdonn     prtaddr = addr;
120*33318Sdonn }
121*33318Sdonn 
122*33318Sdonn /*
123*33318Sdonn  * Another approach:  print n instructions starting at the given address.
124*33318Sdonn  */
125*33318Sdonn 
126*33318Sdonn public printninst(count, addr)
127*33318Sdonn int count;
128*33318Sdonn Address addr;
129*33318Sdonn {
130*33318Sdonn     register Integer i;
131*33318Sdonn     register Address newaddr;
132*33318Sdonn 
133*33318Sdonn     if (count <= 0) {
134*33318Sdonn 	error("non-positive repetition count");
135*33318Sdonn     } else {
136*33318Sdonn 	newaddr = addr;
137*33318Sdonn 	for (i = 0; i < count; i++) {
138*33318Sdonn 	    newaddr = printop(newaddr);
139*33318Sdonn 	}
140*33318Sdonn 	prtaddr = newaddr;
141*33318Sdonn     }
142*33318Sdonn }
143*33318Sdonn 
144*33318Sdonn /*
145*33318Sdonn  * Print the contents of the addresses within the given range
146*33318Sdonn  * according to the given format.
147*33318Sdonn  */
148*33318Sdonn 
149*33318Sdonn typedef struct {
150*33318Sdonn     String name;
151*33318Sdonn     String printfstring;
152*33318Sdonn     int length;
153*33318Sdonn } Format;
154*33318Sdonn 
155*33318Sdonn private Format fmt[] = {
156*33318Sdonn     { "d", " %d", sizeof(short) },
157*33318Sdonn     { "D", " %ld", sizeof(long) },
158*33318Sdonn     { "o", " %o", sizeof(short) },
159*33318Sdonn     { "O", " %lo", sizeof(long) },
160*33318Sdonn     { "x", " %04x", sizeof(short) },
161*33318Sdonn     { "X", " %08x", sizeof(long) },
162*33318Sdonn     { "b", " \\%o", sizeof(char) },
163*33318Sdonn     { "c", " '%c'", sizeof(char) },
164*33318Sdonn     { "s", "%c", sizeof(char) },
165*33318Sdonn     { "f", " %f", sizeof(float) },
166*33318Sdonn     { "g", " %g", sizeof(double) },
167*33318Sdonn     { nil, nil, 0 }
168*33318Sdonn };
169*33318Sdonn 
170*33318Sdonn private Format *findformat(s)
171*33318Sdonn String s;
172*33318Sdonn {
173*33318Sdonn     register Format *f;
174*33318Sdonn 
175*33318Sdonn     f = &fmt[0];
176*33318Sdonn     while (f->name != nil and not streq(f->name, s)) {
177*33318Sdonn 	++f;
178*33318Sdonn     }
179*33318Sdonn     if (f->name == nil) {
180*33318Sdonn 	error("bad print format \"%s\"", s);
181*33318Sdonn     }
182*33318Sdonn     return f;
183*33318Sdonn }
184*33318Sdonn 
185*33318Sdonn /*
186*33318Sdonn  * Retrieve and print out the appropriate data in the given format.
187*33318Sdonn  * Floats have to be handled specially to allow the compiler to
188*33318Sdonn  * convert them to doubles when passing to printf.
189*33318Sdonn  */
190*33318Sdonn 
191*33318Sdonn private printformat (f, addr)
192*33318Sdonn Format *f;
193*33318Sdonn Address addr;
194*33318Sdonn {
195*33318Sdonn     union {
196*33318Sdonn 	char charv;
197*33318Sdonn 	short shortv;
198*33318Sdonn 	int intv;
199*33318Sdonn 	float floatv;
200*33318Sdonn 	double doublev;
201*33318Sdonn     } value;
202*33318Sdonn 
203*33318Sdonn     value.intv = 0;
204*33318Sdonn     dread(&value, addr, f->length);
205*33318Sdonn     if (streq(f->name, "f")) {
206*33318Sdonn 	printf(f->printfstring, value.floatv);
207*33318Sdonn     } else {
208*33318Sdonn 	printf(f->printfstring, value);
209*33318Sdonn     }
210*33318Sdonn }
211*33318Sdonn 
212*33318Sdonn public Address printdata(lowaddr, highaddr, format)
213*33318Sdonn Address lowaddr;
214*33318Sdonn Address highaddr;
215*33318Sdonn String format;
216*33318Sdonn {
217*33318Sdonn     int n;
218*33318Sdonn     register Address addr;
219*33318Sdonn     Format *f;
220*33318Sdonn 
221*33318Sdonn     if (lowaddr > highaddr) {
222*33318Sdonn 	error("first address larger than second");
223*33318Sdonn     }
224*33318Sdonn     f = findformat(format);
225*33318Sdonn     n = 0;
226*33318Sdonn     for (addr = lowaddr; addr <= highaddr; addr += f->length) {
227*33318Sdonn 	if (n == 0) {
228*33318Sdonn 	    printf("%08x: ", addr);
229*33318Sdonn 	}
230*33318Sdonn 	printformat(f, addr);
231*33318Sdonn 	++n;
232*33318Sdonn 	if (n >= (16 div f->length)) {
233*33318Sdonn 	    printf("\n");
234*33318Sdonn 	    n = 0;
235*33318Sdonn 	}
236*33318Sdonn     }
237*33318Sdonn     if (n != 0) {
238*33318Sdonn 	printf("\n");
239*33318Sdonn     }
240*33318Sdonn     prtaddr = addr;
241*33318Sdonn     return addr;
242*33318Sdonn }
243*33318Sdonn 
244*33318Sdonn /*
245*33318Sdonn  * The other approach is to print n items starting with a given address.
246*33318Sdonn  */
247*33318Sdonn 
248*33318Sdonn public printndata(count, startaddr, format)
249*33318Sdonn int count;
250*33318Sdonn Address startaddr;
251*33318Sdonn String format;
252*33318Sdonn {
253*33318Sdonn     int i, n;
254*33318Sdonn     Address addr;
255*33318Sdonn     Format *f;
256*33318Sdonn     Boolean isstring;
257*33318Sdonn     char c;
258*33318Sdonn 
259*33318Sdonn     if (count <= 0) {
260*33318Sdonn 	error("non-positive repetition count");
261*33318Sdonn     }
262*33318Sdonn     f = findformat(format);
263*33318Sdonn     isstring = (Boolean) streq(f->name, "s");
264*33318Sdonn     n = 0;
265*33318Sdonn     addr = startaddr;
266*33318Sdonn     for (i = 0; i < count; i++) {
267*33318Sdonn 	if (n == 0) {
268*33318Sdonn 	    printf("%08x: ", addr);
269*33318Sdonn 	}
270*33318Sdonn 	if (isstring) {
271*33318Sdonn 	    printf("\"");
272*33318Sdonn 	    dread(&c, addr, sizeof(char));
273*33318Sdonn 	    while (c != '\0') {
274*33318Sdonn 		printchar(c);
275*33318Sdonn 		++addr;
276*33318Sdonn 		dread(&c, addr, sizeof(char));
277*33318Sdonn 	    }
278*33318Sdonn 	    printf("\"\n");
279*33318Sdonn 	    n = 0;
280*33318Sdonn 	    addr += sizeof(String);
281*33318Sdonn 	} else {
282*33318Sdonn 	    printformat(f, addr);
283*33318Sdonn 	    ++n;
284*33318Sdonn 	    if (n >= (16 div f->length)) {
285*33318Sdonn 		printf("\n");
286*33318Sdonn 		n = 0;
287*33318Sdonn 	    }
288*33318Sdonn 	    addr += f->length;
289*33318Sdonn 	}
290*33318Sdonn     }
291*33318Sdonn     if (n != 0) {
292*33318Sdonn 	printf("\n");
293*33318Sdonn     }
294*33318Sdonn     prtaddr = addr;
295*33318Sdonn }
296*33318Sdonn 
297*33318Sdonn /*
298*33318Sdonn  * Print out a value according to the given format.
299*33318Sdonn  */
300*33318Sdonn 
301*33318Sdonn public printvalue(v, format)
302*33318Sdonn long v;
303*33318Sdonn String format;
304*33318Sdonn {
305*33318Sdonn     Format *f;
306*33318Sdonn     char *p, *q;
307*33318Sdonn 
308*33318Sdonn     f = findformat(format);
309*33318Sdonn     if (streq(f->name, "s")) {
310*33318Sdonn 	putchar('"');
311*33318Sdonn 	p = (char *) &v;
312*33318Sdonn 	q = p + sizeof(v);
313*33318Sdonn 	while (p < q) {
314*33318Sdonn 	    printchar(*p);
315*33318Sdonn 	    ++p;
316*33318Sdonn 	}
317*33318Sdonn 	putchar('"');
318*33318Sdonn     } else {
319*33318Sdonn 	printf(f->printfstring, v);
320*33318Sdonn     }
321*33318Sdonn     putchar('\n');
322*33318Sdonn }
323*33318Sdonn 
324*33318Sdonn /*
325*33318Sdonn  * Print out an execution time error.
326*33318Sdonn  * Assumes the source position of the error has been calculated.
327*33318Sdonn  *
328*33318Sdonn  * Have to check if the -r option was specified; if so then
329*33318Sdonn  * the object file information hasn't been read in yet.
330*33318Sdonn  */
331*33318Sdonn 
332*33318Sdonn public printerror()
333*33318Sdonn {
334*33318Sdonn     extern Integer sys_nsig;
335*33318Sdonn     extern String sys_siglist[];
336*33318Sdonn     integer err;
337*33318Sdonn 
338*33318Sdonn     if (isfinished(process)) {
339*33318Sdonn 	err = exitcode(process);
340*33318Sdonn 	if (err == 0) {
341*33318Sdonn 	    printf("\"%s\" terminated normally\n", objname);
342*33318Sdonn 	} else {
343*33318Sdonn 	    printf("\"%s\" terminated abnormally (exit code %d)\n",
344*33318Sdonn 		objname, err
345*33318Sdonn 	    );
346*33318Sdonn 	}
347*33318Sdonn 	erecover();
348*33318Sdonn     }
349*33318Sdonn     err = errnum(process);
350*33318Sdonn     putchar('\n');
351*33318Sdonn     printsig(err);
352*33318Sdonn     putchar(' ');
353*33318Sdonn     printloc();
354*33318Sdonn     putchar('\n');
355*33318Sdonn     if (curline > 0) {
356*33318Sdonn 	printlines(curline, curline);
357*33318Sdonn     } else {
358*33318Sdonn 	printinst(pc, pc);
359*33318Sdonn     }
360*33318Sdonn     erecover();
361*33318Sdonn }
362*33318Sdonn 
363*33318Sdonn /*
364*33318Sdonn  * Print out a signal.
365*33318Sdonn  */
366*33318Sdonn 
367*33318Sdonn private String illinames[] = {
368*33318Sdonn     "reserved addressing fault",
369*33318Sdonn     "privileged instruction fault",
370*33318Sdonn     "reserved operand fault"
371*33318Sdonn };
372*33318Sdonn 
373*33318Sdonn private String fpenames[] = {
374*33318Sdonn     nil,
375*33318Sdonn     "integer overflow trap",
376*33318Sdonn     "integer divide by zero trap",
377*33318Sdonn     "floating overflow trap",
378*33318Sdonn     "floating/decimal divide by zero trap",
379*33318Sdonn     "floating underflow trap",
380*33318Sdonn     "decimal overflow trap",
381*33318Sdonn     "subscript out of range trap",
382*33318Sdonn     "floating overflow fault",
383*33318Sdonn     "floating divide by zero fault",
384*33318Sdonn     "floating underflow fault"
385*33318Sdonn };
386*33318Sdonn 
387*33318Sdonn public printsig (signo)
388*33318Sdonn integer signo;
389*33318Sdonn {
390*33318Sdonn     integer code;
391*33318Sdonn 
392*33318Sdonn     if (signo < 0 or signo > sys_nsig) {
393*33318Sdonn 	printf("[signal %d]", signo);
394*33318Sdonn     } else {
395*33318Sdonn 	printf("%s", sys_siglist[signo]);
396*33318Sdonn     }
397*33318Sdonn     code = errcode(process);
398*33318Sdonn     if (signo == SIGILL) {
399*33318Sdonn 	if (code >= 0 and code < sizeof(illinames) / sizeof(illinames[0])) {
400*33318Sdonn 	    printf(" (%s)", illinames[code]);
401*33318Sdonn 	}
402*33318Sdonn     } else if (signo == SIGFPE) {
403*33318Sdonn 	if (code > 0 and code < sizeof(fpenames) / sizeof(fpenames[0])) {
404*33318Sdonn 	    printf(" (%s)", fpenames[code]);
405*33318Sdonn 	}
406*33318Sdonn     }
407*33318Sdonn }
408*33318Sdonn 
409*33318Sdonn /*
410*33318Sdonn  * Note the termination of the program.  We do this so as to avoid
411*33318Sdonn  * having the process exit, which would make the values of variables
412*33318Sdonn  * inaccessible.  We do want to flush all output buffers here,
413*33318Sdonn  * otherwise it'll never get done.
414*33318Sdonn  */
415*33318Sdonn 
416*33318Sdonn public endprogram()
417*33318Sdonn {
418*33318Sdonn     Integer exitcode;
419*33318Sdonn 
420*33318Sdonn     stepto(nextaddr(pc, true));
421*33318Sdonn     printnews();
422*33318Sdonn     exitcode = argn(1, nil);
423*33318Sdonn     if (exitcode != 0) {
424*33318Sdonn 	printf("\nexecution completed (exit code %d)\n", exitcode);
425*33318Sdonn     } else {
426*33318Sdonn 	printf("\nexecution completed\n");
427*33318Sdonn     }
428*33318Sdonn     getsrcpos();
429*33318Sdonn     erecover();
430*33318Sdonn }
431*33318Sdonn 
432*33318Sdonn /*
433*33318Sdonn  * Single step the machine a source line (or instruction if "inst_tracing"
434*33318Sdonn  * is true).  If "isnext" is true, skip over procedure calls.
435*33318Sdonn  */
436*33318Sdonn 
437*33318Sdonn private Address getcall();
438*33318Sdonn 
439*33318Sdonn public dostep(isnext)
440*33318Sdonn Boolean isnext;
441*33318Sdonn {
442*33318Sdonn     register Address addr;
443*33318Sdonn     register Lineno line;
444*33318Sdonn     String filename;
445*33318Sdonn     Address startaddr;
446*33318Sdonn 
447*33318Sdonn     startaddr = pc;
448*33318Sdonn     addr = nextaddr(pc, isnext);
449*33318Sdonn     if (not inst_tracing and nlhdr.nlines != 0) {
450*33318Sdonn 	line = linelookup(addr);
451*33318Sdonn 	while (line == 0) {
452*33318Sdonn 	    addr = nextaddr(addr, isnext);
453*33318Sdonn 	    line = linelookup(addr);
454*33318Sdonn 	}
455*33318Sdonn 	curline = line;
456*33318Sdonn     } else {
457*33318Sdonn 	curline = 0;
458*33318Sdonn     }
459*33318Sdonn     stepto(addr);
460*33318Sdonn     filename = srcfilename(addr);
461*33318Sdonn     setsource(filename);
462*33318Sdonn }
463*33318Sdonn 
464*33318Sdonn typedef short Bpinst;
465*33318Sdonn 
466*33318Sdonn extern Bpinst BP_OP;
467*33318Sdonn #ifdef sun
468*33318Sdonn 	asm("_BP_OP: trap #15");
469*33318Sdonn #else /* IRIS */
470*33318Sdonn 	asm("_BP_OP: trap #1");
471*33318Sdonn #endif
472*33318Sdonn 
473*33318Sdonn #define BP_ERRNO    SIGTRAP     /* signal received at a breakpoint */
474*33318Sdonn 
475*33318Sdonn /*
476*33318Sdonn  * Setting a breakpoint at a location consists of saving
477*33318Sdonn  * the word at the location and poking a BP_OP there.
478*33318Sdonn  *
479*33318Sdonn  * We save the locations and words on a list for use in unsetting.
480*33318Sdonn  */
481*33318Sdonn 
482*33318Sdonn typedef struct Savelist *Savelist;
483*33318Sdonn 
484*33318Sdonn struct Savelist {
485*33318Sdonn     Address location;
486*33318Sdonn     Bpinst save;
487*33318Sdonn     short refcount;
488*33318Sdonn     Savelist link;
489*33318Sdonn };
490*33318Sdonn 
491*33318Sdonn private Savelist savelist;
492*33318Sdonn 
493*33318Sdonn /*
494*33318Sdonn  * Set a breakpoint at the given address.  Only save the word there
495*33318Sdonn  * if it's not already a breakpoint.
496*33318Sdonn  */
497*33318Sdonn 
498*33318Sdonn public setbp(addr)
499*33318Sdonn Address addr;
500*33318Sdonn {
501*33318Sdonn     Bpinst w, save;
502*33318Sdonn     register Savelist newsave, s;
503*33318Sdonn 
504*33318Sdonn     for (s = savelist; s != nil; s = s->link) {
505*33318Sdonn 	if (s->location == addr) {
506*33318Sdonn 	    s->refcount++;
507*33318Sdonn 	    return;
508*33318Sdonn 	}
509*33318Sdonn     }
510*33318Sdonn     iread(&save, addr, sizeof(save));
511*33318Sdonn     newsave = new(Savelist);
512*33318Sdonn     newsave->location = addr;
513*33318Sdonn     newsave->save = save;
514*33318Sdonn     newsave->refcount = 1;
515*33318Sdonn     newsave->link = savelist;
516*33318Sdonn     savelist = newsave;
517*33318Sdonn     w = BP_OP;
518*33318Sdonn     iwrite(&w, addr, sizeof(w));
519*33318Sdonn }
520*33318Sdonn 
521*33318Sdonn /*
522*33318Sdonn  * Unset a breakpoint; unfortunately we have to search the SAVELIST
523*33318Sdonn  * to find the saved value.  The assumption is that the SAVELIST will
524*33318Sdonn  * usually be quite small.
525*33318Sdonn  */
526*33318Sdonn 
527*33318Sdonn public unsetbp(addr)
528*33318Sdonn Address addr;
529*33318Sdonn {
530*33318Sdonn     register Savelist s, prev;
531*33318Sdonn 
532*33318Sdonn     prev = nil;
533*33318Sdonn     for (s = savelist; s != nil; s = s->link) {
534*33318Sdonn 	if (s->location == addr) {
535*33318Sdonn 	    iwrite(&s->save, addr, sizeof(s->save));
536*33318Sdonn 	    s->refcount--;
537*33318Sdonn 	    if (s->refcount == 0) {
538*33318Sdonn 		if (prev == nil) {
539*33318Sdonn 		    savelist = s->link;
540*33318Sdonn 		} else {
541*33318Sdonn 		    prev->link = s->link;
542*33318Sdonn 		}
543*33318Sdonn 		dispose(s);
544*33318Sdonn 	    }
545*33318Sdonn 	    return;
546*33318Sdonn 	}
547*33318Sdonn 	prev = s;
548*33318Sdonn     }
549*33318Sdonn     panic("unsetbp: couldn't find address %d", addr);
550*33318Sdonn }
551*33318Sdonn 
552*33318Sdonn /*
553*33318Sdonn  * Instruction decoding routines for 68000, derived from adb.
554*33318Sdonn  *
555*33318Sdonn  * The shared boolean variable "printing" is true if the decoded
556*33318Sdonn  * instruction is to be printed, false if not.  In either case,
557*33318Sdonn  * the address of the next instruction after the given one is returned.
558*33318Sdonn  */
559*33318Sdonn 
560*33318Sdonn private Boolean printing;
561*33318Sdonn private Boolean following;
562*33318Sdonn private Boolean followcalls;
563*33318Sdonn private Address instaddr;
564*33318Sdonn 
565*33318Sdonn #define instread(var) \
566*33318Sdonn { \
567*33318Sdonn     iread(&var, instaddr, sizeof(var)); \
568*33318Sdonn     instaddr += sizeof(var); \
569*33318Sdonn }
570*33318Sdonn 
571*33318Sdonn private Optab *decode(inst, addr)
572*33318Sdonn Word inst;
573*33318Sdonn Address addr;
574*33318Sdonn {
575*33318Sdonn     register Optab *o;
576*33318Sdonn 
577*33318Sdonn     o = &optab[0];
578*33318Sdonn     while (o->mask != 0 and (inst&o->mask) != o->match) {
579*33318Sdonn 	++o;
580*33318Sdonn     }
581*33318Sdonn     return o;
582*33318Sdonn }
583*33318Sdonn 
584*33318Sdonn private Address printop(addr)
585*33318Sdonn Address addr;
586*33318Sdonn {
587*33318Sdonn     Optab *o;
588*33318Sdonn     short inst;
589*33318Sdonn 
590*33318Sdonn     printf("%08x  ", addr);
591*33318Sdonn     iread(&inst, addr, sizeof(inst));
592*33318Sdonn     o = decode(inst, addr);
593*33318Sdonn     if (o->mask == 0) {
594*33318Sdonn 	printf("\tbadop");
595*33318Sdonn 	instaddr = addr + sizeof(inst);
596*33318Sdonn     } else {
597*33318Sdonn 	printing = true;
598*33318Sdonn 	following = false;
599*33318Sdonn 	instaddr = addr + sizeof(inst);
600*33318Sdonn 	(*o->opfun)(inst, o->farg);
601*33318Sdonn 	printing = false;
602*33318Sdonn     }
603*33318Sdonn     printf("\n");
604*33318Sdonn     return instaddr;
605*33318Sdonn }
606*33318Sdonn 
607*33318Sdonn /*
608*33318Sdonn  * Quickly find the return address of the current procedure or function
609*33318Sdonn  * while single stepping.  Just get the word pointed at by sp.
610*33318Sdonn  */
611*33318Sdonn 
612*33318Sdonn private Address currtnaddr ()
613*33318Sdonn {
614*33318Sdonn     Address retaddr;
615*33318Sdonn 
616*33318Sdonn     dread(&retaddr, reg(STKP), sizeof(retaddr));
617*33318Sdonn     return retaddr;
618*33318Sdonn }
619*33318Sdonn 
620*33318Sdonn /*
621*33318Sdonn  * Print out the effective address for the given parameters.
622*33318Sdonn  */
623*33318Sdonn 
624*33318Sdonn private printea(mode, reg, size)
625*33318Sdonn long mode, reg;
626*33318Sdonn int size;
627*33318Sdonn {
628*33318Sdonn     long index, disp;
629*33318Sdonn     static char *aregs[] = { "a0", "a1", "a2", "a3", "a4", "a5", "a6", "sp" };
630*33318Sdonn     Byte b;
631*33318Sdonn     short w;
632*33318Sdonn     long l;
633*33318Sdonn 
634*33318Sdonn     switch ((int)(mode)) {
635*33318Sdonn 	case 0:
636*33318Sdonn 	    if (printing) {
637*33318Sdonn 		printf("d%D", reg);
638*33318Sdonn 	    }
639*33318Sdonn 	    break;
640*33318Sdonn 
641*33318Sdonn 	case 1:
642*33318Sdonn 	    if (printing) {
643*33318Sdonn 		printf("%s", aregs[reg]);
644*33318Sdonn 	    }
645*33318Sdonn 	    break;
646*33318Sdonn 
647*33318Sdonn 	case 2:
648*33318Sdonn 	    if (printing) {
649*33318Sdonn 		printf("%s@", aregs[reg]);
650*33318Sdonn 	    }
651*33318Sdonn 	    break;
652*33318Sdonn 
653*33318Sdonn 	case 3:
654*33318Sdonn 	    if (printing) {
655*33318Sdonn 		printf("%s@+", aregs[reg]);
656*33318Sdonn 	    }
657*33318Sdonn 	    break;
658*33318Sdonn 
659*33318Sdonn 	case 4:
660*33318Sdonn 	    if (printing) {
661*33318Sdonn 		printf("%s@-", aregs[reg]);
662*33318Sdonn 	    }
663*33318Sdonn 	    break;
664*33318Sdonn 
665*33318Sdonn 	case 5:
666*33318Sdonn 	    instread(w);
667*33318Sdonn 	    if (printing) {
668*33318Sdonn 		printf("%s@(%D)", aregs[reg], w);
669*33318Sdonn 	    }
670*33318Sdonn 	    break;
671*33318Sdonn 
672*33318Sdonn 	case 6:
673*33318Sdonn 	    instread(w);
674*33318Sdonn 	    if (printing) {
675*33318Sdonn 		index = w;
676*33318Sdonn 		disp = (char)(index&0377);
677*33318Sdonn 		printf("%s@(%d,%c%D:%c)", aregs[reg], disp,
678*33318Sdonn 		    (index&0100000)?'a':'d',(index>>12)&07,
679*33318Sdonn 		    (index&04000)?'l':'w');
680*33318Sdonn 	    }
681*33318Sdonn 	    break;
682*33318Sdonn 
683*33318Sdonn 	case 7:
684*33318Sdonn 	    switch ((int)(reg)) {
685*33318Sdonn 		case 0:
686*33318Sdonn 		    instread(w);
687*33318Sdonn 		    if (printing) {
688*33318Sdonn 			index = w;
689*33318Sdonn 			psymoff(index);
690*33318Sdonn 		    }
691*33318Sdonn 		    break;
692*33318Sdonn 
693*33318Sdonn 		case 1:
694*33318Sdonn 		    instread(l);
695*33318Sdonn 		    if (printing) {
696*33318Sdonn 			index = l;
697*33318Sdonn 			psymoff(index);
698*33318Sdonn 		    }
699*33318Sdonn 		    break;
700*33318Sdonn 
701*33318Sdonn 		case 2:
702*33318Sdonn 		    instread(w);
703*33318Sdonn 		    if (printing) {
704*33318Sdonn 			disp = w;
705*33318Sdonn 			psymoff(disp + instaddr);
706*33318Sdonn 		    }
707*33318Sdonn 		    break;
708*33318Sdonn 
709*33318Sdonn 		case 3:
710*33318Sdonn 		    instread(w);
711*33318Sdonn 		    if (printing) {
712*33318Sdonn 			index = w;
713*33318Sdonn 			disp = (char)(index&0377);
714*33318Sdonn 			printf("pc@(%D,%c%D:%c)", disp,
715*33318Sdonn 			    (index&0100000)?'a':'d',(index>>12)&07,
716*33318Sdonn 			    (index&04000)?'l':'w');
717*33318Sdonn 		    }
718*33318Sdonn 		    break;
719*33318Sdonn 
720*33318Sdonn 		case 4:
721*33318Sdonn 		    switch (size) {
722*33318Sdonn 			case sizeof(b):
723*33318Sdonn 			    instread(w);
724*33318Sdonn 			    index = (w&0xff);
725*33318Sdonn 			    break;
726*33318Sdonn 
727*33318Sdonn 			case sizeof(w):
728*33318Sdonn 			    instread(w);
729*33318Sdonn 			    index = w;
730*33318Sdonn 			    break;
731*33318Sdonn 
732*33318Sdonn 			case sizeof(l):
733*33318Sdonn 			    instread(l);
734*33318Sdonn 			    index = l;
735*33318Sdonn 			    break;
736*33318Sdonn 
737*33318Sdonn 			default:
738*33318Sdonn 			    if (printing) {
739*33318Sdonn 			    	printf("unexpected size %d in printea\n", size);
740*33318Sdonn 			    }
741*33318Sdonn 			    instread(l);
742*33318Sdonn 			    index = l;
743*33318Sdonn 			    break;
744*33318Sdonn 		    }
745*33318Sdonn 		    if (printing) {
746*33318Sdonn 			printf(IMDF, index);
747*33318Sdonn 		    }
748*33318Sdonn 		    break;
749*33318Sdonn 
750*33318Sdonn 		default:
751*33318Sdonn 		    if (printing) {
752*33318Sdonn 			printf("???");
753*33318Sdonn 		    }
754*33318Sdonn 		    break;
755*33318Sdonn 	    }
756*33318Sdonn 	    break;
757*33318Sdonn 
758*33318Sdonn 	default:
759*33318Sdonn 	    if (printing) {
760*33318Sdonn 		printf("???");
761*33318Sdonn 	    }
762*33318Sdonn 	    break;
763*33318Sdonn     }
764*33318Sdonn }
765*33318Sdonn 
766*33318Sdonn private printEA(ea, size)
767*33318Sdonn long ea;
768*33318Sdonn int size;
769*33318Sdonn {
770*33318Sdonn     printea((ea>>3)&07, ea&07, size);
771*33318Sdonn }
772*33318Sdonn 
773*33318Sdonn private mapsize(inst)
774*33318Sdonn register long inst;
775*33318Sdonn {
776*33318Sdonn     int m;
777*33318Sdonn 
778*33318Sdonn     inst >>= 6;
779*33318Sdonn     inst &= 03;
780*33318Sdonn     switch (inst) {
781*33318Sdonn 	case 0:
782*33318Sdonn 	    m = 1;
783*33318Sdonn 	    break;
784*33318Sdonn 
785*33318Sdonn 	case 1:
786*33318Sdonn 	    m = 2;
787*33318Sdonn 	    break;
788*33318Sdonn 
789*33318Sdonn 	case 2:
790*33318Sdonn 	    m = 4;
791*33318Sdonn 	    break;
792*33318Sdonn 
793*33318Sdonn 	default:
794*33318Sdonn 	    m = -1;
795*33318Sdonn 	    break;
796*33318Sdonn     }
797*33318Sdonn     return m;
798*33318Sdonn }
799*33318Sdonn 
800*33318Sdonn private char suffix(size)
801*33318Sdonn int size;
802*33318Sdonn {
803*33318Sdonn     char c;
804*33318Sdonn 
805*33318Sdonn     switch (size) {
806*33318Sdonn 	case 1:
807*33318Sdonn 	    c = 'b';
808*33318Sdonn 	    break;
809*33318Sdonn 
810*33318Sdonn 	case 2:
811*33318Sdonn 	    c = 'w';
812*33318Sdonn 	    break;
813*33318Sdonn 
814*33318Sdonn 	case 4:
815*33318Sdonn 	    c = 'l';
816*33318Sdonn 	    break;
817*33318Sdonn 
818*33318Sdonn 	default:
819*33318Sdonn 	    panic("bad size %d in suffix", size);
820*33318Sdonn     }
821*33318Sdonn     return c;
822*33318Sdonn }
823*33318Sdonn 
824*33318Sdonn /*
825*33318Sdonn  * Print an address offset.  Eventually this should attempt to be symbolic,
826*33318Sdonn  * but for now its just printed in hex.
827*33318Sdonn  */
828*33318Sdonn 
829*33318Sdonn private psymoff (off)
830*33318Sdonn Word off;
831*33318Sdonn {
832*33318Sdonn     Symbol f;
833*33318Sdonn 
834*33318Sdonn     f = whatblock((Address) (off + FUNCOFFSET));
835*33318Sdonn     if (codeloc(f) == off + FUNCOFFSET) {
836*33318Sdonn 	printf("%s", symname(f));
837*33318Sdonn     } else {
838*33318Sdonn 	printf("0x%x", off);
839*33318Sdonn     }
840*33318Sdonn }
841*33318Sdonn 
842*33318Sdonn /*
843*33318Sdonn  * Instruction class specific routines.
844*33318Sdonn  */
845*33318Sdonn 
846*33318Sdonn public omove(inst, s)
847*33318Sdonn long inst;
848*33318Sdonn String s;
849*33318Sdonn {
850*33318Sdonn     register int c;
851*33318Sdonn     int size;
852*33318Sdonn 
853*33318Sdonn     c = s[0];
854*33318Sdonn     if (printing) {
855*33318Sdonn 	printf("\tmov%c\t", c);
856*33318Sdonn     }
857*33318Sdonn     size = ((c == 'b') ? 1 : (c == 'w') ? 2 : 4);
858*33318Sdonn     printea((inst>>3)&07, inst&07, size);
859*33318Sdonn     if (printing) {
860*33318Sdonn 	printf(",");
861*33318Sdonn     }
862*33318Sdonn     printea((inst>>6)&07, (inst>>9)&07, size);
863*33318Sdonn }
864*33318Sdonn 
865*33318Sdonn /*
866*33318Sdonn  * Two types: bsr (4 bytes) and bsrs (2 bytes)
867*33318Sdonn  */
868*33318Sdonn 
869*33318Sdonn public obranch(inst, dummy)
870*33318Sdonn long inst;
871*33318Sdonn {
872*33318Sdonn     long disp;
873*33318Sdonn     String s;
874*33318Sdonn     short w;
875*33318Sdonn     Address startingaddr;	/* address of branch instruction */
876*33318Sdonn     int branchtype;		/* type of branch (0 = unconditional) */
877*33318Sdonn     Address dest;
878*33318Sdonn     Address retaddr;		/* for bsr instruction */
879*33318Sdonn 
880*33318Sdonn     startingaddr = instaddr - 2;
881*33318Sdonn     disp = inst&0377;
882*33318Sdonn     s = "s ";
883*33318Sdonn     if (disp == 0) {
884*33318Sdonn 	retaddr = startingaddr + 4;
885*33318Sdonn     } else {
886*33318Sdonn 	retaddr = startingaddr + 2;
887*33318Sdonn     }
888*33318Sdonn     if (disp > 127) {
889*33318Sdonn 	disp |= ~0377;
890*33318Sdonn     } else if (disp == 0){
891*33318Sdonn 	s = " ";
892*33318Sdonn 	instread(w);
893*33318Sdonn 	disp = w;
894*33318Sdonn     }
895*33318Sdonn     branchtype = (int)((inst>>8)&017);
896*33318Sdonn     dest = startingaddr + 2 + disp;
897*33318Sdonn     if (printing) {
898*33318Sdonn 	printf("\tb%s%s\t", bname[branchtype], s);
899*33318Sdonn 	psymoff(dest);
900*33318Sdonn     }
901*33318Sdonn     if (following) {
902*33318Sdonn 	/*
903*33318Sdonn 	 * If we're to follow the dynamic flow of instructions,
904*33318Sdonn 	 * we must see where the branch leads.  A branchtype of 0
905*33318Sdonn 	 * indicates an unconditional branch which we simply take
906*33318Sdonn 	 * as the new instruction address.  For a conditional branch,
907*33318Sdonn 	 * we continue execution up to the current address, single step,
908*33318Sdonn 	 * and keep going.
909*33318Sdonn 	 */
910*33318Sdonn 	if (branchtype == 0) {
911*33318Sdonn 	    instaddr = dest;
912*33318Sdonn 	} else if (branchtype == 01) {		/* bsr */
913*33318Sdonn 	    if (followcalls) {
914*33318Sdonn 		steppast(startingaddr);
915*33318Sdonn 		curfunc = whatblock(pc, true);
916*33318Sdonn 		if (not isbperr()) {
917*33318Sdonn 		    printstatus();
918*33318Sdonn 		    /* NOTREACHED */
919*33318Sdonn 		}
920*33318Sdonn 		bpact();
921*33318Sdonn 		if (nosource(curfunc) and canskip(curfunc) and
922*33318Sdonn 		  nlhdr.nlines != 0) {
923*33318Sdonn 		    stepto(retaddr);
924*33318Sdonn 		    instaddr = pc;
925*33318Sdonn 		    bpact();
926*33318Sdonn 		} else {
927*33318Sdonn 		    callnews(/* iscall = */ true);
928*33318Sdonn 		}
929*33318Sdonn 	    }
930*33318Sdonn 	} else {
931*33318Sdonn 	    steppast(startingaddr);
932*33318Sdonn 	}
933*33318Sdonn     }
934*33318Sdonn }
935*33318Sdonn 
936*33318Sdonn public odbcc(inst, form)
937*33318Sdonn long inst;
938*33318Sdonn String form;
939*33318Sdonn {
940*33318Sdonn     long disp;
941*33318Sdonn     short w;
942*33318Sdonn 
943*33318Sdonn     instread(w);
944*33318Sdonn     if (printing) {
945*33318Sdonn     	printf(form, dbname[(int)((inst>>8)&017)], inst&07);
946*33318Sdonn 	psymoff(w + sizeof(w));
947*33318Sdonn     }
948*33318Sdonn }
949*33318Sdonn 
950*33318Sdonn public oscc(inst, dummy)
951*33318Sdonn long inst;
952*33318Sdonn long dummy;
953*33318Sdonn {
954*33318Sdonn     if (printing) {
955*33318Sdonn 	printf("\ts%s\t", cname[(int)((inst>>8)&017)]);
956*33318Sdonn     }
957*33318Sdonn     printea((inst>>3)&07, inst&07, 1);
958*33318Sdonn }
959*33318Sdonn 
960*33318Sdonn public biti(inst, dummy)
961*33318Sdonn long inst;
962*33318Sdonn long dummy;
963*33318Sdonn {
964*33318Sdonn     short w;
965*33318Sdonn 
966*33318Sdonn     if (printing) {
967*33318Sdonn 	printf("\t%s\t", bit[(int)((inst>>6)&03)]);
968*33318Sdonn     }
969*33318Sdonn     if (inst&0x0100) {
970*33318Sdonn 	if (printing) {
971*33318Sdonn 	    printf("d%D,", inst>>9);
972*33318Sdonn 	}
973*33318Sdonn     } else {
974*33318Sdonn 	instread(w);
975*33318Sdonn 	if (printing) {
976*33318Sdonn 	    printf(IMDF, w);
977*33318Sdonn 	    printf(",");
978*33318Sdonn 	}
979*33318Sdonn     }
980*33318Sdonn     printEA(inst);
981*33318Sdonn }
982*33318Sdonn 
983*33318Sdonn public opmode(inst, opcode)
984*33318Sdonn long inst;
985*33318Sdonn long opcode;
986*33318Sdonn {
987*33318Sdonn     register int opmode;
988*33318Sdonn     register int reg;
989*33318Sdonn     int size;
990*33318Sdonn 
991*33318Sdonn     opmode = (int)((inst>>6) & 07);
992*33318Sdonn     reg = (int)((inst>>9) & 07);
993*33318Sdonn     if (opmode == 0 or opmode == 4) {
994*33318Sdonn 	size = 1;
995*33318Sdonn     } else if (opmode == 1 or opmode == 3 or opmode == 5) {
996*33318Sdonn 	size = 2;
997*33318Sdonn     } else {
998*33318Sdonn 	size = 4;
999*33318Sdonn     }
1000*33318Sdonn     if (printing) {
1001*33318Sdonn 	printf("\t%s%c\t", opcode, suffix(size));
1002*33318Sdonn     }
1003*33318Sdonn     if (opmode >= 4 and opmode <= 6) {
1004*33318Sdonn 	if (printing) {
1005*33318Sdonn 	    printf("d%d,", reg);
1006*33318Sdonn 	}
1007*33318Sdonn 	printea((inst>>3)&07, inst&07, size);
1008*33318Sdonn     } else {
1009*33318Sdonn 	printea((inst>>3)&07, inst&07, size);
1010*33318Sdonn 	if (printing) {
1011*33318Sdonn 	    printf(",%c%d",(opmode<=2) ? 'd' : 'a', reg);
1012*33318Sdonn 	}
1013*33318Sdonn     }
1014*33318Sdonn }
1015*33318Sdonn 
1016*33318Sdonn public shroi(inst, ds)
1017*33318Sdonn long inst;
1018*33318Sdonn String ds;
1019*33318Sdonn {
1020*33318Sdonn     int rx, ry;
1021*33318Sdonn     String opcode;
1022*33318Sdonn 
1023*33318Sdonn     if ((inst & 0xC0) == 0xC0) {
1024*33318Sdonn 	opcode = shro[(int)((inst>>9)&03)];
1025*33318Sdonn 	if (printing) {
1026*33318Sdonn 	    printf("\t%s%s\t", opcode, ds);
1027*33318Sdonn 	}
1028*33318Sdonn 	printEA(inst);
1029*33318Sdonn     } else {
1030*33318Sdonn 	if (printing) {
1031*33318Sdonn 	    opcode = shro[(int)((inst>>3)&03)];
1032*33318Sdonn 	    printf("\t%s%s%c\t", opcode, ds, suffix(mapsize(inst)));
1033*33318Sdonn 	    rx = (int)((inst>>9)&07); ry = (int)(inst&07);
1034*33318Sdonn 	    if ((inst>>5)&01) {
1035*33318Sdonn 		printf("d%d,d%d", rx, ry);
1036*33318Sdonn 	    } else {
1037*33318Sdonn 		printf(IMDF, (rx ? rx : 8));
1038*33318Sdonn 		printf(",d%d", ry);
1039*33318Sdonn 	    }
1040*33318Sdonn 	}
1041*33318Sdonn     }
1042*33318Sdonn }
1043*33318Sdonn 
1044*33318Sdonn public oimmed(inst, opcode)
1045*33318Sdonn long inst;
1046*33318Sdonn register String opcode;
1047*33318Sdonn {
1048*33318Sdonn     register int size;
1049*33318Sdonn     long const;
1050*33318Sdonn     short w;
1051*33318Sdonn 
1052*33318Sdonn     size = mapsize(inst);
1053*33318Sdonn     if (size > 0) {
1054*33318Sdonn 	if (size == 4) {
1055*33318Sdonn 	    instread(const);
1056*33318Sdonn 	} else {
1057*33318Sdonn 	    instread(w);
1058*33318Sdonn 	    const = w;
1059*33318Sdonn 	}
1060*33318Sdonn 	if (printing) {
1061*33318Sdonn 	    printf("\t%s%c\t", opcode, suffix(size));
1062*33318Sdonn 	    printf(IMDF, const);
1063*33318Sdonn 	    printf(",");
1064*33318Sdonn 	}
1065*33318Sdonn 	printEA(inst, size);
1066*33318Sdonn     } else {
1067*33318Sdonn 	if (printing) {
1068*33318Sdonn 	    printf("\tbadop");
1069*33318Sdonn 	}
1070*33318Sdonn     }
1071*33318Sdonn }
1072*33318Sdonn 
1073*33318Sdonn public oreg(inst, opcode)
1074*33318Sdonn long inst;
1075*33318Sdonn register String opcode;
1076*33318Sdonn {
1077*33318Sdonn     if (printing) {
1078*33318Sdonn 	printf(opcode, (inst & 07));
1079*33318Sdonn     }
1080*33318Sdonn }
1081*33318Sdonn 
1082*33318Sdonn public extend(inst, opcode)
1083*33318Sdonn long inst;
1084*33318Sdonn String opcode;
1085*33318Sdonn {
1086*33318Sdonn     register int size;
1087*33318Sdonn     int ry, rx;
1088*33318Sdonn     char c;
1089*33318Sdonn 
1090*33318Sdonn     if (printing) {
1091*33318Sdonn 	size = mapsize(inst);
1092*33318Sdonn 	ry = (inst&07);
1093*33318Sdonn 	rx = ((inst>>9)&07);
1094*33318Sdonn 	c = ((inst & 0x1000) ? suffix(size) : ' ');
1095*33318Sdonn 	printf("\t%s%c\t", opcode, c);
1096*33318Sdonn 	if (opcode[0] == 'e') {
1097*33318Sdonn 	    if (inst & 0x0080) {
1098*33318Sdonn 		printf("d%D,a%D", rx, ry);
1099*33318Sdonn 	    } else if (inst & 0x0008) {
1100*33318Sdonn 		printf("a%D,a%D", rx, ry);
1101*33318Sdonn 	    } else {
1102*33318Sdonn 		printf("d%D,d%D", rx, ry);
1103*33318Sdonn 	    }
1104*33318Sdonn 	} else if ((inst & 0xF000) == 0xB000) {
1105*33318Sdonn 	    printf("a%D@+,a%D@+", ry, rx);
1106*33318Sdonn 	} else if (inst & 0x8) {
1107*33318Sdonn 	    printf("a%D@-,a%D@-", ry, rx);
1108*33318Sdonn 	} else {
1109*33318Sdonn 	    printf("d%D,d%D", ry, rx);
1110*33318Sdonn 	}
1111*33318Sdonn     }
1112*33318Sdonn }
1113*33318Sdonn 
1114*33318Sdonn public olink(inst, dummy)
1115*33318Sdonn long inst;
1116*33318Sdonn long dummy;
1117*33318Sdonn {
1118*33318Sdonn     short w;
1119*33318Sdonn 
1120*33318Sdonn     instread(w);
1121*33318Sdonn     if (printing) {
1122*33318Sdonn 	printf("\tlink\ta%D,", inst&07);
1123*33318Sdonn 	printf(IMDF, w);
1124*33318Sdonn     }
1125*33318Sdonn }
1126*33318Sdonn 
1127*33318Sdonn public otrap(inst, dummy)
1128*33318Sdonn long inst;
1129*33318Sdonn {
1130*33318Sdonn     if (printing) {
1131*33318Sdonn 	printf("\ttrap\t");
1132*33318Sdonn 	printf(IMDF, inst&017);
1133*33318Sdonn     }
1134*33318Sdonn }
1135*33318Sdonn 
1136*33318Sdonn public oneop(inst, opcode)
1137*33318Sdonn long inst;
1138*33318Sdonn register String opcode;
1139*33318Sdonn {
1140*33318Sdonn     if (printing) {
1141*33318Sdonn 	printf("\t%s",opcode);
1142*33318Sdonn     }
1143*33318Sdonn     printEA(inst);
1144*33318Sdonn }
1145*33318Sdonn 
1146*33318Sdonn public jsrop(inst, opcode)
1147*33318Sdonn long inst;
1148*33318Sdonn register String opcode;
1149*33318Sdonn {
1150*33318Sdonn     Address startingaddr;	/* beginning of jsr instruction */
1151*33318Sdonn     Address retaddr; /* can't call return_addr (frame not set up yet) */
1152*33318Sdonn 
1153*33318Sdonn     startingaddr = instaddr - 2;
1154*33318Sdonn     switch ((inst >> 3) & 07) {
1155*33318Sdonn 	case 2:
1156*33318Sdonn 	    retaddr = instaddr;		/* two byte instruction */
1157*33318Sdonn 	    break;
1158*33318Sdonn 	case 5:
1159*33318Sdonn 	case 6:
1160*33318Sdonn 	    retaddr = instaddr + 2;	/* four byte instruction */
1161*33318Sdonn 	    break;
1162*33318Sdonn 	case 7:
1163*33318Sdonn 	default:
1164*33318Sdonn 	    switch (inst & 07) {
1165*33318Sdonn 		case 0:
1166*33318Sdonn 		case 2:
1167*33318Sdonn 		case 3:
1168*33318Sdonn 		    retaddr = instaddr + 2;
1169*33318Sdonn 		    break;
1170*33318Sdonn 		case 1:
1171*33318Sdonn 		default:
1172*33318Sdonn 		    retaddr = instaddr + 4;	/* six byte instruction */
1173*33318Sdonn 		    break;
1174*33318Sdonn 	    }
1175*33318Sdonn 	    break;
1176*33318Sdonn     }
1177*33318Sdonn     if (printing) {
1178*33318Sdonn 	printf("\t%s",opcode);
1179*33318Sdonn     }
1180*33318Sdonn     printEA(inst);
1181*33318Sdonn     if (following and followcalls) {
1182*33318Sdonn 	steppast(startingaddr);
1183*33318Sdonn 	curfunc = whatblock(pc, true);
1184*33318Sdonn 	if (not isbperr()) {
1185*33318Sdonn 	    printstatus();
1186*33318Sdonn 	    /* NOTREACHED */
1187*33318Sdonn 	}
1188*33318Sdonn 	bpact();
1189*33318Sdonn 	if (nosource(curfunc) and canskip(curfunc) and nlhdr.nlines != 0) {
1190*33318Sdonn 	    stepto(retaddr);
1191*33318Sdonn 	    instaddr = pc;
1192*33318Sdonn 	    bpact();
1193*33318Sdonn 	} else {
1194*33318Sdonn 	    callnews(/* iscall = */ true);
1195*33318Sdonn 	}
1196*33318Sdonn     }
1197*33318Sdonn }
1198*33318Sdonn 
1199*33318Sdonn public jmpop(inst, opcode)
1200*33318Sdonn long inst;
1201*33318Sdonn register String opcode;
1202*33318Sdonn {
1203*33318Sdonn     Address startingaddr;	/* beginning of jump instruction */
1204*33318Sdonn 
1205*33318Sdonn     startingaddr = instaddr - 2;
1206*33318Sdonn     if (printing) {
1207*33318Sdonn 	printf("\t%s",opcode);
1208*33318Sdonn     }
1209*33318Sdonn     printEA(inst);
1210*33318Sdonn     if (following) {
1211*33318Sdonn 	steppast(startingaddr);
1212*33318Sdonn     }
1213*33318Sdonn }
1214*33318Sdonn 
1215*33318Sdonn public pregmask(mask)
1216*33318Sdonn register int mask;
1217*33318Sdonn {
1218*33318Sdonn     register int i;
1219*33318Sdonn     register int flag = 0;
1220*33318Sdonn 
1221*33318Sdonn     if (printing) {
1222*33318Sdonn 	printf("#<");
1223*33318Sdonn 	for (i=0; i<16; i++) {
1224*33318Sdonn 	    if (mask&1) {
1225*33318Sdonn 		if (flag) {
1226*33318Sdonn 		    printf(",");
1227*33318Sdonn 		} else {
1228*33318Sdonn 		    ++flag;
1229*33318Sdonn 		}
1230*33318Sdonn 		printf("%c%d",(i<8) ? 'd' : 'a', i&07);
1231*33318Sdonn 	    }
1232*33318Sdonn 	    mask >>= 1;
1233*33318Sdonn 	}
1234*33318Sdonn 	printf(">");
1235*33318Sdonn     }
1236*33318Sdonn }
1237*33318Sdonn 
1238*33318Sdonn public omovem(inst, dummy)
1239*33318Sdonn long inst;
1240*33318Sdonn long dummy;
1241*33318Sdonn {
1242*33318Sdonn     register int i, list, mask;
1243*33318Sdonn     register int reglist;
1244*33318Sdonn     short w;
1245*33318Sdonn 
1246*33318Sdonn     i = 0;
1247*33318Sdonn     list = 0;
1248*33318Sdonn     mask = 0100000;
1249*33318Sdonn     instread(w);
1250*33318Sdonn     reglist = w;
1251*33318Sdonn     if ((inst & 070) == 040) {	/* predecrement */
1252*33318Sdonn 	for (i = 15; i > 0; i -= 2) {
1253*33318Sdonn 	    list |= ((mask & reglist) >> i);
1254*33318Sdonn 	    mask >>= 1;
1255*33318Sdonn 	}
1256*33318Sdonn 	for (i = 1; i < 16; i += 2) {
1257*33318Sdonn 	    list |= ((mask & reglist) << i);
1258*33318Sdonn 	    mask >>= 1;
1259*33318Sdonn 	}
1260*33318Sdonn 	reglist = list;
1261*33318Sdonn     }
1262*33318Sdonn     if (printing) {
1263*33318Sdonn 	printf("\tmovem%c\t",(inst&100)?'l':'w');
1264*33318Sdonn     }
1265*33318Sdonn     if (inst&02000) {
1266*33318Sdonn 	printEA(inst);
1267*33318Sdonn 	if (printing) {
1268*33318Sdonn 	    printf(",");
1269*33318Sdonn 	}
1270*33318Sdonn 	pregmask(reglist);
1271*33318Sdonn     } else {
1272*33318Sdonn 	pregmask(reglist);
1273*33318Sdonn 	if (printing) {
1274*33318Sdonn 	    printf(",");
1275*33318Sdonn 	}
1276*33318Sdonn 	printEA(inst);
1277*33318Sdonn     }
1278*33318Sdonn }
1279*33318Sdonn 
1280*33318Sdonn public ochk(inst, opcode)
1281*33318Sdonn long inst;
1282*33318Sdonn register String opcode;
1283*33318Sdonn {
1284*33318Sdonn     if (printing) {
1285*33318Sdonn 	printf("\t%s\t", opcode);
1286*33318Sdonn     }
1287*33318Sdonn     printEA(inst, sizeof(Byte));
1288*33318Sdonn     if (printing) {
1289*33318Sdonn 	printf(",%c%D", (opcode[0] == 'l') ? 'a' : 'd', (inst>>9)&07);
1290*33318Sdonn     }
1291*33318Sdonn }
1292*33318Sdonn 
1293*33318Sdonn public soneop(inst, opcode)
1294*33318Sdonn long inst;
1295*33318Sdonn register String opcode;
1296*33318Sdonn {
1297*33318Sdonn     register int size;
1298*33318Sdonn 
1299*33318Sdonn     size = mapsize(inst);
1300*33318Sdonn     if (size > 0) {
1301*33318Sdonn 	if (printing) {
1302*33318Sdonn 	    printf("\t%s%c\t", opcode, suffix(size));
1303*33318Sdonn 	}
1304*33318Sdonn 	printEA(inst);
1305*33318Sdonn     } else {
1306*33318Sdonn 	if (printing) {
1307*33318Sdonn 	    printf("\tbadop");
1308*33318Sdonn 	}
1309*33318Sdonn     }
1310*33318Sdonn }
1311*33318Sdonn 
1312*33318Sdonn public oquick(inst, opcode)
1313*33318Sdonn long inst;
1314*33318Sdonn register String opcode;
1315*33318Sdonn {
1316*33318Sdonn     register int size;
1317*33318Sdonn     register int data;
1318*33318Sdonn 
1319*33318Sdonn     size = mapsize(inst);
1320*33318Sdonn     data = (int)((inst>>9) & 07);
1321*33318Sdonn     if (data == 0) {
1322*33318Sdonn 	data = 8;
1323*33318Sdonn     }
1324*33318Sdonn     if (size > 0) {
1325*33318Sdonn 	if (printing) {
1326*33318Sdonn 	    printf("\t%s%c\t", opcode, suffix(size));
1327*33318Sdonn 	    printf(IMDF, data);
1328*33318Sdonn 	    printf(",");
1329*33318Sdonn 	}
1330*33318Sdonn 	printEA(inst);
1331*33318Sdonn     } else {
1332*33318Sdonn 	if (printing) {
1333*33318Sdonn 	    printf("\tbadop");
1334*33318Sdonn 	}
1335*33318Sdonn     }
1336*33318Sdonn }
1337*33318Sdonn 
1338*33318Sdonn public omoveq(inst, dummy)
1339*33318Sdonn long inst;
1340*33318Sdonn long dummy;
1341*33318Sdonn {
1342*33318Sdonn     register int data;
1343*33318Sdonn 
1344*33318Sdonn     if (printing) {
1345*33318Sdonn 	data = (int)(inst & 0377);
1346*33318Sdonn 	if (data > 127) {
1347*33318Sdonn 	    data |= ~0377;
1348*33318Sdonn 	}
1349*33318Sdonn 	printf("\tmoveq\t");
1350*33318Sdonn 	printf(IMDF, data);
1351*33318Sdonn 	printf(",d%D", (inst>>9)&07);
1352*33318Sdonn     }
1353*33318Sdonn }
1354*33318Sdonn 
1355*33318Sdonn public oprint(inst, opcode)
1356*33318Sdonn long inst;
1357*33318Sdonn register String opcode;
1358*33318Sdonn {
1359*33318Sdonn     if (printing) {
1360*33318Sdonn 	printf("\t%s",opcode);
1361*33318Sdonn     }
1362*33318Sdonn }
1363*33318Sdonn 
1364*33318Sdonn public ostop(inst, opcode)
1365*33318Sdonn long inst;
1366*33318Sdonn register String opcode;
1367*33318Sdonn {
1368*33318Sdonn     short w;
1369*33318Sdonn 
1370*33318Sdonn     instread(w);
1371*33318Sdonn     if (printing) {
1372*33318Sdonn 	printf(opcode, w);
1373*33318Sdonn     }
1374*33318Sdonn }
1375*33318Sdonn 
1376*33318Sdonn public orts(inst, opcode)
1377*33318Sdonn long inst;
1378*33318Sdonn register String opcode;
1379*33318Sdonn {
1380*33318Sdonn     Address addr;
1381*33318Sdonn 
1382*33318Sdonn     if (following) {
1383*33318Sdonn 	callnews(/* iscall = */ false);
1384*33318Sdonn     	if (inst_tracing) {
1385*33318Sdonn 	    addr = currtnaddr();
1386*33318Sdonn     	} else {
1387*33318Sdonn 	    addr = return_addr();
1388*33318Sdonn 	    if (addr == 0) {
1389*33318Sdonn 		stepto(instaddr - 2);
1390*33318Sdonn 		addr = currtnaddr();
1391*33318Sdonn 	    }
1392*33318Sdonn 	}
1393*33318Sdonn 	stepto(addr);
1394*33318Sdonn 	instaddr = pc;
1395*33318Sdonn     }
1396*33318Sdonn     if (printing) {
1397*33318Sdonn 	printf("\t%s",opcode);
1398*33318Sdonn     }
1399*33318Sdonn }
1400*33318Sdonn 
1401*33318Sdonn /*
1402*33318Sdonn  * Not used by C compiler; does an rts but before doing so, pops
1403*33318Sdonn  * arg bytes from the stack.
1404*33318Sdonn  */
1405*33318Sdonn 
1406*33318Sdonn public ortspop(inst, opcode)
1407*33318Sdonn long inst;
1408*33318Sdonn register String opcode;
1409*33318Sdonn {
1410*33318Sdonn     Address addr;
1411*33318Sdonn     short w;
1412*33318Sdonn 
1413*33318Sdonn     instread(w);
1414*33318Sdonn     if (following) {
1415*33318Sdonn 	callnews(/* iscall = */ false);
1416*33318Sdonn     	if (inst_tracing) {
1417*33318Sdonn 	    addr = currtnaddr();
1418*33318Sdonn     	} else {
1419*33318Sdonn 	    addr = return_addr();
1420*33318Sdonn 	}
1421*33318Sdonn 	stepto(addr);
1422*33318Sdonn 	instaddr = pc;
1423*33318Sdonn     }
1424*33318Sdonn     if (printing) {
1425*33318Sdonn 	printf(opcode, w);
1426*33318Sdonn     }
1427*33318Sdonn }
1428*33318Sdonn 
1429*33318Sdonn public omovs(inst, opcode)
1430*33318Sdonn long inst;
1431*33318Sdonn String opcode;
1432*33318Sdonn {
1433*33318Sdonn     register int size;
1434*33318Sdonn     register unsigned int controlword;
1435*33318Sdonn     short w;
1436*33318Sdonn 
1437*33318Sdonn     size = mapsize(inst);
1438*33318Sdonn     instread(w);
1439*33318Sdonn     controlword = w >> 11;
1440*33318Sdonn     if (printing) {
1441*33318Sdonn 	printf("\t%s%c\t", opcode, suffix(size));
1442*33318Sdonn     }
1443*33318Sdonn     if (controlword & 1){
1444*33318Sdonn 	controlword >>= 1;
1445*33318Sdonn 	if (printing) {
1446*33318Sdonn 	    printf((controlword&0x8) ? "a%D," : "d%D,", controlword&7 );
1447*33318Sdonn 	}
1448*33318Sdonn 	printEA(inst&0xff, size);
1449*33318Sdonn     } else {
1450*33318Sdonn 	controlword >>= 1;
1451*33318Sdonn 	printEA(inst&0xff, size);
1452*33318Sdonn 	if (printing) {
1453*33318Sdonn 	    printf((controlword&0x8) ? ",a%D" : ",d%D", controlword&7);
1454*33318Sdonn 	}
1455*33318Sdonn     }
1456*33318Sdonn }
1457*33318Sdonn 
1458*33318Sdonn public omovc(inst, opcode)
1459*33318Sdonn long inst;
1460*33318Sdonn String opcode;
1461*33318Sdonn {
1462*33318Sdonn     register unsigned int controlword;
1463*33318Sdonn     String creg;
1464*33318Sdonn     short w;
1465*33318Sdonn 
1466*33318Sdonn     instread(w);
1467*33318Sdonn     if (printing) {
1468*33318Sdonn 	controlword = w;
1469*33318Sdonn 	switch (controlword & 0xfff) {
1470*33318Sdonn 	    case 0:
1471*33318Sdonn 		creg = "sfc";
1472*33318Sdonn 		break;
1473*33318Sdonn 
1474*33318Sdonn 	    case 1:
1475*33318Sdonn 		creg = "dfc";
1476*33318Sdonn 		break;
1477*33318Sdonn 
1478*33318Sdonn 	    case 0x800:
1479*33318Sdonn 		creg = "usp";
1480*33318Sdonn 		break;
1481*33318Sdonn 
1482*33318Sdonn 	    case 0x801:
1483*33318Sdonn 		creg = "vbr";
1484*33318Sdonn 		break;
1485*33318Sdonn 
1486*33318Sdonn 	    default:
1487*33318Sdonn 		creg = "???";
1488*33318Sdonn 		break;
1489*33318Sdonn 	}
1490*33318Sdonn 	controlword >>= 12;
1491*33318Sdonn 	if (inst & 1){
1492*33318Sdonn 	    printf((controlword&0x8) ? "%sa%D,%s" : "%sd%D,%s",
1493*33318Sdonn 		opcode, controlword&7, creg );
1494*33318Sdonn 	} else {
1495*33318Sdonn 	    printf((controlword&0x8) ? "%s%s,a%D" : "%s%s,d%D",
1496*33318Sdonn 		opcode, creg, controlword&7 );
1497*33318Sdonn 	}
1498*33318Sdonn     }
1499*33318Sdonn }
1500*33318Sdonn 
1501*33318Sdonn /*
1502*33318Sdonn  * Compute the next address that will be executed from the given one.
1503*33318Sdonn  * If "isnext" is true then consider a procedure call as straight line code.
1504*33318Sdonn  *
1505*33318Sdonn  * Unconditional branches we just follow, for conditional branches
1506*33318Sdonn  * we continue execution to the current location and then single step
1507*33318Sdonn  * the machine.
1508*33318Sdonn  */
1509*33318Sdonn 
1510*33318Sdonn public Address nextaddr(startaddr, isnext)
1511*33318Sdonn Address startaddr;
1512*33318Sdonn Boolean isnext;
1513*33318Sdonn {
1514*33318Sdonn     Optab *o;
1515*33318Sdonn     short inst;
1516*33318Sdonn 
1517*33318Sdonn     instaddr = usignal(process);
1518*33318Sdonn     if (instaddr == 0 or instaddr == 1) {
1519*33318Sdonn 	following = true;
1520*33318Sdonn 	followcalls = (Boolean) (not isnext);
1521*33318Sdonn 	printing = false;
1522*33318Sdonn 	iread(&inst, startaddr, sizeof(inst));
1523*33318Sdonn 	instaddr = startaddr + sizeof(inst);
1524*33318Sdonn 	o = decode(inst, startaddr);
1525*33318Sdonn 	if (o->mask == 0) {
1526*33318Sdonn 	    fprintf(stderr,
1527*33318Sdonn 		"[internal error: undecodable op at 0x%x]\n", startaddr);
1528*33318Sdonn 	    fflush(stderr);
1529*33318Sdonn 	} else {
1530*33318Sdonn 	    (*o->opfun)(inst, o->farg);
1531*33318Sdonn 	}
1532*33318Sdonn 	following = false;
1533*33318Sdonn     }
1534*33318Sdonn     return instaddr;
1535*33318Sdonn }
1536*33318Sdonn 
1537*33318Sdonn /*
1538*33318Sdonn  * Step to the given address and then execute one instruction past it.
1539*33318Sdonn  * Set instaddr to the new instruction address.
1540*33318Sdonn  */
1541*33318Sdonn 
1542*33318Sdonn private steppast(addr)
1543*33318Sdonn Address addr;
1544*33318Sdonn {
1545*33318Sdonn     stepto(addr);
1546*33318Sdonn     pstep(process, DEFSIG);
1547*33318Sdonn     pc = reg(PROGCTR);
1548*33318Sdonn     instaddr = pc;
1549*33318Sdonn }
1550*33318Sdonn 
1551*33318Sdonn /*
1552*33318Sdonn  * Enter a procedure by creating and executing a call instruction.
1553*33318Sdonn  */
1554*33318Sdonn 
1555*33318Sdonn #define CALLSIZE 6	/* size of call instruction */
1556*33318Sdonn 
1557*33318Sdonn public beginproc(p)
1558*33318Sdonn Symbol p;
1559*33318Sdonn {
1560*33318Sdonn     char save[CALLSIZE];
1561*33318Sdonn     struct {
1562*33318Sdonn 	short op;
1563*33318Sdonn 	char addr[sizeof(long)];	/* unaligned long */
1564*33318Sdonn     } call;
1565*33318Sdonn     long dest;
1566*33318Sdonn 
1567*33318Sdonn     pc = CODESTART + 6;
1568*33318Sdonn     iread(save, pc, sizeof(save));
1569*33318Sdonn     call.op = 0x4eb9;			/* jsr */
1570*33318Sdonn     dest = codeloc(p) - FUNCOFFSET;
1571*33318Sdonn     mov(&dest, call.addr, sizeof(call.addr));
1572*33318Sdonn     iwrite(&call, pc, sizeof(call));
1573*33318Sdonn     setreg(PROGCTR, pc);
1574*33318Sdonn     pstep(process, DEFSIG);
1575*33318Sdonn     iwrite(save, pc, sizeof(save));
1576*33318Sdonn     pc = reg(PROGCTR);
1577*33318Sdonn     if (not isbperr()) {
1578*33318Sdonn 	printstatus();
1579*33318Sdonn     }
1580*33318Sdonn     /*
1581*33318Sdonn      * Execute link instruction so the return addr is visible.
1582*33318Sdonn      */
1583*33318Sdonn     pstep(process, DEFSIG);
1584*33318Sdonn     pc = reg(PROGCTR);
1585*33318Sdonn     if (not isbperr()) {
1586*33318Sdonn 	printstatus();
1587*33318Sdonn     }
1588*33318Sdonn }
1589*33318Sdonn 
1590*33318Sdonn /*
1591*33318Sdonn  * Special variables for debugging the kernel.
1592*33318Sdonn  */
1593*33318Sdonn 
1594*33318Sdonn public integer masterpcbb;
1595*33318Sdonn public integer slr;
1596*33318Sdonn public struct pte *sbr;
1597*33318Sdonn private struct pcb pcb;
1598*33318Sdonn 
1599*33318Sdonn public getpcb ()
1600*33318Sdonn {
1601*33318Sdonn     integer i;
1602*33318Sdonn 
1603*33318Sdonn     fseek(corefile, masterpcbb & ~0x80000000, 0);
1604*33318Sdonn     get(corefile, pcb);
1605*33318Sdonn     pcb.pcb_p0lr &= ~AST_CLR;
1606*33318Sdonn     printf("p0br %lx p0lr %lx p1br %lx p1lr %lx\n",
1607*33318Sdonn 	pcb.pcb_p0br, pcb.pcb_p0lr, pcb.pcb_p1br, pcb.pcb_p1lr
1608*33318Sdonn     );
1609*33318Sdonn #   ifdef sun
1610*33318Sdonn     for (i = 0; i < 14; i++) {
1611*33318Sdonn 	setreg(i, pcb.pcb_regs.val[i]);
1612*33318Sdonn     }
1613*33318Sdonn #   else /* IRIS */
1614*33318Sdonn     for (i = 0; i < 14; i++) {
1615*33318Sdonn 	setreg(i, pcb.pcb_regs[i]);
1616*33318Sdonn     }
1617*33318Sdonn #   endif
1618*33318Sdonn }
1619*33318Sdonn 
1620*33318Sdonn public copyregs (savreg, reg)
1621*33318Sdonn Word savreg[], reg[];
1622*33318Sdonn {
1623*33318Sdonn     reg[0] = savreg[R0];
1624*33318Sdonn     reg[1] = savreg[R1];
1625*33318Sdonn     reg[2] = savreg[R2];
1626*33318Sdonn     reg[3] = savreg[R3];
1627*33318Sdonn     reg[4] = savreg[R4];
1628*33318Sdonn     reg[5] = savreg[R5];
1629*33318Sdonn     reg[6] = savreg[R6];
1630*33318Sdonn     reg[7] = savreg[R7];
1631*33318Sdonn     reg[8] = savreg[AR0];
1632*33318Sdonn     reg[9] = savreg[AR1];
1633*33318Sdonn     reg[10] = savreg[AR2];
1634*33318Sdonn     reg[11] = savreg[AR3];
1635*33318Sdonn     reg[12] = savreg[AR4];
1636*33318Sdonn     reg[13] = savreg[AR5];
1637*33318Sdonn     reg[14] = savreg[AR6];
1638*33318Sdonn     reg[15] = savreg[AR7];
1639*33318Sdonn     reg[PROGCTR] = savreg[PC];
1640*33318Sdonn }
1641*33318Sdonn 
1642*33318Sdonn /*
1643*33318Sdonn  * Map a virtual address to a physical address.
1644*33318Sdonn  * XXX THIS CAN'T BE RIGHT... XXX
1645*33318Sdonn  */
1646*33318Sdonn 
1647*33318Sdonn public Address vmap (addr)
1648*33318Sdonn Address addr;
1649*33318Sdonn {
1650*33318Sdonn     Address r;
1651*33318Sdonn     integer v, n;
1652*33318Sdonn     struct pte pte;
1653*33318Sdonn 
1654*33318Sdonn     r = addr & ~0xc0000000;
1655*33318Sdonn     v = btop(r);
1656*33318Sdonn     switch (addr&0xc0000000) {
1657*33318Sdonn 	case 0xc0000000:
1658*33318Sdonn 	case 0x80000000:
1659*33318Sdonn 	    /*
1660*33318Sdonn 	     * In system space, so get system pte.
1661*33318Sdonn 	     * If it is valid or reclaimable then the physical address
1662*33318Sdonn 	     * is the combination of its page number and the page offset
1663*33318Sdonn 	     * of the original address.
1664*33318Sdonn 	     */
1665*33318Sdonn 	    if (v >= slr) {
1666*33318Sdonn 		error("address %x out of segment", addr);
1667*33318Sdonn 	    }
1668*33318Sdonn 	    r = ((long) (sbr + v)) & ~0x80000000;
1669*33318Sdonn 	    goto simple;
1670*33318Sdonn 
1671*33318Sdonn 	case 0x40000000:
1672*33318Sdonn 	    /*
1673*33318Sdonn 	     * In p1 space, must not be in shadow region.
1674*33318Sdonn 	     */
1675*33318Sdonn 	    if (v < pcb.pcb_p1lr) {
1676*33318Sdonn 		error("address %x out of segment", addr);
1677*33318Sdonn 	    }
1678*33318Sdonn 	    r = (Address) (pcb.pcb_p1br + v);
1679*33318Sdonn 	    break;
1680*33318Sdonn 
1681*33318Sdonn 	case 0x00000000:
1682*33318Sdonn 	    /*
1683*33318Sdonn 	     * In p0 space, must not be off end of region.
1684*33318Sdonn 	     */
1685*33318Sdonn 	    if (v >= pcb.pcb_p0lr) {
1686*33318Sdonn 		error("address %x out of segment", addr);
1687*33318Sdonn 	    }
1688*33318Sdonn 	    r = (Address) (pcb.pcb_p0br + v);
1689*33318Sdonn 	    break;
1690*33318Sdonn 
1691*33318Sdonn 	default:
1692*33318Sdonn 	    /* do nothing */
1693*33318Sdonn 	    break;
1694*33318Sdonn     }
1695*33318Sdonn     /*
1696*33318Sdonn      * For p0/p1 address, user-level page table should be in
1697*33318Sdonn      * kernel virtual memory.  Do second-level indirect by recursing.
1698*33318Sdonn      */
1699*33318Sdonn     if ((r & 0x80000000) == 0) {
1700*33318Sdonn 	error("bad p0br or p1br in pcb");
1701*33318Sdonn     }
1702*33318Sdonn     r = vmap(r);
1703*33318Sdonn simple:
1704*33318Sdonn     /*
1705*33318Sdonn      * "r" is now the address of the pte of the page
1706*33318Sdonn      * we are interested in; get the pte and paste up the physical address.
1707*33318Sdonn      */
1708*33318Sdonn     fseek(corefile, r, 0);
1709*33318Sdonn     n = fread(&pte, sizeof(pte), 1, corefile);
1710*33318Sdonn     if (n != 1) {
1711*33318Sdonn 	error("page table botch (fread at %x returns %d)", r, n);
1712*33318Sdonn     }
1713*33318Sdonn     if (pte.pg_v == 0 and (pte.pg_fod != 0 or pte.pg_pfnum == 0)) {
1714*33318Sdonn 	error("page no valid or reclamable");
1715*33318Sdonn     }
1716*33318Sdonn     return (addr&PGOFSET) + ((Address) ptob(pte.pg_pfnum));
1717*33318Sdonn }
1718*33318Sdonn 
1719*33318Sdonn /*
1720*33318Sdonn  * Extract a bit field from an integer.
1721*33318Sdonn  */
1722*33318Sdonn 
1723*33318Sdonn public integer extractField (s)
1724*33318Sdonn Symbol s;
1725*33318Sdonn {
1726*33318Sdonn     integer nbytes, nbits, n, r, off, len;
1727*33318Sdonn 
1728*33318Sdonn     off = s->symvalue.field.offset;
1729*33318Sdonn     len = s->symvalue.field.length;
1730*33318Sdonn     nbytes = size(s);
1731*33318Sdonn     n = 0;
1732*33318Sdonn     if (nbytes > sizeof(n)) {
1733*33318Sdonn 	printf("[bad size in extractField -- word assumed]\n");
1734*33318Sdonn 	nbytes = sizeof(n);
1735*33318Sdonn     }
1736*33318Sdonn     popn(nbytes, ((char *) &n) + (sizeof(Word) - nbytes));
1737*33318Sdonn     nbits = nbytes * BITSPERBYTE;
1738*33318Sdonn     r = n >> (nbits - ((off mod nbits) + len));
1739*33318Sdonn     r &= ((1 << len) - 1);
1740*33318Sdonn     return r;
1741*33318Sdonn }
1742*33318Sdonn 
1743*33318Sdonn /*
1744*33318Sdonn  * Change the length of a value in memory according to a given difference
1745*33318Sdonn  * in the lengths of its new and old types.
1746*33318Sdonn  */
1747*33318Sdonn 
1748*33318Sdonn public loophole (oldlen, newlen)
1749*33318Sdonn integer oldlen, newlen;
1750*33318Sdonn {
1751*33318Sdonn     integer i, n;
1752*33318Sdonn     Stack *oldsp;
1753*33318Sdonn 
1754*33318Sdonn     n = newlen - oldlen;
1755*33318Sdonn     oldsp = sp - oldlen;
1756*33318Sdonn     if (n > 0) {
1757*33318Sdonn 	for (i = oldlen - 1; i >= 0; i--) {
1758*33318Sdonn 	    oldsp[n + i] = oldsp[i];
1759*33318Sdonn 	}
1760*33318Sdonn 	for (i = 0; i < n; i++) {
1761*33318Sdonn 	    oldsp[i] = '\0';
1762*33318Sdonn 	}
1763*33318Sdonn     } else {
1764*33318Sdonn 	for (i = 0; i < newlen; i++) {
1765*33318Sdonn 	    oldsp[i] = oldsp[i - n];
1766*33318Sdonn 	}
1767*33318Sdonn     }
1768*33318Sdonn     sp += n;
1769*33318Sdonn }
1770