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