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