1 /*-
2 * Copyright (c) 1991 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * %sccs.include.proprietary.c%
6 */
7
8 #ifndef lint
9 static char sccsid[] = "@(#)opset.c 5.1 (Berkeley) 04/04/91";
10 #endif /* not lint */
11
12 /*
13 * adb - instruction decoding
14 */
15
16 #include "defs.h"
17 #include "optab.h"
18
19 struct optab *ioptab[256]; /* index by opcode to optab */
20
21 /* set up ioptab */
mkioptab()22 mkioptab()
23 {
24 register struct optab *p;
25
26 for (p = optab; p->iname; p++)
27 ioptab[p->val] = p;
28 }
29
30 /*
31 * Print one instruction, and leave dotinc set to the number of bytes
32 * it occupied.
33 */
printins(space)34 printins(space)
35 int space;
36 {
37 u_char ins; /* instruction opcode */
38 int argno; /* argument index */
39 register int mode; /* mode */
40 register int r; /* register name */
41 register int d; /* assembled byte, word, long or float */
42 register int dotoff; /* offset from dot of current byte */
43 register u_char *ap;
44 register struct optab *ip;
45 union {
46 u_char ub;
47 char b;
48 short w;
49 int l;
50 } mem;
51 extern char *syscalls[];
52 extern int nsys;
53 #define snarfbytes(nbytes) \
54 (void) adbread(space, inkdot(dotoff), &mem.b, nbytes); \
55 checkerr(); \
56 dotoff += (nbytes)
57
58 if (space == SP_NONE)
59 ins = (u_char)dot;
60 else {
61 (void) adbread(space, dot, &ins, 1);
62 checkerr();
63 }
64 if ((ip = ioptab[ins]) == NULL) {
65 adbprintf("?%2x", ins);
66 dotinc = 1;
67 return;
68 }
69 adbprintf("%s%8t", ip->iname);
70 dotoff = 1;
71 ap = ip->argtype;
72 for (argno = 0; argno < ip->nargs; argno++, ap++) {
73 var[argno] = 0x80000000;
74 if (argno != 0)
75 printc(',');
76 again:
77 if (*ap & ACCB) /* branch displacement */
78 mode = 0xAF + ((*ap & 7) << 5);
79 else {
80 snarfbytes(1);
81 mode = mem.ub;
82 }
83 r = mode & 0xF;
84 mode >>= 4;
85 switch (mode) {
86
87 case 0: case 1: case 2: case 3:
88 /* short literal */
89 d = mode << 4 | r;
90 goto immed;
91
92 case 4: /* [r] */
93 adbprintf("[%s]", regname[r]);
94 goto again;
95
96 case 5: /* r */
97 adbprintf("%s", regname[r]);
98 continue;
99
100 case 6: /* (r) */
101 adbprintf("(%s)", regname[r]);
102 continue;
103
104 case 7: /* -(r) */
105 adbprintf("-(%s)", regname[r]);
106 continue;
107
108 case 9: /* *(r)+ */
109 printc('*');
110 /* FALLTHROUGH */
111
112 case 8: /* (r)+ */
113 if (r == 0xf) {
114 /* PC immediate */
115 snarfbytes(4);
116 d = mem.l;
117 } else if (mode == 8 && (r == 8 || r == 9)) {
118 /* absolute */
119 snarfbytes((r & 1) + 1);
120 d = r == 8 ? mem.b : mem.w;
121 } else {
122 adbprintf("(%s)+", regname[r]);
123 continue;
124 }
125 immed:
126 printc('$');
127 if (ins == KCALL && (u_int)d < nsys && syscalls[d])
128 prints(syscalls[d]);
129 else
130 adbprintf("%R", d);
131 var[argno] = d;
132 continue;
133
134 case 0xA: /* byte displacement */
135 case 0xB: /* byte displacement deferred */
136 d = 1;
137 break;
138
139 case 0xC: /* word displacement */
140 case 0xD: /* word displacement deferred */
141 d = 2;
142 break;
143
144 case 0xE: /* long displacement */
145 case 0xF: /* long displacement deferred */
146 d = 4;
147 break;
148 }
149
150 /* displacement or displacement deferred */
151 if (mode & 1)
152 printc('*');
153 snarfbytes(d);
154 switch (d) {
155 case 1:
156 d = mem.b;
157 break;
158 case 2:
159 d = mem.w;
160 break;
161 case 4:
162 d = mem.l;
163 break;
164 }
165 if (r == 0xF) { /* PC offset addressing */
166 d += dot + dotoff;
167 psymoff("%R", (addr_t)d, SP_DATA, maxoff, "");
168 } else
169 adbprintf("%V(%s)", d, regname[r]);
170 var[argno] = d;
171 }
172 if (ins == CASEL) {
173 register addr_t adjdot;
174
175 if (inkdot(dotoff) & 01) /* align */
176 dotoff++;
177 adjdot = inkdot(dotoff);
178 for (argno = 0; argno <= var[2]; ++argno) {
179 adbprintf("\n %R: ", argno + var[1]);
180 snarfbytes(2);
181 psymoff("%R", adjdot + mem.w, SP_DATA, maxoff, "");
182 }
183 }
184 dotinc = dotoff;
185 }
186