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