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