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