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