xref: /original-bsd/old/dbx/sun.c (revision fa921481)
1 /*
2  * Copyright (c) 1983 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 static char sccsid[] = "@(#)sun.c	5.2 (Berkeley) 06/01/90";
10 #endif /* not lint */
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 "tree.h"
27 #include "eval.h"
28 #include "keywords.h"
29 #include "ops.h"
30 
31 #ifndef public
32 typedef unsigned int Address;
33 typedef unsigned char Byte;
34 typedef unsigned int Word;
35 
36 /*
37  * On the 68000, the pc isn't in a register, but we make believe
38  * so there's one more register.
39  *
40  * Note that there's also no argument pointer, this means code
41  * involving "ARGP" should always be #ifdef'd.
42  *
43  * The address corresponding to the beginning of a function is recorded
44  * as the address + FUNCOFFSET (skip the link instruction so that
45  * local information is available).
46  */
47 
48 #define NREG 17
49 
50 #define FRP 14
51 #define STKP 15
52 #define PROGCTR 16
53 
54 #define CALL_RETADDR	0x800c		/* Return address for 'call' command */
55 #define FUNCOFFSET 4
56 
57 #ifdef sun
58 #    define CODESTART 0x8000
59 #else /* IRIS */
60 #   define CODESTART 0x1000
61 #endif
62 
63 #define optab_init()
64 
65 #define BITSPERBYTE 8
66 #define BITSPERWORD (BITSPERBYTE * sizeof(Word))
67 
68 /*
69  * This magic macro enables us to look at the process' registers
70  * in its user structure.
71  */
72 
73 #define regloc(reg)	(ctob(UPAGES) + (sizeof(Word) * ((reg) - PC)) - 10)
74 
75 #include "source.h"
76 #include "symbols.h"
77 #include <signal.h>
78 #include <sys/param.h>
79 #include <sys/dir.h>
80 #include <machine/psl.h>
81 #include <machine/pte.h>
82 #include <sys/user.h>
83 #undef DELETE /* XXX */
84 #include <sys/vm.h>
85 #include <machine/reg.h>
86 
87 Address pc;
88 Address prtaddr;
89 
90 #endif
91 
92 /*
93  * Indices into u. for use in collecting registers values.
94  */
95 public int rloc[] ={
96 #ifdef sun
97     R0, R1, R2, R3, R4, R5, R6, R7, AR0, AR1, AR2, AR3, AR4, AR5, AR6, AR7, PC
98 #else /* IRIS */
99     R0, R1, R2, R3, R4, R5, R6, R7, AR0, AR1, AR2, AR3, AR4, AR5, AR6, AR7, 16
100 #endif
101 };
102 
103 private Address printop();
104 
105 /*
106  * Decode and print the instructions within the given address range.
107  */
108 
109 public printinst(lowaddr, highaddr)
110 Address lowaddr;
111 Address highaddr;
112 {
113     register Address addr;
114 
115     for (addr = lowaddr; addr <= highaddr; ) {
116 	addr = printop(addr);
117     }
118     prtaddr = addr;
119 }
120 
121 /*
122  * Another approach:  print n instructions starting at the given address.
123  */
124 
125 public printninst(count, addr)
126 int count;
127 Address addr;
128 {
129     register Integer i;
130     register Address newaddr;
131 
132     if (count <= 0) {
133 	error("non-positive repetition count");
134     } else {
135 	newaddr = addr;
136 	for (i = 0; i < count; i++) {
137 	    newaddr = printop(newaddr);
138 	}
139 	prtaddr = newaddr;
140     }
141 }
142 
143 /*
144  * Print the contents of the addresses within the given range
145  * according to the given format.
146  */
147 
148 typedef struct {
149     String name;
150     String printfstring;
151     int length;
152 } Format;
153 
154 private Format fmt[] = {
155     { "d", " %d", sizeof(short) },
156     { "D", " %ld", sizeof(long) },
157     { "o", " %o", sizeof(short) },
158     { "O", " %lo", sizeof(long) },
159     { "x", " %04x", sizeof(short) },
160     { "X", " %08x", sizeof(long) },
161     { "b", " \\%o", sizeof(char) },
162     { "c", " '%c'", sizeof(char) },
163     { "s", "%c", sizeof(char) },
164     { "f", " %f", sizeof(float) },
165     { "g", " %g", sizeof(double) },
166     { nil, nil, 0 }
167 };
168 
169 private Format *findformat(s)
170 String s;
171 {
172     register Format *f;
173 
174     f = &fmt[0];
175     while (f->name != nil and not streq(f->name, s)) {
176 	++f;
177     }
178     if (f->name == nil) {
179 	error("bad print format \"%s\"", s);
180     }
181     return f;
182 }
183 
184 /*
185  * Retrieve and print out the appropriate data in the given format.
186  * Floats have to be handled specially to allow the compiler to
187  * convert them to doubles when passing to printf.
188  */
189 
190 private printformat (f, addr)
191 Format *f;
192 Address addr;
193 {
194     union {
195 	char charv;
196 	short shortv;
197 	int intv;
198 	float floatv;
199 	double doublev;
200     } value;
201 
202     value.intv = 0;
203     dread(&value, addr, f->length);
204     if (streq(f->name, "f")) {
205 	printf(f->printfstring, value.floatv);
206     } else {
207 	printf(f->printfstring, value);
208     }
209 }
210 
211 public Address printdata(lowaddr, highaddr, format)
212 Address lowaddr;
213 Address highaddr;
214 String format;
215 {
216     int n;
217     register Address addr;
218     Format *f;
219 
220     if (lowaddr > highaddr) {
221 	error("first address larger than second");
222     }
223     f = findformat(format);
224     n = 0;
225     for (addr = lowaddr; addr <= highaddr; addr += f->length) {
226 	if (n == 0) {
227 	    printf("%08x: ", addr);
228 	}
229 	printformat(f, addr);
230 	++n;
231 	if (n >= (16 div f->length)) {
232 	    printf("\n");
233 	    n = 0;
234 	}
235     }
236     if (n != 0) {
237 	printf("\n");
238     }
239     prtaddr = addr;
240     return addr;
241 }
242 
243 /*
244  * The other approach is to print n items starting with a given address.
245  */
246 
247 public printndata(count, startaddr, format)
248 int count;
249 Address startaddr;
250 String format;
251 {
252     int i, n;
253     Address addr;
254     Format *f;
255     Boolean isstring;
256     char c;
257 
258     if (count <= 0) {
259 	error("non-positive repetition count");
260     }
261     f = findformat(format);
262     isstring = (Boolean) streq(f->name, "s");
263     n = 0;
264     addr = startaddr;
265     for (i = 0; i < count; i++) {
266 	if (n == 0) {
267 	    printf("%08x: ", addr);
268 	}
269 	if (isstring) {
270 	    printf("\"");
271 	    dread(&c, addr, sizeof(char));
272 	    while (c != '\0') {
273 		printchar(c);
274 		++addr;
275 		dread(&c, addr, sizeof(char));
276 	    }
277 	    printf("\"\n");
278 	    n = 0;
279 	    addr += sizeof(String);
280 	} else {
281 	    printformat(f, addr);
282 	    ++n;
283 	    if (n >= (16 div f->length)) {
284 		printf("\n");
285 		n = 0;
286 	    }
287 	    addr += f->length;
288 	}
289     }
290     if (n != 0) {
291 	printf("\n");
292     }
293     prtaddr = addr;
294 }
295 
296 /*
297  * Print out a value according to the given format.
298  */
299 
300 public printvalue(v, format)
301 long v;
302 String format;
303 {
304     Format *f;
305     char *p, *q;
306 
307     f = findformat(format);
308     if (streq(f->name, "s")) {
309 	putchar('"');
310 	p = (char *) &v;
311 	q = p + sizeof(v);
312 	while (p < q) {
313 	    printchar(*p);
314 	    ++p;
315 	}
316 	putchar('"');
317     } else {
318 	printf(f->printfstring, v);
319     }
320     putchar('\n');
321 }
322 
323 /*
324  * Print out an execution time error.
325  * Assumes the source position of the error has been calculated.
326  *
327  * Have to check if the -r option was specified; if so then
328  * the object file information hasn't been read in yet.
329  */
330 
331 public printerror()
332 {
333     extern Integer sys_nsig;
334     extern String sys_siglist[];
335     integer err;
336 
337     if (isfinished(process)) {
338 	err = exitcode(process);
339 	if (err == 0) {
340 	    printf("\"%s\" terminated normally\n", objname);
341 	} else {
342 	    printf("\"%s\" terminated abnormally (exit code %d)\n",
343 		objname, err
344 	    );
345 	}
346 	erecover();
347     }
348     err = errnum(process);
349     putchar('\n');
350     printsig(err);
351     putchar(' ');
352     printloc();
353     putchar('\n');
354     if (curline > 0) {
355 	printlines(curline, curline);
356     } else {
357 	printinst(pc, pc);
358     }
359     erecover();
360 }
361 
362 /*
363  * Print out a signal.
364  */
365 
366 private String illinames[] = {
367     "reserved addressing fault",
368     "privileged instruction fault",
369     "reserved operand fault"
370 };
371 
372 private String fpenames[] = {
373     nil,
374     "integer overflow trap",
375     "integer divide by zero trap",
376     "floating overflow trap",
377     "floating/decimal divide by zero trap",
378     "floating underflow trap",
379     "decimal overflow trap",
380     "subscript out of range trap",
381     "floating overflow fault",
382     "floating divide by zero fault",
383     "floating underflow fault"
384 };
385 
386 public printsig (signo)
387 integer signo;
388 {
389     integer code;
390 
391     if (signo < 0 or signo > sys_nsig) {
392 	printf("[signal %d]", signo);
393     } else {
394 	printf("%s", sys_siglist[signo]);
395     }
396     code = errcode(process);
397     if (signo == SIGILL) {
398 	if (code >= 0 and code < sizeof(illinames) / sizeof(illinames[0])) {
399 	    printf(" (%s)", illinames[code]);
400 	}
401     } else if (signo == SIGFPE) {
402 	if (code > 0 and code < sizeof(fpenames) / sizeof(fpenames[0])) {
403 	    printf(" (%s)", fpenames[code]);
404 	}
405     }
406 }
407 
408 /*
409  * Note the termination of the program.  We do this so as to avoid
410  * having the process exit, which would make the values of variables
411  * inaccessible.  We do want to flush all output buffers here,
412  * otherwise it'll never get done.
413  */
414 
415 public endprogram()
416 {
417     Integer exitcode;
418 
419     stepto(nextaddr(pc, true));
420     printnews();
421     exitcode = argn(1, nil);
422     if (exitcode != 0) {
423 	printf("\nexecution completed (exit code %d)\n", exitcode);
424     } else {
425 	printf("\nexecution completed\n");
426     }
427     getsrcpos();
428     erecover();
429 }
430 
431 /*
432  * Single step the machine a source line (or instruction if "inst_tracing"
433  * is true).  If "isnext" is true, skip over procedure calls.
434  */
435 
436 private Address getcall();
437 
438 public dostep(isnext)
439 Boolean isnext;
440 {
441     register Address addr;
442     register Lineno line;
443     String filename;
444     Address startaddr;
445 
446     startaddr = pc;
447     addr = nextaddr(pc, isnext);
448     if (not inst_tracing and nlhdr.nlines != 0) {
449 	line = linelookup(addr);
450 	while (line == 0) {
451 	    addr = nextaddr(addr, isnext);
452 	    line = linelookup(addr);
453 	}
454 	curline = line;
455     } else {
456 	curline = 0;
457     }
458     stepto(addr);
459     filename = srcfilename(addr);
460     setsource(filename);
461 }
462 
463 typedef short Bpinst;
464 
465 extern Bpinst BP_OP;
466 #ifdef sun
467 	asm("_BP_OP: trap #15");
468 #else /* IRIS */
469 	asm("_BP_OP: trap #1");
470 #endif
471 
472 #define BP_ERRNO    SIGTRAP     /* signal received at a breakpoint */
473 
474 /*
475  * Setting a breakpoint at a location consists of saving
476  * the word at the location and poking a BP_OP there.
477  *
478  * We save the locations and words on a list for use in unsetting.
479  */
480 
481 typedef struct Savelist *Savelist;
482 
483 struct Savelist {
484     Address location;
485     Bpinst save;
486     short refcount;
487     Savelist link;
488 };
489 
490 private Savelist savelist;
491 
492 /*
493  * Set a breakpoint at the given address.  Only save the word there
494  * if it's not already a breakpoint.
495  */
496 
497 public setbp(addr)
498 Address addr;
499 {
500     Bpinst w, save;
501     register Savelist newsave, s;
502 
503     for (s = savelist; s != nil; s = s->link) {
504 	if (s->location == addr) {
505 	    s->refcount++;
506 	    return;
507 	}
508     }
509     iread(&save, addr, sizeof(save));
510     newsave = new(Savelist);
511     newsave->location = addr;
512     newsave->save = save;
513     newsave->refcount = 1;
514     newsave->link = savelist;
515     savelist = newsave;
516     w = BP_OP;
517     iwrite(&w, addr, sizeof(w));
518 }
519 
520 /*
521  * Unset a breakpoint; unfortunately we have to search the SAVELIST
522  * to find the saved value.  The assumption is that the SAVELIST will
523  * usually be quite small.
524  */
525 
526 public unsetbp(addr)
527 Address addr;
528 {
529     register Savelist s, prev;
530 
531     prev = nil;
532     for (s = savelist; s != nil; s = s->link) {
533 	if (s->location == addr) {
534 	    iwrite(&s->save, addr, sizeof(s->save));
535 	    s->refcount--;
536 	    if (s->refcount == 0) {
537 		if (prev == nil) {
538 		    savelist = s->link;
539 		} else {
540 		    prev->link = s->link;
541 		}
542 		dispose(s);
543 	    }
544 	    return;
545 	}
546 	prev = s;
547     }
548     panic("unsetbp: couldn't find address %d", addr);
549 }
550 
551 /*
552  * Instruction decoding routines for 68000, derived from adb.
553  *
554  * The shared boolean variable "printing" is true if the decoded
555  * instruction is to be printed, false if not.  In either case,
556  * the address of the next instruction after the given one is returned.
557  */
558 
559 private Boolean printing;
560 private Boolean following;
561 private Boolean followcalls;
562 private Address instaddr;
563 
564 #define instread(var) \
565 { \
566     iread(&var, instaddr, sizeof(var)); \
567     instaddr += sizeof(var); \
568 }
569 
570 private Optab *decode(inst, addr)
571 Word inst;
572 Address addr;
573 {
574     register Optab *o;
575 
576     o = &optab[0];
577     while (o->mask != 0 and (inst&o->mask) != o->match) {
578 	++o;
579     }
580     return o;
581 }
582 
583 private Address printop(addr)
584 Address addr;
585 {
586     Optab *o;
587     short inst;
588 
589     printf("%08x  ", addr);
590     iread(&inst, addr, sizeof(inst));
591     o = decode(inst, addr);
592     if (o->mask == 0) {
593 	printf("\tbadop");
594 	instaddr = addr + sizeof(inst);
595     } else {
596 	printing = true;
597 	following = false;
598 	instaddr = addr + sizeof(inst);
599 	(*o->opfun)(inst, o->farg);
600 	printing = false;
601     }
602     printf("\n");
603     return instaddr;
604 }
605 
606 /*
607  * Quickly find the return address of the current procedure or function
608  * while single stepping.  Just get the word pointed at by sp.
609  */
610 
611 private Address currtnaddr ()
612 {
613     Address retaddr;
614 
615     dread(&retaddr, reg(STKP), sizeof(retaddr));
616     return retaddr;
617 }
618 
619 /*
620  * Print out the effective address for the given parameters.
621  */
622 
623 private printea(mode, reg, size)
624 long mode, reg;
625 int size;
626 {
627     long index, disp;
628     static char *aregs[] = { "a0", "a1", "a2", "a3", "a4", "a5", "a6", "sp" };
629     Byte b;
630     short w;
631     long l;
632 
633     switch ((int)(mode)) {
634 	case 0:
635 	    if (printing) {
636 		printf("d%D", reg);
637 	    }
638 	    break;
639 
640 	case 1:
641 	    if (printing) {
642 		printf("%s", aregs[reg]);
643 	    }
644 	    break;
645 
646 	case 2:
647 	    if (printing) {
648 		printf("%s@", aregs[reg]);
649 	    }
650 	    break;
651 
652 	case 3:
653 	    if (printing) {
654 		printf("%s@+", aregs[reg]);
655 	    }
656 	    break;
657 
658 	case 4:
659 	    if (printing) {
660 		printf("%s@-", aregs[reg]);
661 	    }
662 	    break;
663 
664 	case 5:
665 	    instread(w);
666 	    if (printing) {
667 		printf("%s@(%D)", aregs[reg], w);
668 	    }
669 	    break;
670 
671 	case 6:
672 	    instread(w);
673 	    if (printing) {
674 		index = w;
675 		disp = (char)(index&0377);
676 		printf("%s@(%d,%c%D:%c)", aregs[reg], disp,
677 		    (index&0100000)?'a':'d',(index>>12)&07,
678 		    (index&04000)?'l':'w');
679 	    }
680 	    break;
681 
682 	case 7:
683 	    switch ((int)(reg)) {
684 		case 0:
685 		    instread(w);
686 		    if (printing) {
687 			index = w;
688 			psymoff(index);
689 		    }
690 		    break;
691 
692 		case 1:
693 		    instread(l);
694 		    if (printing) {
695 			index = l;
696 			psymoff(index);
697 		    }
698 		    break;
699 
700 		case 2:
701 		    instread(w);
702 		    if (printing) {
703 			disp = w;
704 			psymoff(disp + instaddr);
705 		    }
706 		    break;
707 
708 		case 3:
709 		    instread(w);
710 		    if (printing) {
711 			index = w;
712 			disp = (char)(index&0377);
713 			printf("pc@(%D,%c%D:%c)", disp,
714 			    (index&0100000)?'a':'d',(index>>12)&07,
715 			    (index&04000)?'l':'w');
716 		    }
717 		    break;
718 
719 		case 4:
720 		    switch (size) {
721 			case sizeof(b):
722 			    instread(w);
723 			    index = (w&0xff);
724 			    break;
725 
726 			case sizeof(w):
727 			    instread(w);
728 			    index = w;
729 			    break;
730 
731 			case sizeof(l):
732 			    instread(l);
733 			    index = l;
734 			    break;
735 
736 			default:
737 			    if (printing) {
738 			    	printf("unexpected size %d in printea\n", size);
739 			    }
740 			    instread(l);
741 			    index = l;
742 			    break;
743 		    }
744 		    if (printing) {
745 			printf(IMDF, index);
746 		    }
747 		    break;
748 
749 		default:
750 		    if (printing) {
751 			printf("???");
752 		    }
753 		    break;
754 	    }
755 	    break;
756 
757 	default:
758 	    if (printing) {
759 		printf("???");
760 	    }
761 	    break;
762     }
763 }
764 
765 private printEA(ea, size)
766 long ea;
767 int size;
768 {
769     printea((ea>>3)&07, ea&07, size);
770 }
771 
772 private mapsize(inst)
773 register long inst;
774 {
775     int m;
776 
777     inst >>= 6;
778     inst &= 03;
779     switch (inst) {
780 	case 0:
781 	    m = 1;
782 	    break;
783 
784 	case 1:
785 	    m = 2;
786 	    break;
787 
788 	case 2:
789 	    m = 4;
790 	    break;
791 
792 	default:
793 	    m = -1;
794 	    break;
795     }
796     return m;
797 }
798 
799 private char suffix(size)
800 int size;
801 {
802     char c;
803 
804     switch (size) {
805 	case 1:
806 	    c = 'b';
807 	    break;
808 
809 	case 2:
810 	    c = 'w';
811 	    break;
812 
813 	case 4:
814 	    c = 'l';
815 	    break;
816 
817 	default:
818 	    panic("bad size %d in suffix", size);
819     }
820     return c;
821 }
822 
823 /*
824  * Print an address offset.  Eventually this should attempt to be symbolic,
825  * but for now its just printed in hex.
826  */
827 
828 private psymoff (off)
829 Word off;
830 {
831     Symbol f;
832 
833     f = whatblock((Address) (off + FUNCOFFSET));
834     if (codeloc(f) == off + FUNCOFFSET) {
835 	printf("%s", symname(f));
836     } else {
837 	printf("0x%x", off);
838     }
839 }
840 
841 /*
842  * Instruction class specific routines.
843  */
844 
845 public omove(inst, s)
846 long inst;
847 String s;
848 {
849     register int c;
850     int size;
851 
852     c = s[0];
853     if (printing) {
854 	printf("\tmov%c\t", c);
855     }
856     size = ((c == 'b') ? 1 : (c == 'w') ? 2 : 4);
857     printea((inst>>3)&07, inst&07, size);
858     if (printing) {
859 	printf(",");
860     }
861     printea((inst>>6)&07, (inst>>9)&07, size);
862 }
863 
864 /*
865  * Two types: bsr (4 bytes) and bsrs (2 bytes)
866  */
867 
868 public obranch(inst, dummy)
869 long inst;
870 {
871     long disp;
872     String s;
873     short w;
874     Address startingaddr;	/* address of branch instruction */
875     int branchtype;		/* type of branch (0 = unconditional) */
876     Address dest;
877     Address retaddr;		/* for bsr instruction */
878 
879     startingaddr = instaddr - 2;
880     disp = inst&0377;
881     s = "s ";
882     if (disp == 0) {
883 	retaddr = startingaddr + 4;
884     } else {
885 	retaddr = startingaddr + 2;
886     }
887     if (disp > 127) {
888 	disp |= ~0377;
889     } else if (disp == 0){
890 	s = " ";
891 	instread(w);
892 	disp = w;
893     }
894     branchtype = (int)((inst>>8)&017);
895     dest = startingaddr + 2 + disp;
896     if (printing) {
897 	printf("\tb%s%s\t", bname[branchtype], s);
898 	psymoff(dest);
899     }
900     if (following) {
901 	/*
902 	 * If we're to follow the dynamic flow of instructions,
903 	 * we must see where the branch leads.  A branchtype of 0
904 	 * indicates an unconditional branch which we simply take
905 	 * as the new instruction address.  For a conditional branch,
906 	 * we continue execution up to the current address, single step,
907 	 * and keep going.
908 	 */
909 	if (branchtype == 0) {
910 	    instaddr = dest;
911 	} else if (branchtype == 01) {		/* bsr */
912 	    if (followcalls) {
913 		steppast(startingaddr);
914 		curfunc = whatblock(pc, true);
915 		if (not isbperr()) {
916 		    printstatus();
917 		    /* NOTREACHED */
918 		}
919 		bpact();
920 		if (nosource(curfunc) and canskip(curfunc) and
921 		  nlhdr.nlines != 0) {
922 		    stepto(retaddr);
923 		    instaddr = pc;
924 		    bpact();
925 		} else {
926 		    callnews(/* iscall = */ true);
927 		}
928 	    }
929 	} else {
930 	    steppast(startingaddr);
931 	}
932     }
933 }
934 
935 public odbcc(inst, form)
936 long inst;
937 String form;
938 {
939     long disp;
940     short w;
941 
942     instread(w);
943     if (printing) {
944     	printf(form, dbname[(int)((inst>>8)&017)], inst&07);
945 	psymoff(w + sizeof(w));
946     }
947 }
948 
949 public oscc(inst, dummy)
950 long inst;
951 long dummy;
952 {
953     if (printing) {
954 	printf("\ts%s\t", cname[(int)((inst>>8)&017)]);
955     }
956     printea((inst>>3)&07, inst&07, 1);
957 }
958 
959 public biti(inst, dummy)
960 long inst;
961 long dummy;
962 {
963     short w;
964 
965     if (printing) {
966 	printf("\t%s\t", bit[(int)((inst>>6)&03)]);
967     }
968     if (inst&0x0100) {
969 	if (printing) {
970 	    printf("d%D,", inst>>9);
971 	}
972     } else {
973 	instread(w);
974 	if (printing) {
975 	    printf(IMDF, w);
976 	    printf(",");
977 	}
978     }
979     printEA(inst);
980 }
981 
982 public opmode(inst, opcode)
983 long inst;
984 long opcode;
985 {
986     register int opmode;
987     register int reg;
988     int size;
989 
990     opmode = (int)((inst>>6) & 07);
991     reg = (int)((inst>>9) & 07);
992     if (opmode == 0 or opmode == 4) {
993 	size = 1;
994     } else if (opmode == 1 or opmode == 3 or opmode == 5) {
995 	size = 2;
996     } else {
997 	size = 4;
998     }
999     if (printing) {
1000 	printf("\t%s%c\t", opcode, suffix(size));
1001     }
1002     if (opmode >= 4 and opmode <= 6) {
1003 	if (printing) {
1004 	    printf("d%d,", reg);
1005 	}
1006 	printea((inst>>3)&07, inst&07, size);
1007     } else {
1008 	printea((inst>>3)&07, inst&07, size);
1009 	if (printing) {
1010 	    printf(",%c%d",(opmode<=2) ? 'd' : 'a', reg);
1011 	}
1012     }
1013 }
1014 
1015 public shroi(inst, ds)
1016 long inst;
1017 String ds;
1018 {
1019     int rx, ry;
1020     String opcode;
1021 
1022     if ((inst & 0xC0) == 0xC0) {
1023 	opcode = shro[(int)((inst>>9)&03)];
1024 	if (printing) {
1025 	    printf("\t%s%s\t", opcode, ds);
1026 	}
1027 	printEA(inst);
1028     } else {
1029 	if (printing) {
1030 	    opcode = shro[(int)((inst>>3)&03)];
1031 	    printf("\t%s%s%c\t", opcode, ds, suffix(mapsize(inst)));
1032 	    rx = (int)((inst>>9)&07); ry = (int)(inst&07);
1033 	    if ((inst>>5)&01) {
1034 		printf("d%d,d%d", rx, ry);
1035 	    } else {
1036 		printf(IMDF, (rx ? rx : 8));
1037 		printf(",d%d", ry);
1038 	    }
1039 	}
1040     }
1041 }
1042 
1043 public oimmed(inst, opcode)
1044 long inst;
1045 register String opcode;
1046 {
1047     register int size;
1048     long const;
1049     short w;
1050 
1051     size = mapsize(inst);
1052     if (size > 0) {
1053 	if (size == 4) {
1054 	    instread(const);
1055 	} else {
1056 	    instread(w);
1057 	    const = w;
1058 	}
1059 	if (printing) {
1060 	    printf("\t%s%c\t", opcode, suffix(size));
1061 	    printf(IMDF, const);
1062 	    printf(",");
1063 	}
1064 	printEA(inst, size);
1065     } else {
1066 	if (printing) {
1067 	    printf("\tbadop");
1068 	}
1069     }
1070 }
1071 
1072 public oreg(inst, opcode)
1073 long inst;
1074 register String opcode;
1075 {
1076     if (printing) {
1077 	printf(opcode, (inst & 07));
1078     }
1079 }
1080 
1081 public extend(inst, opcode)
1082 long inst;
1083 String opcode;
1084 {
1085     register int size;
1086     int ry, rx;
1087     char c;
1088 
1089     if (printing) {
1090 	size = mapsize(inst);
1091 	ry = (inst&07);
1092 	rx = ((inst>>9)&07);
1093 	c = ((inst & 0x1000) ? suffix(size) : ' ');
1094 	printf("\t%s%c\t", opcode, c);
1095 	if (opcode[0] == 'e') {
1096 	    if (inst & 0x0080) {
1097 		printf("d%D,a%D", rx, ry);
1098 	    } else if (inst & 0x0008) {
1099 		printf("a%D,a%D", rx, ry);
1100 	    } else {
1101 		printf("d%D,d%D", rx, ry);
1102 	    }
1103 	} else if ((inst & 0xF000) == 0xB000) {
1104 	    printf("a%D@+,a%D@+", ry, rx);
1105 	} else if (inst & 0x8) {
1106 	    printf("a%D@-,a%D@-", ry, rx);
1107 	} else {
1108 	    printf("d%D,d%D", ry, rx);
1109 	}
1110     }
1111 }
1112 
1113 public olink(inst, dummy)
1114 long inst;
1115 long dummy;
1116 {
1117     short w;
1118 
1119     instread(w);
1120     if (printing) {
1121 	printf("\tlink\ta%D,", inst&07);
1122 	printf(IMDF, w);
1123     }
1124 }
1125 
1126 public otrap(inst, dummy)
1127 long inst;
1128 {
1129     if (printing) {
1130 	printf("\ttrap\t");
1131 	printf(IMDF, inst&017);
1132     }
1133 }
1134 
1135 public oneop(inst, opcode)
1136 long inst;
1137 register String opcode;
1138 {
1139     if (printing) {
1140 	printf("\t%s",opcode);
1141     }
1142     printEA(inst);
1143 }
1144 
1145 public jsrop(inst, opcode)
1146 long inst;
1147 register String opcode;
1148 {
1149     Address startingaddr;	/* beginning of jsr instruction */
1150     Address retaddr; /* can't call return_addr (frame not set up yet) */
1151 
1152     startingaddr = instaddr - 2;
1153     switch ((inst >> 3) & 07) {
1154 	case 2:
1155 	    retaddr = instaddr;		/* two byte instruction */
1156 	    break;
1157 	case 5:
1158 	case 6:
1159 	    retaddr = instaddr + 2;	/* four byte instruction */
1160 	    break;
1161 	case 7:
1162 	default:
1163 	    switch (inst & 07) {
1164 		case 0:
1165 		case 2:
1166 		case 3:
1167 		    retaddr = instaddr + 2;
1168 		    break;
1169 		case 1:
1170 		default:
1171 		    retaddr = instaddr + 4;	/* six byte instruction */
1172 		    break;
1173 	    }
1174 	    break;
1175     }
1176     if (printing) {
1177 	printf("\t%s",opcode);
1178     }
1179     printEA(inst);
1180     if (following and followcalls) {
1181 	steppast(startingaddr);
1182 	curfunc = whatblock(pc, true);
1183 	if (not isbperr()) {
1184 	    printstatus();
1185 	    /* NOTREACHED */
1186 	}
1187 	bpact();
1188 	if (nosource(curfunc) and canskip(curfunc) and nlhdr.nlines != 0) {
1189 	    stepto(retaddr);
1190 	    instaddr = pc;
1191 	    bpact();
1192 	} else {
1193 	    callnews(/* iscall = */ true);
1194 	}
1195     }
1196 }
1197 
1198 public jmpop(inst, opcode)
1199 long inst;
1200 register String opcode;
1201 {
1202     Address startingaddr;	/* beginning of jump instruction */
1203 
1204     startingaddr = instaddr - 2;
1205     if (printing) {
1206 	printf("\t%s",opcode);
1207     }
1208     printEA(inst);
1209     if (following) {
1210 	steppast(startingaddr);
1211     }
1212 }
1213 
1214 public pregmask(mask)
1215 register int mask;
1216 {
1217     register int i;
1218     register int flag = 0;
1219 
1220     if (printing) {
1221 	printf("#<");
1222 	for (i=0; i<16; i++) {
1223 	    if (mask&1) {
1224 		if (flag) {
1225 		    printf(",");
1226 		} else {
1227 		    ++flag;
1228 		}
1229 		printf("%c%d",(i<8) ? 'd' : 'a', i&07);
1230 	    }
1231 	    mask >>= 1;
1232 	}
1233 	printf(">");
1234     }
1235 }
1236 
1237 public omovem(inst, dummy)
1238 long inst;
1239 long dummy;
1240 {
1241     register int i, list, mask;
1242     register int reglist;
1243     short w;
1244 
1245     i = 0;
1246     list = 0;
1247     mask = 0100000;
1248     instread(w);
1249     reglist = w;
1250     if ((inst & 070) == 040) {	/* predecrement */
1251 	for (i = 15; i > 0; i -= 2) {
1252 	    list |= ((mask & reglist) >> i);
1253 	    mask >>= 1;
1254 	}
1255 	for (i = 1; i < 16; i += 2) {
1256 	    list |= ((mask & reglist) << i);
1257 	    mask >>= 1;
1258 	}
1259 	reglist = list;
1260     }
1261     if (printing) {
1262 	printf("\tmovem%c\t",(inst&100)?'l':'w');
1263     }
1264     if (inst&02000) {
1265 	printEA(inst);
1266 	if (printing) {
1267 	    printf(",");
1268 	}
1269 	pregmask(reglist);
1270     } else {
1271 	pregmask(reglist);
1272 	if (printing) {
1273 	    printf(",");
1274 	}
1275 	printEA(inst);
1276     }
1277 }
1278 
1279 public ochk(inst, opcode)
1280 long inst;
1281 register String opcode;
1282 {
1283     if (printing) {
1284 	printf("\t%s\t", opcode);
1285     }
1286     printEA(inst, sizeof(Byte));
1287     if (printing) {
1288 	printf(",%c%D", (opcode[0] == 'l') ? 'a' : 'd', (inst>>9)&07);
1289     }
1290 }
1291 
1292 public soneop(inst, opcode)
1293 long inst;
1294 register String opcode;
1295 {
1296     register int size;
1297 
1298     size = mapsize(inst);
1299     if (size > 0) {
1300 	if (printing) {
1301 	    printf("\t%s%c\t", opcode, suffix(size));
1302 	}
1303 	printEA(inst);
1304     } else {
1305 	if (printing) {
1306 	    printf("\tbadop");
1307 	}
1308     }
1309 }
1310 
1311 public oquick(inst, opcode)
1312 long inst;
1313 register String opcode;
1314 {
1315     register int size;
1316     register int data;
1317 
1318     size = mapsize(inst);
1319     data = (int)((inst>>9) & 07);
1320     if (data == 0) {
1321 	data = 8;
1322     }
1323     if (size > 0) {
1324 	if (printing) {
1325 	    printf("\t%s%c\t", opcode, suffix(size));
1326 	    printf(IMDF, data);
1327 	    printf(",");
1328 	}
1329 	printEA(inst);
1330     } else {
1331 	if (printing) {
1332 	    printf("\tbadop");
1333 	}
1334     }
1335 }
1336 
1337 public omoveq(inst, dummy)
1338 long inst;
1339 long dummy;
1340 {
1341     register int data;
1342 
1343     if (printing) {
1344 	data = (int)(inst & 0377);
1345 	if (data > 127) {
1346 	    data |= ~0377;
1347 	}
1348 	printf("\tmoveq\t");
1349 	printf(IMDF, data);
1350 	printf(",d%D", (inst>>9)&07);
1351     }
1352 }
1353 
1354 public oprint(inst, opcode)
1355 long inst;
1356 register String opcode;
1357 {
1358     if (printing) {
1359 	printf("\t%s",opcode);
1360     }
1361 }
1362 
1363 public ostop(inst, opcode)
1364 long inst;
1365 register String opcode;
1366 {
1367     short w;
1368 
1369     instread(w);
1370     if (printing) {
1371 	printf(opcode, w);
1372     }
1373 }
1374 
1375 public orts(inst, opcode)
1376 long inst;
1377 register String opcode;
1378 {
1379     Address addr;
1380 
1381     if (following) {
1382 	callnews(/* iscall = */ false);
1383     	if (inst_tracing) {
1384 	    addr = currtnaddr();
1385     	} else {
1386 	    addr = return_addr();
1387 	    if (addr == 0) {
1388 		stepto(instaddr - 2);
1389 		addr = currtnaddr();
1390 	    }
1391 	}
1392 	stepto(addr);
1393 	instaddr = pc;
1394     }
1395     if (printing) {
1396 	printf("\t%s",opcode);
1397     }
1398 }
1399 
1400 /*
1401  * Not used by C compiler; does an rts but before doing so, pops
1402  * arg bytes from the stack.
1403  */
1404 
1405 public ortspop(inst, opcode)
1406 long inst;
1407 register String opcode;
1408 {
1409     Address addr;
1410     short w;
1411 
1412     instread(w);
1413     if (following) {
1414 	callnews(/* iscall = */ false);
1415     	if (inst_tracing) {
1416 	    addr = currtnaddr();
1417     	} else {
1418 	    addr = return_addr();
1419 	}
1420 	stepto(addr);
1421 	instaddr = pc;
1422     }
1423     if (printing) {
1424 	printf(opcode, w);
1425     }
1426 }
1427 
1428 public omovs(inst, opcode)
1429 long inst;
1430 String opcode;
1431 {
1432     register int size;
1433     register unsigned int controlword;
1434     short w;
1435 
1436     size = mapsize(inst);
1437     instread(w);
1438     controlword = w >> 11;
1439     if (printing) {
1440 	printf("\t%s%c\t", opcode, suffix(size));
1441     }
1442     if (controlword & 1){
1443 	controlword >>= 1;
1444 	if (printing) {
1445 	    printf((controlword&0x8) ? "a%D," : "d%D,", controlword&7 );
1446 	}
1447 	printEA(inst&0xff, size);
1448     } else {
1449 	controlword >>= 1;
1450 	printEA(inst&0xff, size);
1451 	if (printing) {
1452 	    printf((controlword&0x8) ? ",a%D" : ",d%D", controlword&7);
1453 	}
1454     }
1455 }
1456 
1457 public omovc(inst, opcode)
1458 long inst;
1459 String opcode;
1460 {
1461     register unsigned int controlword;
1462     String creg;
1463     short w;
1464 
1465     instread(w);
1466     if (printing) {
1467 	controlword = w;
1468 	switch (controlword & 0xfff) {
1469 	    case 0:
1470 		creg = "sfc";
1471 		break;
1472 
1473 	    case 1:
1474 		creg = "dfc";
1475 		break;
1476 
1477 	    case 0x800:
1478 		creg = "usp";
1479 		break;
1480 
1481 	    case 0x801:
1482 		creg = "vbr";
1483 		break;
1484 
1485 	    default:
1486 		creg = "???";
1487 		break;
1488 	}
1489 	controlword >>= 12;
1490 	if (inst & 1){
1491 	    printf((controlword&0x8) ? "%sa%D,%s" : "%sd%D,%s",
1492 		opcode, controlword&7, creg );
1493 	} else {
1494 	    printf((controlword&0x8) ? "%s%s,a%D" : "%s%s,d%D",
1495 		opcode, creg, controlword&7 );
1496 	}
1497     }
1498 }
1499 
1500 /*
1501  * Compute the next address that will be executed from the given one.
1502  * If "isnext" is true then consider a procedure call as straight line code.
1503  *
1504  * Unconditional branches we just follow, for conditional branches
1505  * we continue execution to the current location and then single step
1506  * the machine.
1507  */
1508 
1509 public Address nextaddr(startaddr, isnext)
1510 Address startaddr;
1511 Boolean isnext;
1512 {
1513     Optab *o;
1514     short inst;
1515 
1516     instaddr = usignal(process);
1517     if (instaddr == 0 or instaddr == 1) {
1518 	following = true;
1519 	followcalls = (Boolean) (not isnext);
1520 	printing = false;
1521 	iread(&inst, startaddr, sizeof(inst));
1522 	instaddr = startaddr + sizeof(inst);
1523 	o = decode(inst, startaddr);
1524 	if (o->mask == 0) {
1525 	    fprintf(stderr,
1526 		"[internal error: undecodable op at 0x%x]\n", startaddr);
1527 	    fflush(stderr);
1528 	} else {
1529 	    (*o->opfun)(inst, o->farg);
1530 	}
1531 	following = false;
1532     }
1533     return instaddr;
1534 }
1535 
1536 /*
1537  * Step to the given address and then execute one instruction past it.
1538  * Set instaddr to the new instruction address.
1539  */
1540 
1541 private steppast(addr)
1542 Address addr;
1543 {
1544     stepto(addr);
1545     pstep(process, DEFSIG);
1546     pc = reg(PROGCTR);
1547     instaddr = pc;
1548 }
1549 
1550 /*
1551  * Enter a procedure by creating and executing a call instruction.
1552  */
1553 
1554 #define CALLSIZE 6	/* size of call instruction */
1555 
1556 public beginproc(p)
1557 Symbol p;
1558 {
1559     char save[CALLSIZE];
1560     struct {
1561 	short op;
1562 	char addr[sizeof(long)];	/* unaligned long */
1563     } call;
1564     long dest;
1565 
1566     pc = CODESTART + 6;
1567     iread(save, pc, sizeof(save));
1568     call.op = 0x4eb9;			/* jsr */
1569     dest = codeloc(p) - FUNCOFFSET;
1570     mov(&dest, call.addr, sizeof(call.addr));
1571     iwrite(&call, pc, sizeof(call));
1572     setreg(PROGCTR, pc);
1573     pstep(process, DEFSIG);
1574     iwrite(save, pc, sizeof(save));
1575     pc = reg(PROGCTR);
1576     if (not isbperr()) {
1577 	printstatus();
1578     }
1579     /*
1580      * Execute link instruction so the return addr is visible.
1581      */
1582     pstep(process, DEFSIG);
1583     pc = reg(PROGCTR);
1584     if (not isbperr()) {
1585 	printstatus();
1586     }
1587 }
1588 
1589 /*
1590  * Special variables for debugging the kernel.
1591  */
1592 
1593 public integer masterpcbb;
1594 public integer slr;
1595 public struct pte *sbr;
1596 private struct pcb pcb;
1597 
1598 public getpcb ()
1599 {
1600     integer i;
1601 
1602     fseek(corefile, masterpcbb & ~0x80000000, 0);
1603     get(corefile, pcb);
1604     pcb.pcb_p0lr &= ~AST_CLR;
1605     printf("p0br %lx p0lr %lx p1br %lx p1lr %lx\n",
1606 	pcb.pcb_p0br, pcb.pcb_p0lr, pcb.pcb_p1br, pcb.pcb_p1lr
1607     );
1608 #   ifdef sun
1609     for (i = 0; i < 14; i++) {
1610 	setreg(i, pcb.pcb_regs.val[i]);
1611     }
1612 #   else /* IRIS */
1613     for (i = 0; i < 14; i++) {
1614 	setreg(i, pcb.pcb_regs[i]);
1615     }
1616 #   endif
1617 }
1618 
1619 public copyregs (savreg, reg)
1620 Word savreg[], reg[];
1621 {
1622     reg[0] = savreg[R0];
1623     reg[1] = savreg[R1];
1624     reg[2] = savreg[R2];
1625     reg[3] = savreg[R3];
1626     reg[4] = savreg[R4];
1627     reg[5] = savreg[R5];
1628     reg[6] = savreg[R6];
1629     reg[7] = savreg[R7];
1630     reg[8] = savreg[AR0];
1631     reg[9] = savreg[AR1];
1632     reg[10] = savreg[AR2];
1633     reg[11] = savreg[AR3];
1634     reg[12] = savreg[AR4];
1635     reg[13] = savreg[AR5];
1636     reg[14] = savreg[AR6];
1637     reg[15] = savreg[AR7];
1638     reg[PROGCTR] = savreg[PC];
1639 }
1640 
1641 /*
1642  * Map a virtual address to a physical address.
1643  * XXX THIS CAN'T BE RIGHT... XXX
1644  */
1645 
1646 public Address vmap (addr)
1647 Address addr;
1648 {
1649     Address r;
1650     integer v, n;
1651     struct pte pte;
1652 
1653     r = addr & ~0xc0000000;
1654     v = btop(r);
1655     switch (addr&0xc0000000) {
1656 	case 0xc0000000:
1657 	case 0x80000000:
1658 	    /*
1659 	     * In system space, so get system pte.
1660 	     * If it is valid or reclaimable then the physical address
1661 	     * is the combination of its page number and the page offset
1662 	     * of the original address.
1663 	     */
1664 	    if (v >= slr) {
1665 		error("address %x out of segment", addr);
1666 	    }
1667 	    r = ((long) (sbr + v)) & ~0x80000000;
1668 	    goto simple;
1669 
1670 	case 0x40000000:
1671 	    /*
1672 	     * In p1 space, must not be in shadow region.
1673 	     */
1674 	    if (v < pcb.pcb_p1lr) {
1675 		error("address %x out of segment", addr);
1676 	    }
1677 	    r = (Address) (pcb.pcb_p1br + v);
1678 	    break;
1679 
1680 	case 0x00000000:
1681 	    /*
1682 	     * In p0 space, must not be off end of region.
1683 	     */
1684 	    if (v >= pcb.pcb_p0lr) {
1685 		error("address %x out of segment", addr);
1686 	    }
1687 	    r = (Address) (pcb.pcb_p0br + v);
1688 	    break;
1689 
1690 	default:
1691 	    /* do nothing */
1692 	    break;
1693     }
1694     /*
1695      * For p0/p1 address, user-level page table should be in
1696      * kernel virtual memory.  Do second-level indirect by recursing.
1697      */
1698     if ((r & 0x80000000) == 0) {
1699 	error("bad p0br or p1br in pcb");
1700     }
1701     r = vmap(r);
1702 simple:
1703     /*
1704      * "r" is now the address of the pte of the page
1705      * we are interested in; get the pte and paste up the physical address.
1706      */
1707     fseek(corefile, r, 0);
1708     n = fread(&pte, sizeof(pte), 1, corefile);
1709     if (n != 1) {
1710 	error("page table botch (fread at %x returns %d)", r, n);
1711     }
1712     if (pte.pg_v == 0 and (pte.pg_fod != 0 or pte.pg_pfnum == 0)) {
1713 	error("page no valid or reclamable");
1714     }
1715     return (addr&PGOFSET) + ((Address) ptob(pte.pg_pfnum));
1716 }
1717 
1718 /*
1719  * Extract a bit field from an integer.
1720  */
1721 
1722 public integer extractField (s)
1723 Symbol s;
1724 {
1725     integer nbytes, nbits, n, r, off, len;
1726 
1727     off = s->symvalue.field.offset;
1728     len = s->symvalue.field.length;
1729     nbytes = size(s);
1730     n = 0;
1731     if (nbytes > sizeof(n)) {
1732 	printf("[bad size in extractField -- word assumed]\n");
1733 	nbytes = sizeof(n);
1734     }
1735     popn(nbytes, ((char *) &n) + (sizeof(Word) - nbytes));
1736     nbits = nbytes * BITSPERBYTE;
1737     r = n >> (nbits - ((off mod nbits) + len));
1738     r &= ((1 << len) - 1);
1739     return r;
1740 }
1741 
1742 /*
1743  * Change the length of a value in memory according to a given difference
1744  * in the lengths of its new and old types.
1745  */
1746 
1747 public loophole (oldlen, newlen)
1748 integer oldlen, newlen;
1749 {
1750     integer i, n;
1751     Stack *oldsp;
1752 
1753     n = newlen - oldlen;
1754     oldsp = sp - oldlen;
1755     if (n > 0) {
1756 	for (i = oldlen - 1; i >= 0; i--) {
1757 	    oldsp[n + i] = oldsp[i];
1758 	}
1759 	for (i = 0; i < n; i++) {
1760 	    oldsp[i] = '\0';
1761 	}
1762     } else {
1763 	for (i = 0; i < newlen; i++) {
1764 	    oldsp[i] = oldsp[i - n];
1765 	}
1766     }
1767     sp += n;
1768 }
1769