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