merge in latest Linton version
[unix-history] / usr / src / old / dbx / vax.c
CommitLineData
2a24676e
DF
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 */
cd6e9098 6
2a24676e 7#ifndef lint
d244f11c 8static char sccsid[] = "@(#)vax.c 5.4 (Berkeley) %G%";
2a24676e 9#endif not lint
0022c355 10
d244f11c 11static char rcsid[] = "$Header: machine.c,v 1.2 87/03/26 14:54:55 donn Exp $";
cd6e9098
ML
12
13/*
14 * Target machine dependent stuff.
15 */
16
17#include "defs.h"
18#include "machine.h"
19#include "process.h"
2fd0f574 20#include "runtime.h"
cd6e9098
ML
21#include "events.h"
22#include "main.h"
23#include "symbols.h"
24#include "source.h"
25#include "mappings.h"
26#include "object.h"
d244f11c
DS
27#include "tree.h"
28#include "eval.h"
0022c355 29#include "keywords.h"
9882bead 30#include "ops.h"
cd6e9098
ML
31
32#ifndef public
33typedef unsigned int Address;
34typedef unsigned char Byte;
35typedef 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
d244f11c
DS
44#define CODESTART 0
45#define FUNCOFFSET 2
46
47#define nargspassed(frame) argn(0, frame)
48
cd6e9098
ML
49#define BITSPERBYTE 8
50#define BITSPERWORD (BITSPERBYTE * sizeof(Word))
51
b4ee78f0 52/*
d244f11c
DS
53 * This magic macro enables us to look at the process' registers
54 * in its user structure.
b4ee78f0 55 */
b4ee78f0 56
d244f11c 57#define regloc(reg) (ctob(UPAGES) + (sizeof(Word) * (reg)))
b4ee78f0 58
cd6e9098
ML
59#include "source.h"
60#include "symbols.h"
d244f11c 61#include <signal.h>
25560c54
SL
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>
d244f11c 67#undef DELETE /* XXX */
25560c54
SL
68#include <sys/vm.h>
69#include <machine/reg.h>
cd6e9098
ML
70
71Address pc;
72Address prtaddr;
73
74#endif
75
d244f11c
DS
76/*
77 * Indices into u. for use in collecting registers values.
78 */
79public int rloc[] ={
80 R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, AP, FP, SP, PC
81};
82
cd6e9098
ML
83private Address printop();
84
d244f11c
DS
85private Optab *ioptab[256]; /* index by opcode to optab */
86
25560c54 87/*
d244f11c 88 * Initialize the opcode lookup table.
25560c54 89 */
d244f11c
DS
90public optab_init()
91{
92 register Optab *p;
93
94 for (p = optab; p->iname; p++)
95 ioptab[p->val & 0xff] = p;
96}
25560c54 97
cd6e9098
ML
98/*
99 * Decode and print the instructions within the given address range.
100 */
101
102public printinst(lowaddr, highaddr)
103Address lowaddr;
104Address 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
118public printninst(count, addr)
119int count;
120Address 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
cd6e9098
ML
136/*
137 * Print the contents of the addresses within the given range
138 * according to the given format.
139 */
140
141typedef struct {
142 String name;
143 String printfstring;
144 int length;
145} Format;
146
147private 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) },
5d8fcc0a 157 { "f", " %f", sizeof(float) },
cd6e9098
ML
158 { "g", " %g", sizeof(double) },
159 { nil, nil, 0 }
160};
161
08cf9c08
ML
162private Format *findformat(s)
163String 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
d244f11c
DS
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
183private printformat (f, addr)
184Format *f;
185Address 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
cd6e9098
ML
204public Address printdata(lowaddr, highaddr, format)
205Address lowaddr;
206Address highaddr;
207String format;
208{
d244f11c 209 int n;
cd6e9098 210 register Address addr;
d244f11c 211 Format *f;
cd6e9098
ML
212
213 if (lowaddr > highaddr) {
214 error("first address larger than second");
215 }
08cf9c08 216 f = findformat(format);
cd6e9098 217 n = 0;
cd6e9098
ML
218 for (addr = lowaddr; addr <= highaddr; addr += f->length) {
219 if (n == 0) {
220 printf("%08x: ", addr);
221 }
d244f11c 222 printformat(f, addr);
cd6e9098
ML
223 ++n;
224 if (n >= (16 div f->length)) {
d244f11c 225 printf("\n");
cd6e9098
ML
226 n = 0;
227 }
228 }
229 if (n != 0) {
d244f11c 230 printf("\n");
cd6e9098
ML
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
240public printndata(count, startaddr, format)
241int count;
242Address startaddr;
243String format;
244{
d244f11c
DS
245 int i, n;
246 Address addr;
247 Format *f;
248 Boolean isstring;
5d8fcc0a 249 char c;
cd6e9098
ML
250
251 if (count <= 0) {
252 error("non-positive repetition count");
253 }
08cf9c08 254 f = findformat(format);
cd6e9098
ML
255 isstring = (Boolean) streq(f->name, "s");
256 n = 0;
257 addr = startaddr;
cd6e9098
ML
258 for (i = 0; i < count; i++) {
259 if (n == 0) {
260 printf("%08x: ", addr);
261 }
262 if (isstring) {
d244f11c 263 printf("\"");
5d8fcc0a
ML
264 dread(&c, addr, sizeof(char));
265 while (c != '\0') {
266 printchar(c);
cd6e9098 267 ++addr;
5d8fcc0a 268 dread(&c, addr, sizeof(char));
cd6e9098 269 }
d244f11c 270 printf("\"\n");
cd6e9098
ML
271 n = 0;
272 addr += sizeof(String);
273 } else {
d244f11c 274 printformat(f, addr);
cd6e9098
ML
275 ++n;
276 if (n >= (16 div f->length)) {
d244f11c 277 printf("\n");
cd6e9098
ML
278 n = 0;
279 }
280 addr += f->length;
281 }
282 }
283 if (n != 0) {
d244f11c 284 printf("\n");
cd6e9098
ML
285 }
286 prtaddr = addr;
287}
288
08cf9c08
ML
289/*
290 * Print out a value according to the given format.
291 */
292
293public printvalue(v, format)
294long v;
295String 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
cd6e9098
ML
316/*
317 * Print out an execution time error.
8026876b 318 * Assumes the source position of the error has been calculated.
cd6e9098
ML
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
324public printerror()
325{
326 extern Integer sys_nsig;
327 extern String sys_siglist[];
0022c355 328 integer err;
cd6e9098
ML
329
330 if (isfinished(process)) {
1853d822 331 err = exitcode(process);
0022c355
ML
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 }
cd6e9098
ML
339 erecover();
340 }
cd6e9098 341 err = errnum(process);
1853d822
SL
342 putchar('\n');
343 printsig(err);
0022c355 344 putchar(' ');
1853d822 345 printloc();
cd6e9098
ML
346 putchar('\n');
347 if (curline > 0) {
348 printlines(curline, curline);
349 } else {
350 printinst(pc, pc);
351 }
352 erecover();
353}
354
d244f11c
DS
355/*
356 * Print out a signal.
357 */
358
359private String illinames[] = {
360 "reserved addressing fault",
361 "privileged instruction fault",
362 "reserved operand fault"
363};
364
365private 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
379public printsig (signo)
380integer 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
408public 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
429private Address getcall();
430
431public dostep(isnext)
432Boolean 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
456typedef 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
469typedef struct Savelist *Savelist;
470
471struct Savelist {
472 Address location;
473 Bpinst save;
474 short refcount;
475 Savelist link;
476};
477
478private 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
485public setbp(addr)
486Address 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
514public unsetbp(addr)
515Address 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
543private Address printop(addr)
544Address 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;
0022c355 661
d244f11c
DS
662 case BYTEDISPDEF:
663 printf("*");
664 argval = printdisp(addr, 1, reg, amode);
665 addr += 1;
666 break;
0022c355 667
d244f11c
DS
668 case WORDDISP:
669 argval = printdisp(addr, 2, reg, amode);
670 addr += 2;
671 break;
1853d822 672
d244f11c
DS
673 case WORDDISPDEF:
674 printf("*");
675 argval = printdisp(addr, 2, reg, amode);
676 addr += 2;
677 break;
1853d822 678
d244f11c
DS
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;
0022c355 689 }
d244f11c
DS
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;
0022c355 696 }
1853d822 697 }
d244f11c
DS
698 printf("\n");
699 return addr;
1853d822
SL
700}
701
cd6e9098 702/*
d244f11c
DS
703 * Print the displacement of an instruction that uses displacement
704 * addressing.
cd6e9098
ML
705 */
706
d244f11c
DS
707private int printdisp(addr, nbytes, reg, mode)
708Address addr;
709int nbytes;
710char *reg;
711int mode;
cd6e9098 712{
d244f11c
DS
713 char byte;
714 short hword;
715 int argval;
716 Symbol f;
cd6e9098 717
d244f11c
DS
718 switch (nbytes) {
719 case 1:
720 iread(&byte, addr, sizeof(byte));
721 argval = byte;
722 break;
cd6e9098 723
d244f11c
DS
724 case 2:
725 iread(&hword, addr, sizeof(hword));
726 argval = hword;
727 break;
cd6e9098 728
d244f11c
DS
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);
cd6e9098 742 }
38f911d6 743 } else {
d244f11c
DS
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 }
cd6e9098 753 }
d244f11c 754 return argval;
cd6e9098
ML
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
0022c355
ML
769private Address findnextaddr();
770
cd6e9098
ML
771public Address nextaddr(startaddr, isnext)
772Address startaddr;
2fd0f574
SL
773boolean 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
0022c355
ML
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
791private boolean skipfunc (ins, f)
792VaxOpcode ins;
793Symbol 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
2fd0f574
SL
805private Address findnextaddr(startaddr, isnext)
806Address startaddr;
cd6e9098
ML
807Boolean isnext;
808{
809 register Address addr;
d244f11c 810 register Optab *op;
cd6e9098
ML
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) {
0022c355
ML
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 *
cd6e9098
ML
833 case O_BRB:
834 case O_BRW:
cd6e9098
ML
835 addrstatus = BRANCH;
836 break;
0022c355
ML
837 *
838 */
cd6e9098
ML
839
840 case O_BSBB:
841 case O_BSBW:
842 case O_JSB:
843 case O_CALLG:
844 case O_CALLS:
0022c355
ML
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)) {
cd6e9098 857 addrstatus = KNOWN;
0022c355 858 addr = return_addr();
cd6e9098 859 stepto(addr);
eac2165c 860 bpact();
0022c355
ML
861 } else {
862 callnews(/* iscall = */ true);
cd6e9098
ML
863 }
864 break;
865
866 case O_RSB:
867 case O_RET:
868 addrstatus = KNOWN;
0022c355 869 stepto(addr);
cd6e9098 870 callnews(/* iscall = */ false);
0022c355
ML
871 pstep(process, DEFSIG);
872 addr = reg(PROGCTR);
873 pc = addr;
874 if (not isbperr()) {
875 printstatus();
2fd0f574 876 }
3b5f59dc 877 bpact();
cd6e9098
ML
878 break;
879
0022c355 880 case O_BRB: case O_BRW:
2fd0f574 881 case O_JMP: /* because it may be jmp (r1) */
cd6e9098
ML
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);
2fd0f574 894 pstep(process, DEFSIG);
cd6e9098
ML
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;
d244f11c
DS
908 op = ioptab[ins];
909 for (argno = 0; argno < op->numargs; argno++) {
cd6e9098
ML
910 if (indexf == true) {
911 indexf = false;
912 }
d244f11c 913 argtype = op->argtype[argno];
cd6e9098
ML
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
1012private int getdisp(addr, nbytes, reg, mode)
1013Address addr;
1014int nbytes;
1015String reg;
1016int 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
cd6e9098
ML
1043/*
1044 * Enter a procedure by creating and executing a call instruction.
1045 */
1046
1047#define CALLSIZE 7 /* size of call instruction */
1048
1049public beginproc(p, argc)
1050Symbol p;
1051Integer 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);
2fd0f574 1071 pstep(process, DEFSIG);
cd6e9098
ML
1072 iwrite(save, pc, sizeof(save));
1073 pc = reg(PROGCTR);
1074 if (not isbperr()) {
1075 printstatus();
1076 }
1077}
b4ee78f0
SL
1078
1079/*
1080 * Special variables for debugging the kernel.
1081 */
1082
1083public integer masterpcbb;
1084public integer slr;
1085public struct pte *sbr;
d244f11c 1086private struct pcb pcb;
b4ee78f0
SL
1087
1088public getpcb ()
1089{
d244f11c
DS
1090 integer i;
1091
1092 fseek(corefile, masterpcbb & ~0x80000000, 0);
b4ee78f0
SL
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
1116public copyregs (savreg, reg)
1117Word 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
1141public Address vmap (addr)
1142Address 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);
1197simple:
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}
d244f11c
DS
1212
1213/*
1214 * Extract a bit field from an integer.
1215 */
1216
1217public integer extractField (s)
1218Symbol 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
1239public loophole (oldlen, newlen)
1240integer 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}