|
|
1.1 root 1: /*
2: * Copyright (c) 1985 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[] = "@(#)tahoe.c 5.5 (Berkeley) 1/12/88";
9: #endif not lint
10:
11: /*
12: * Target machine dependent stuff.
13: */
14:
15: #include "defs.h"
16: #include "machine.h"
17: #include "process.h"
18: #include "runtime.h"
19: #include "events.h"
20: #include "main.h"
21: #include "symbols.h"
22: #include "source.h"
23: #include "mappings.h"
24: #include "object.h"
25: #include "keywords.h"
26: #include "ops.h"
27: #include "eval.h"
28: #include <signal.h>
29:
30: #ifndef public
31: typedef unsigned int Address;
32: typedef unsigned char Byte;
33: typedef unsigned int Word;
34:
35: #define NREG 16
36:
37: #define FRP 13
38: #define STKP 14
39: #define PROGCTR 15
40:
41: #define CODESTART 0
42: #define FUNCOFFSET 2
43:
44: #define BITSPERBYTE 8
45: #define BITSPERWORD (BITSPERBYTE * sizeof(Word))
46:
47: /*
48: * This magic macro enables us to look at the process' registers
49: * in its user structure.
50: */
51:
52: #define regloc(reg) (ctob(UPAGES) + (sizeof(Word) * (reg)))
53:
54: #define nargspassed(frame) (((argn(-1, frame)&0xffff)-4)/4)
55:
56: #define SYSBASE 0xc0000000 /* base of system address space */
57: #define physaddr(a) ((a) &~ 0xc0000000)
58:
59: #include "source.h"
60: #include "symbols.h"
61: #include <sys/param.h>
62: #include <sys/dir.h>
63: #include <machine/psl.h>
64: #include <sys/user.h>
65: #undef DELETE /* XXX */
66: #include <sys/vm.h>
67: #include <machine/reg.h>
68: #include <machine/pte.h>
69:
70: Address pc;
71: Address prtaddr;
72:
73: #endif
74:
75: /*
76: * Indices into u. for use in collecting registers values.
77: */
78: public int rloc[] =
79: { R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, FP, SP, PC };
80:
81: private Address printop();
82:
83: Optab *ioptab[256]; /* index by opcode to optab */
84: /*
85: * Initialize the opcode lookup table.
86: */
87: public optab_init()
88: {
89: register Optab *p;
90:
91: for (p = optab; p->iname; p++)
92: ioptab[p->val & 0xff] = p;
93: }
94:
95: /*
96: * Decode and print the instructions within the given address range.
97: */
98: public printinst(lowaddr, highaddr)
99: Address lowaddr, highaddr;
100: {
101: register Address addr;
102:
103: for (addr = lowaddr; addr <= highaddr; )
104: addr = printop(addr);
105: prtaddr = addr;
106: }
107:
108: /*
109: * Another approach: print n instructions starting at the given address.
110: */
111: public printninst(count, addr)
112: int count;
113: Address addr;
114: {
115: register Integer i;
116: register Address newaddr;
117:
118: if (count <= 0)
119: error("non-positive repetition count");
120: for (newaddr = addr, i = 0; i < count; i++)
121: newaddr = printop(newaddr);
122: prtaddr = newaddr;
123: }
124:
125: /*
126: * Hacked version of adb's instruction decoder.
127: */
128: private Address printop(addr)
129: Address addr;
130: {
131: register Optab *op;
132: Opcode ins;
133: unsigned char mode;
134: int argtype, amode, argno, argval, r;
135: String reg;
136: Boolean indexf;
137: short offset;
138:
139: argval = 0;
140: indexf = false;
141: printf("%08x ", addr);
142: iread(&ins, addr, sizeof(ins));
143: addr += 1;
144: op = ioptab[ins];
145: printf("%s", op->iname);
146: for (argno = 0; argno < op->numargs; argno++) {
147: if (indexf == true)
148: indexf = false;
149: else
150: printf(argno == 0 ? "\t" : ",");
151: argtype = op->argtype[argno];
152: if (is_branch_disp(argtype))
153: mode = 0xAF + (typelen(argtype) << 5);
154: else
155: iread(&mode, addr, sizeof(mode)), addr += 1;
156: reg = regname[regnm(mode)];
157: amode = addrmode(mode);
158: switch (amode) {
159:
160: case LITSHORT: case LITUPTO31:
161: case LITUPTO47: case LITUPTO63:
162: if (ins == O_KCALL && mode >= 0 && mode < SYSSIZE &&
163: systab[mode])
164: printf("$%s", systab[mode]);
165: else
166: printf("$%x", mode);
167: argval = mode;
168: break;
169:
170: case INDEX:
171: printf("[%s]", reg);
172: indexf = true;
173: argno--;
174: break;
175:
176: case REG:
177: printf("%s", reg);
178: break;
179:
180: case REGDEF:
181: printf("(%s)", reg);
182: break;
183:
184: case AUTODEC:
185: printf("-(%s)", reg);
186: break;
187:
188: case AUTOINC:
189: r = mode & 0xf;
190: if (r == 0xf || r == 8 || r == 9) {
191: int size = (mode&03) + 1;
192:
193: /* immediate mode */
194: printf("$");
195: argval = printdisp(addr, size,
196: regname[PROGCTR], amode);
197: addr += size;
198: } else
199: printf("(%s)+", reg);
200: break;
201:
202: case AUTOINCDEF:
203: if ((mode&0xf) == 0xf) {
204: printf("*$");
205: argval = printdisp(addr, 4, reg, amode);
206: addr += 4;
207: } else
208: printf("*(%s)+", reg);
209: break;
210:
211: case BYTEDISP:
212: argval = printdisp(addr, 1, reg, amode);
213: addr += 1;
214: break;
215:
216: case BYTEDISPDEF:
217: printf("*");
218: argval = printdisp(addr, 1, reg, amode);
219: addr += 1;
220: break;
221:
222: case WORDDISP:
223: argval = printdisp(addr, 2, reg, amode);
224: addr += 2;
225: break;
226:
227: case WORDDISPDEF:
228: printf("*");
229: argval = printdisp(addr, 2, reg, amode);
230: addr += 2;
231: break;
232:
233: case LONGDISP:
234: argval = printdisp(addr, 4, reg, amode);
235: addr += 4;
236: break;
237:
238: case LONGDISPDEF:
239: printf("*");
240: argval = printdisp(addr, 4, reg, amode);
241: addr += 4;
242: break;
243: }
244: }
245: if (ins == O_CASEL)
246: for (argno = 0; argno <= argval; argno++) {
247: iread(&offset, addr, sizeof(offset));
248: printf("\n\t\t%d", offset);
249: addr += 2;
250: }
251: printf("\n");
252: return (addr);
253: }
254:
255: /*
256: * Print the displacement of an instruction that uses displacement
257: * addressing.
258: */
259: private int printdisp(addr, nbytes, reg, mode)
260: Address addr;
261: int nbytes;
262: char *reg;
263: int mode;
264: {
265: char byte;
266: short hword;
267: int argval;
268: Symbol f;
269:
270: switch (nbytes) {
271:
272: case 1:
273: iread(&byte, addr, sizeof(byte));
274: argval = byte;
275: break;
276:
277: case 2:
278: iread(&hword, addr, sizeof(hword));
279: argval = hword;
280: break;
281:
282: case 4:
283: iread(&argval, addr, sizeof(argval));
284: break;
285: }
286: if (reg == regname[PROGCTR] && mode >= BYTEDISP)
287: argval += addr + nbytes;
288: if (reg == regname[PROGCTR]) {
289: f = whatblock((Address) argval + 2);
290: if (codeloc(f) == argval + 2)
291: printf("%s", symname(f));
292: else
293: printf("%x", argval);
294: } else {
295: if (varIsSet("$hexoffsets")) {
296: if (argval < 0)
297: printf("-%x(%s)", -(argval), reg);
298: else
299: printf("%x(%s)", argval, reg);
300: } else
301: printf("%d(%s)", argval, reg);
302: }
303: return (argval);
304: }
305:
306: /*
307: * Print the contents of the addresses within the given range
308: * according to the given format.
309: */
310: typedef struct {
311: String name;
312: String printfstring;
313: int length;
314: } Format;
315:
316: private Format fmt[] = {
317: { "d", " %d", sizeof(short) },
318: { "D", " %ld", sizeof(long) },
319: { "o", " %o", sizeof(short) },
320: { "O", " %lo", sizeof(long) },
321: { "x", " %04x", sizeof(short) },
322: { "X", " %08x", sizeof(long) },
323: { "b", " \\%o", sizeof(char) },
324: { "c", " '%c'", sizeof(char) },
325: { "s", "%c", sizeof(char) },
326: { "f", " %f", sizeof(float) },
327: { "g", " %g", sizeof(double) },
328: { nil, nil, 0 }
329: };
330:
331: private Format *findformat(s)
332: String s;
333: {
334: register Format *f;
335:
336: for (f = &fmt[0]; f->name != nil && !streq(f->name, s); f++)
337: ;
338: if (f->name == nil)
339: error("bad print format \"%s\"", s);
340: return (f);
341: }
342:
343: public Address printdata(lowaddr, highaddr, format)
344: Address lowaddr;
345: Address highaddr;
346: String format;
347: {
348: register int n;
349: register Address addr;
350: register Format *f;
351: int value;
352:
353: if (lowaddr > highaddr)
354: error("first address larger than second");
355: f = findformat(format);
356: n = 0;
357: value = 0;
358: for (addr = lowaddr; addr <= highaddr; addr += f->length) {
359: if (n == 0)
360: printf("%08x: ", addr);
361: dread(&value, addr, f->length);
362: printf(f->printfstring, value);
363: ++n;
364: if (n >= (16 div f->length)) {
365: putchar('\n');
366: n = 0;
367: }
368: }
369: if (n != 0)
370: putchar('\n');
371: prtaddr = addr;
372: return (addr);
373: }
374:
375: /*
376: * The other approach is to print n items starting with a given address.
377: */
378:
379: public printndata(count, startaddr, format)
380: int count;
381: Address startaddr;
382: String format;
383: {
384: register int i, n;
385: register Address addr;
386: register Format *f;
387: register Boolean isstring;
388: char c;
389: union {
390: char charv;
391: short shortv;
392: int intv;
393: float floatv;
394: double doublev;
395: } value;
396:
397: if (count <= 0)
398: error("non-positive repetition count");
399: f = findformat(format);
400: isstring = (Boolean) streq(f->name, "s");
401: n = 0;
402: addr = startaddr;
403: value.intv = 0;
404: for (i = 0; i < count; i++) {
405: if (n == 0)
406: printf("%08x: ", addr);
407: if (isstring) {
408: putchar('"');
409: dread(&c, addr, sizeof(char));
410: while (c != '\0') {
411: printchar(c);
412: ++addr;
413: dread(&c, addr, sizeof(char));
414: }
415: putchar('"');
416: putchar('\n');
417: n = 0;
418: addr += sizeof(String);
419: continue;
420: }
421: dread(&value, addr, f->length);
422: printf(f->printfstring, value);
423: ++n;
424: if (n >= (16 div f->length)) {
425: putchar('\n');
426: n = 0;
427: }
428: addr += f->length;
429: }
430: if (n != 0)
431: putchar('\n');
432: prtaddr = addr;
433: }
434:
435: /*
436: * Print out a value according to the given format.
437: */
438: public printvalue(v, format)
439: long v;
440: String format;
441: {
442: Format *f;
443: char *p, *q;
444:
445: f = findformat(format);
446: if (streq(f->name, "s")) {
447: putchar('"');
448: for (p = (char *) &v, q = p + sizeof(v); p < q; ++p)
449: printchar(*p);
450: putchar('"');
451: } else
452: printf(f->printfstring, v);
453: putchar('\n');
454: }
455:
456: /*
457: * Print out an execution time error.
458: * Assumes the source position of the error has been calculated.
459: *
460: * Have to check if the -r option was specified; if so then
461: * the object file information hasn't been read in yet.
462: */
463: public printerror()
464: {
465: extern Integer sys_nsig;
466: extern String sys_siglist[];
467: integer err;
468:
469: if (isfinished(process)) {
470: err = exitcode(process);
471: if (err) {
472: printf("\"%s\" terminated abnormally (exit code %d)\n",
473: objname, err);
474: erecover();
475: } else
476: printf("\"%s\" terminated normally\n", objname);
477: }
478: if (runfirst) {
479: fprintf(stderr, "Entering debugger ...\n");
480: init();
481: }
482: err = errnum(process);
483: putchar('\n');
484: printsig(err);
485: putchar(' ');
486: printloc();
487: putchar('\n');
488: if (curline > 0)
489: printlines(curline, curline);
490: else
491: printinst(pc, pc);
492: erecover();
493: }
494:
495: /*
496: * Print out a signal.
497: */
498: private String illinames[] = {
499: "reserved addressing fault",
500: "privileged instruction fault",
501: "reserved operand fault"
502: };
503: #define NILLINAMES (sizeof (illinames) / sizeof (illinames[0]))
504:
505: private String fpenames[] = {
506: nil,
507: "integer overflow trap",
508: "integer divide by zero trap",
509: "floating point divide by zero trap",
510: "floating point overflow trap",
511: "floating point underflow trap",
512: };
513: #define NFPENAMES (sizeof (fpenames) / sizeof (fpenames[0]))
514:
515: public printsig(signo)
516: integer signo;
517: {
518: integer code;
519:
520: if (signo < 0 or signo > sys_nsig)
521: printf("[signal %d]", signo);
522: else
523: printf("%s", sys_siglist[signo]);
524: code = errcode(process);
525: if (signo == SIGILL)
526: if (code >= 0 && code < NILLINAMES)
527: printf(" (%s)", illinames[code]);
528: if (signo == SIGFPE)
529: if (code > 0 and code < NFPENAMES)
530: printf(" (%s)", fpenames[code]);
531: }
532:
533: /*
534: * Note the termination of the program. We do this so as to avoid
535: * having the process exit, which would make the values of variables
536: * inaccessible. We do want to flush all output buffers here,
537: * otherwise it'll never get done.
538: */
539: public endprogram()
540: {
541: Integer exitcode;
542:
543: stepto(nextaddr(pc, true));
544: printnews();
545: exitcode = argn(1, nil);
546: if (exitcode != 0)
547: printf("\nexecution completed (exit code %d)\n", exitcode);
548: else
549: printf("\nexecution completed\n");
550: getsrcpos();
551: erecover();
552: }
553:
554: private Address getcall();
555: /*
556: * Single step the machine a source line (or instruction if "inst_tracing"
557: * is true). If "isnext" is true, skip over procedure calls.
558: */
559: public dostep(isnext)
560: Boolean isnext;
561: {
562: register Address addr;
563: register Lineno line;
564: String filename;
565: Address startaddr;
566:
567: startaddr = pc;
568: addr = nextaddr(pc, isnext);
569: if (!inst_tracing && nlhdr.nlines != 0) {
570: line = linelookup(addr);
571: for (; line == 0; line = linelookup(addr))
572: addr = nextaddr(addr, isnext);
573: curline = line;
574: } else
575: curline = 0;
576: stepto(addr);
577: filename = srcfilename(addr);
578: setsource(filename);
579: }
580:
581: private Address findnextaddr();
582: /*
583: * Compute the next address that will be executed from the given one.
584: * If "isnext" is true then consider a procedure call as straight line code.
585: *
586: * We must unfortunately do much of the same work that is necessary
587: * to print instructions. In addition we have to deal with branches.
588: * Unconditional branches we just follow, for conditional branches
589: * we continue execution to the current location and then single step
590: * the machine. We assume that the last argument in an instruction
591: * that branches is the branch address (or relative offset).
592: */
593: public Address nextaddr(startaddr, isnext)
594: Address startaddr;
595: boolean isnext;
596: {
597: Address addr;
598:
599: addr = usignal(process);
600: if (addr == 0 or addr == 1)
601: addr = findnextaddr(startaddr, isnext);
602: return (addr);
603: }
604:
605: /*
606: * Determine if it's ok to skip function f entered by instruction ins.
607: * If so, we're going to compute the return address and step to it.
608: */
609: private boolean skipfunc(ins, f)
610: Opcode ins;
611: Symbol f;
612: {
613:
614: return ((boolean) (!inst_tracing && nlhdr.nlines != 0 &&
615: nosource(curfunc) && canskip(curfunc)));
616: }
617:
618: private Address findnextaddr(startaddr, isnext)
619: Address startaddr;
620: Boolean isnext;
621: {
622: register Address addr;
623: Optab *op;
624: Opcode ins;
625: unsigned char mode;
626: int argtype, amode, argno, argval, nib;
627: String r;
628: Boolean indexf;
629: enum { KNOWN, SEQUENTIAL, BRANCH } addrstatus;
630:
631: argval = 0;
632: indexf = false;
633: addr = startaddr;
634: iread(&ins, addr, sizeof(ins));
635: switch (ins) {
636:
637: case O_CALLF:
638: case O_CALLS:
639: addrstatus = KNOWN;
640: stepto(addr);
641: pstep(process, DEFSIG);
642: addr = reg(PROGCTR);
643: pc = addr;
644: setcurfunc(whatblock(pc));
645: if (not isbperr()) {
646: printstatus();
647: /* NOTREACHED */
648: }
649: bpact();
650: if (isnext or skipfunc(ins, curfunc)) {
651: addrstatus = KNOWN;
652: addr = return_addr();
653: stepto(addr);
654: bpact();
655: } else
656: callnews(/* iscall = */ true);
657: break;
658:
659: case O_RET:
660: addrstatus = KNOWN;
661: stepto(addr);
662: callnews(/* iscall = */ false);
663: pstep(process, DEFSIG);
664: addr = reg(PROGCTR);
665: pc = addr;
666: if (not isbperr())
667: printstatus();
668: bpact();
669: break;
670:
671: case O_BRB:
672: case O_BRW:
673: case O_JMP:
674: case O_BBSSI:
675: case O_BCC:
676: case O_BCS:
677: case O_BEQL:
678: case O_BGEQ:
679: case O_BGTR:
680: case O_BGTRU:
681: case O_BLEQ:
682: case O_BLEQU:
683: case O_BLSS:
684: case O_BNEQ:
685: case O_BVC:
686: case O_BVS:
687: case O_CASEL:
688: case O_AOBLSS:
689: case O_AOBLEQ:
690: addrstatus = KNOWN;
691: stepto(addr);
692: pstep(process, DEFSIG);
693: addr = reg(PROGCTR);
694: pc = addr;
695: if (not isbperr())
696: printstatus();
697: break;
698:
699: default:
700: addrstatus = SEQUENTIAL;
701: break;
702: }
703: if (addrstatus == KNOWN)
704: return (addr);
705: addr += 1;
706: op = ioptab[ins];
707: for (argno = 0; argno < op->numargs; argno++) {
708: if (indexf == true)
709: indexf = false;
710: argtype = op->argtype[argno];
711: if (is_branch_disp(argtype))
712: mode = 0xAF + (typelen(argtype) << 5);
713: else
714: iread(&mode, addr, sizeof(mode)), addr += 1;
715: r = regname[regnm(mode)];
716: amode = addrmode(mode);
717: switch (amode) {
718:
719: case LITSHORT:
720: case LITUPTO31:
721: case LITUPTO47:
722: case LITUPTO63:
723: argval = mode;
724: break;
725:
726: case INDEX:
727: indexf = true;
728: --argno;
729: break;
730:
731: case REG:
732: case REGDEF:
733: case AUTODEC:
734: break;
735:
736: case AUTOINC:
737: nib = mode & 0xf;
738: if (nib == 0xf || nib == 8 || nib == 9) {
739: int size = (mode&03)+1;
740:
741: argval = getdisp(addr, size,
742: regname[PROGCTR], amode);
743: addr += size;
744: }
745: break;
746:
747: case AUTOINCDEF:
748: if ((mode&0xf) != 0xf)
749: break;
750: argval = getdisp(addr, 4, r, amode);
751: addr += 4;
752: break;
753:
754: case BYTEDISP:
755: case BYTEDISPDEF:
756: argval = getdisp(addr, 1, r, amode);
757: addr += 1;
758: break;
759:
760: case WORDDISP:
761: case WORDDISPDEF:
762: argval = getdisp(addr, 2, r, amode);
763: addr += 2;
764: break;
765:
766: case LONGDISP:
767: case LONGDISPDEF:
768: argval = getdisp(addr, 4, r, amode);
769: addr += 4;
770: break;
771: }
772: }
773: if (ins == O_CALLF or ins == O_CALLS)
774: argval += 2;
775: if (addrstatus == BRANCH)
776: addr = argval;
777: return (addr);
778: }
779:
780: /*
781: * Get the displacement of an instruction that uses displacement addressing.
782: */
783: private int getdisp(addr, nbytes, reg, mode)
784: Address addr;
785: int nbytes;
786: String reg;
787: int mode;
788: {
789: char byte;
790: short hword;
791: int argval;
792:
793: switch (nbytes) {
794:
795: case 1:
796: iread(&byte, addr, sizeof(byte));
797: argval = byte;
798: break;
799:
800: case 2:
801: iread(&hword, addr, sizeof(hword));
802: argval = hword;
803: break;
804:
805: case 4:
806: iread(&argval, addr, sizeof(argval));
807: break;
808: }
809: if (reg == regname[PROGCTR] && mode >= BYTEDISP)
810: argval += addr + nbytes;
811: return (argval);
812: }
813:
814: #define BP_OP O_BPT /* breakpoint trap */
815: #define BP_ERRNO SIGTRAP /* signal received at a breakpoint */
816:
817: /*
818: * Setting a breakpoint at a location consists of saving
819: * the word at the location and poking a BP_OP there.
820: *
821: * We save the locations and words on a list for use in unsetting.
822: */
823: typedef struct Savelist *Savelist;
824:
825: struct Savelist {
826: Address location;
827: Byte save;
828: Byte refcount;
829: Savelist link;
830: };
831:
832: private Savelist savelist;
833:
834: /*
835: * Set a breakpoint at the given address. Only save the word there
836: * if it's not already a breakpoint.
837: */
838: public setbp(addr)
839: Address addr;
840: {
841: Byte w, save;
842: register Savelist newsave, s;
843:
844: for (s = savelist; s != nil; s = s->link)
845: if (s->location == addr) {
846: s->refcount++;
847: return;
848: }
849: iread(&save, addr, sizeof(save));
850: newsave = new(Savelist);
851: newsave->location = addr;
852: newsave->save = save;
853: newsave->refcount = 1;
854: newsave->link = savelist;
855: savelist = newsave;
856: w = BP_OP;
857: iwrite(&w, addr, sizeof(w));
858: }
859:
860: /*
861: * Unset a breakpoint; unfortunately we have to search the SAVELIST
862: * to find the saved value. The assumption is that the SAVELIST will
863: * usually be quite small.
864: */
865: public unsetbp(addr)
866: Address addr;
867: {
868: register Savelist s, prev;
869:
870: prev = nil;
871: for (s = savelist; s != nil; s = s->link) {
872: if (s->location == addr) {
873: iwrite(&s->save, addr, sizeof(s->save));
874: s->refcount--;
875: if (s->refcount == 0) {
876: if (prev == nil)
877: savelist = s->link;
878: else
879: prev->link = s->link;
880: dispose(s);
881: }
882: return;
883: }
884: prev = s;
885: }
886: panic("unsetbp: couldn't find address %d", addr);
887: }
888:
889: /*
890: * Enter a procedure by creating and executing a call instruction.
891: */
892:
893: #define CALLSIZE 7 /* size of call instruction */
894:
895: public beginproc(p, argc)
896: Symbol p;
897: Integer argc;
898: {
899: char save[CALLSIZE];
900: struct {
901: Opcode op;
902: unsigned char numargs;
903: unsigned char mode;
904: char addr[sizeof(long)]; /* unaligned long */
905: } call;
906: long dest;
907:
908: if (4*argc+4 > 256)
909: error("too many parameters (max %d)", 256/4 - 1);
910: pc = 2;
911: iread(save, pc, sizeof(save));
912: call.op = O_CALLF;
913: call.numargs = 4*argc+4;
914: call.mode = 0xef; /* longword relative */
915: dest = codeloc(p) - 2 - (pc + CALLSIZE);
916: mov(&dest, call.addr, sizeof(call.addr));
917: iwrite(&call, pc, sizeof(call));
918: setreg(PROGCTR, pc);
919: pstep(process, DEFSIG);
920: iwrite(save, pc, sizeof(save));
921: pc = reg(PROGCTR);
922: if (not isbperr())
923: printstatus();
924: }
925:
926: /*
927: * Special variables for debugging the kernel.
928: */
929:
930: public integer masterpcbb;
931: public integer slr;
932: public struct pte *sbr;
933: private struct pcb pcb;
934:
935: public getpcb ()
936: {
937: fseek(corefile, masterpcbb & ~0xc0000000, 0);
938: get(corefile, pcb);
939: printf("p0br %lx p0lr %lx p2br %lx p2lr %lx\n",
940: pcb.pcb_p0br, pcb.pcb_p0lr, pcb.pcb_p2br, pcb.pcb_p2lr
941: );
942: setreg(0, pcb.pcb_r0);
943: setreg(1, pcb.pcb_r1);
944: setreg(2, pcb.pcb_r2);
945: setreg(3, pcb.pcb_r3);
946: setreg(4, pcb.pcb_r4);
947: setreg(5, pcb.pcb_r5);
948: setreg(6, pcb.pcb_r6);
949: setreg(7, pcb.pcb_r7);
950: setreg(8, pcb.pcb_r8);
951: setreg(9, pcb.pcb_r9);
952: setreg(10, pcb.pcb_r10);
953: setreg(11, pcb.pcb_r11);
954: setreg(12, pcb.pcb_r12);
955: setreg(FRP, pcb.pcb_fp);
956: setreg(STKP, pcb.pcb_ksp);
957: setreg(PROGCTR, pcb.pcb_pc);
958: }
959:
960: public copyregs (savreg, reg)
961: Word savreg[], reg[];
962: {
963: reg[0] = savreg[R0];
964: reg[1] = savreg[R1];
965: reg[2] = savreg[R2];
966: reg[3] = savreg[R3];
967: reg[4] = savreg[R4];
968: reg[5] = savreg[R5];
969: reg[6] = savreg[R6];
970: reg[7] = savreg[R7];
971: reg[8] = savreg[R8];
972: reg[9] = savreg[R9];
973: reg[10] = savreg[R10];
974: reg[11] = savreg[R11];
975: reg[12] = savreg[R12];
976: reg[FRP] = savreg[FP];
977: reg[STKP] = savreg[SP];
978: reg[PROGCTR] = savreg[PC];
979: }
980:
981: /*
982: * Map a virtual address to a physical address.
983: */
984:
985: public Address vmap (addr)
986: Address addr;
987: {
988: int oldaddr = addr, v;
989: struct pte pte;
990:
991: addr &= ~0xc0000000;
992: v = btop(addr);
993: switch (oldaddr&0xc0000000) {
994:
995: case 0xc0000000:
996: /*
997: * In system space get system pte. If
998: * valid or reclaimable then physical address
999: * is combination of its page number and the page
1000: * offset of the original address.
1001: */
1002: if (v >= slr)
1003: goto oor;
1004: addr = ((long)(sbr+v)) &~ 0xc0000000;
1005: goto simple;
1006:
1007: case 0x80000000:
1008: /*
1009: * In p2 spce must not be in shadow region.
1010: */
1011: if (v < pcb.pcb_p2lr)
1012: goto oor;
1013: addr = (long)(pcb.pcb_p2br+v);
1014: break;
1015:
1016: case 0x40000000:
1017: /*
1018: * In p1 space everything is verboten (for now).
1019: */
1020: goto oor;
1021:
1022: case 0x00000000:
1023: /*
1024: * In p0 space must not be off end of region.
1025: */
1026: if (v >= pcb.pcb_p0lr)
1027: goto oor;
1028: addr = (long)(pcb.pcb_p0br+v);
1029: break;
1030: oor:
1031: error("address out of segment");
1032: }
1033: /*
1034: * For p0/p1/p2 address, user-level page table should
1035: * be in kernel vm. Do second-level indirect by recursing.
1036: */
1037: if ((addr & 0xc0000000) != 0xc0000000)
1038: error("bad p0br, p1br, or p2br in pcb");
1039: addr = vmap(addr);
1040: simple:
1041: /*
1042: * Addr is now address of the pte of the page we
1043: * are interested in; get the pte and paste up the
1044: * physical address.
1045: */
1046: fseek(corefile, addr, 0);
1047: if (fread(&pte, sizeof (pte), 1, corefile) != 1)
1048: error("page table botch");
1049: /* SHOULD CHECK NOT I/O ADDRESS; NEED CPU TYPE! */
1050: if (pte.pg_v == 0 && (pte.pg_fod || pte.pg_pfnum == 0))
1051: error("page not valid/reclaimable");
1052: return ((long)(ptob(pte.pg_pfnum) + (oldaddr & PGOFSET)));
1053: }
1054:
1055: /*
1056: * Extract a bit field from an integer.
1057: */
1058:
1059: public integer extractField (s)
1060: Symbol s;
1061: {
1062: integer nbytes, nbits, n, r, off, len;
1063:
1064: off = s->symvalue.field.offset;
1065: len = s->symvalue.field.length;
1066: nbytes = size(s);
1067: n = 0;
1068: if (nbytes > sizeof(n)) {
1069: printf("[bad size in extractField -- word assumed]\n");
1070: nbytes = sizeof(n);
1071: }
1072: popn(nbytes, ((char *) &n) + (sizeof(Word) - nbytes));
1073: nbits = nbytes * BITSPERBYTE;
1074: r = n >> (nbits - ((off mod nbits) + len));
1075: r &= ((1 << len) - 1);
1076: return r;
1077: }
1078:
1079: /*
1080: * Change the length of a value in memory according to a given difference
1081: * in the lengths of its new and old types.
1082: */
1083:
1084: public loophole (oldlen, newlen)
1085: integer oldlen, newlen;
1086: {
1087: integer i, n;
1088: Stack *oldsp;
1089:
1090: n = newlen - oldlen;
1091: oldsp = sp - oldlen;
1092: if (n > 0) {
1093: for (i = oldlen - 1; i >= 0; i--) {
1094: oldsp[n + i] = oldsp[i];
1095: }
1096: for (i = 0; i < n; i++) {
1097: oldsp[i] = '\0';
1098: }
1099: } else {
1100: for (i = 0; i < newlen; i++) {
1101: oldsp[i] = oldsp[i - n];
1102: }
1103: }
1104: sp += n;
1105: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.