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