date and time created 90/06/25 15:38:16 by bostic
[unix-history] / usr / src / old / dbx / iris.c
CommitLineData
0674773e 1/*
8a90f3aa
KB
2 * Copyright (c) 1983 The Regents of the University of California.
3 * All rights reserved.
4 *
6ecf3d85 5 * %sccs.include.redist.c%
0674773e
DS
6 */
7
8#ifndef lint
6ecf3d85 9static char sccsid[] = "@(#)iris.c 5.3 (Berkeley) %G%";
8a90f3aa 10#endif /* not lint */
0674773e
DS
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
32typedef unsigned int Address;
33typedef unsigned char Byte;
34typedef 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
87Address pc;
88Address prtaddr;
89
90#endif
91
92/*
93 * Indices into u. for use in collecting registers values.
94 */
95public 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
103private Address printop();
104
105/*
106 * Decode and print the instructions within the given address range.
107 */
108
109public printinst(lowaddr, highaddr)
110Address lowaddr;
111Address 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
125public printninst(count, addr)
126int count;
127Address 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
148typedef struct {
149 String name;
150 String printfstring;
151 int length;
152} Format;
153
154private 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
169private Format *findformat(s)
170String 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
190private printformat (f, addr)
191Format *f;
192Address 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
211public Address printdata(lowaddr, highaddr, format)
212Address lowaddr;
213Address highaddr;
214String 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
247public printndata(count, startaddr, format)
248int count;
249Address startaddr;
250String 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
300public printvalue(v, format)
301long v;
302String 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
331public 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
366private String illinames[] = {
367 "reserved addressing fault",
368 "privileged instruction fault",
369 "reserved operand fault"
370};
371
372private 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
386public printsig (signo)
387integer 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
415public 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
436private Address getcall();
437
438public dostep(isnext)
439Boolean 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
463typedef short Bpinst;
464
465extern 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
481typedef struct Savelist *Savelist;
482
483struct Savelist {
484 Address location;
485 Bpinst save;
486 short refcount;
487 Savelist link;
488};
489
490private 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
497public setbp(addr)
498Address 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
526public unsetbp(addr)
527Address 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
559private Boolean printing;
560private Boolean following;
561private Boolean followcalls;
562private Address instaddr;
563
564#define instread(var) \
565{ \
566 iread(&var, instaddr, sizeof(var)); \
567 instaddr += sizeof(var); \
568}
569
570private Optab *decode(inst, addr)
571Word inst;
572Address 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
583private Address printop(addr)
584Address 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
611private 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
623private printea(mode, reg, size)
624long mode, reg;
625int 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
765private printEA(ea, size)
766long ea;
767int size;
768{
769 printea((ea>>3)&07, ea&07, size);
770}
771
772private mapsize(inst)
773register 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
799private char suffix(size)
800int 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
828private psymoff (off)
829Word 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
845public omove(inst, s)
846long inst;
847String 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
868public obranch(inst, dummy)
869long 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
935public odbcc(inst, form)
936long inst;
937String 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
949public oscc(inst, dummy)
950long inst;
951long 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
959public biti(inst, dummy)
960long inst;
961long 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
982public opmode(inst, opcode)
983long inst;
984long 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
1015public shroi(inst, ds)
1016long inst;
1017String 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
1043public oimmed(inst, opcode)
1044long inst;
1045register 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
1072public oreg(inst, opcode)
1073long inst;
1074register String opcode;
1075{
1076 if (printing) {
1077 printf(opcode, (inst & 07));
1078 }
1079}
1080
1081public extend(inst, opcode)
1082long inst;
1083String 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
1113public olink(inst, dummy)
1114long inst;
1115long 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
1126public otrap(inst, dummy)
1127long inst;
1128{
1129 if (printing) {
1130 printf("\ttrap\t");
1131 printf(IMDF, inst&017);
1132 }
1133}
1134
1135public oneop(inst, opcode)
1136long inst;
1137register String opcode;
1138{
1139 if (printing) {
1140 printf("\t%s",opcode);
1141 }
1142 printEA(inst);
1143}
1144
1145public jsrop(inst, opcode)
1146long inst;
1147register 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
1198public jmpop(inst, opcode)
1199long inst;
1200register 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
1214public pregmask(mask)
1215register 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
1237public omovem(inst, dummy)
1238long inst;
1239long 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
1279public ochk(inst, opcode)
1280long inst;
1281register 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
1292public soneop(inst, opcode)
1293long inst;
1294register 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
1311public oquick(inst, opcode)
1312long inst;
1313register 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
1337public omoveq(inst, dummy)
1338long inst;
1339long 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
1354public oprint(inst, opcode)
1355long inst;
1356register String opcode;
1357{
1358 if (printing) {
1359 printf("\t%s",opcode);
1360 }
1361}
1362
1363public ostop(inst, opcode)
1364long inst;
1365register String opcode;
1366{
1367 short w;
1368
1369 instread(w);
1370 if (printing) {
1371 printf(opcode, w);
1372 }
1373}
1374
1375public orts(inst, opcode)
1376long inst;
1377register 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
1405public ortspop(inst, opcode)
1406long inst;
1407register 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
1428public omovs(inst, opcode)
1429long inst;
1430String 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
1457public omovc(inst, opcode)
1458long inst;
1459String 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
1509public Address nextaddr(startaddr, isnext)
1510Address startaddr;
1511Boolean 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
1541private steppast(addr)
1542Address 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
1556public beginproc(p)
1557Symbol 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
1593public integer masterpcbb;
1594public integer slr;
1595public struct pte *sbr;
1596private struct pcb pcb;
1597
1598public 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
1619public copyregs (savreg, reg)
1620Word 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
1646public Address vmap (addr)
1647Address 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);
1702simple:
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
1722public integer extractField (s)
1723Symbol 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
1747public loophole (oldlen, newlen)
1748integer 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}