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