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