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