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