|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)opset.c 4.8 (Berkeley) 1/16/89";
3: #endif
4:
5: /*
6: * adb - instruction printing routines: VAX version
7: */
8:
9: #include "defs.h"
10:
11: /*
12: * Get assembler definitions; declare tables that appear in optab.c.
13: */
14: #define ADB
15: #undef INSTTAB
16: #include "instrs.h"
17:
18: extern struct insttab insttab[];
19: extern char *regname[];
20: extern char *fltimm[];
21:
22: /* these are shared with the assembler: */
23: extern int ty_NORELOC[];
24: extern int ty_nbyte[];
25: #ifdef notyet
26: extern int ty_float[]; /* must update assizetab.c */
27: #endif
28:
29: /*
30: * Definitions for registers and for operand classes.
31: */
32: #define R_PC 0xF
33:
34: #define OC_IMM0 0x0 /* literal, aka immediate */
35: #define OC_IMM1 0x1
36: #define OC_IMM2 0x2
37: #define OC_IMM3 0x3
38: #define OC_INDEX 0x4 /* [rN] */
39: #define OC_REG 0x5 /* rN */
40: #define OC_DREG 0x6 /* (rN) */
41: #define OC_ADREG 0x7 /* -(rN) */
42: #define OC_AIREG 0x8 /* (rN)+ */
43: #define OC_DAIREG 0x9 /* *(rN)+ */
44: #define OC_BDISP 0xA /* b(rN) */
45: #define OC_DBDISP 0xB /* *b(rN) */
46: #define OC_WDISP 0xC /* w(rN) */
47: #define OC_DWDISP 0xD /* *w(rN) */
48: #define OC_LDISP 0xE /* l(rN) */
49: #define OC_DLDISP 0xF /* *l(rN) */
50:
51: #define OC_SHIFT 4
52: #define OC_CONS(oc,reg) (((oc & 0xF) << OC_SHIFT) | (reg & 0xF))
53: #define OC_AMEXT(x) (((x) >> OC_SHIFT) & 0xF)
54: #define OC_REGEXT(x) ((x) & 0xF)
55:
56: /*
57: * Definitions for special instructions.
58: */
59: #define CASEB 0x8F
60: #define CASEW 0xAF
61: #define CASEL 0xCF
62: #define CHMK 0xBC
63:
64: /*
65: * ioptab is a two level 1-based index by opcode into insttab.
66: * The first level into ioptab is given by mapescbyte().
67: * Since ioptab is 1-based, references would be expected to
68: * be of the form
69: *
70: * ptr = &insttab[ioptab[a][b] - 1];
71: *
72: * but the form
73: *
74: * ptr = &(insttab - 1)[ioptab[a][b]]
75: *
76: * is equivalent and generates less code (!) (time to work on the
77: * compiler again...).
78: */
79: static short ioptab[3][256];
80: #define mapescbyte(b) ((b) == ESCD ? 1 : (b) == ESCF ? 2 : 0)
81:
82: mkioptab()
83: {
84: register struct insttab *p;
85: register int mapchar;
86: register short *iop;
87:
88: /*
89: * The idea here is that whenever two opcodes have the same
90: * codes, but different mnemonics, we want to prefer the one
91: * with the `simpler' type. Here lower numbers make simpler
92: * types. This seems (likely) to work reasonably well.
93: *
94: * At present, this affects the following opcodes:
95: *
96: * 7c clrq | clrd | clrg
97: * 7e movaq | movad | movag
98: * 7f pushaq | pushad | pushag
99: * d4 clrl | clrf
100: * de moval | movaf
101: * df pushal | pushaf
102: *
103: * In each case, the leftmost mnemonics are preferred.
104: */
105: #define PREFER(a, b) (A_TYPEXT((a)->argtype[0]) < A_TYPEXT((b)->argtype[0]))
106:
107: for (p = insttab; p->iname != NULL; p++) {
108: mapchar = mapescbyte(p->eopcode);
109: iop = &ioptab[mapchar][p->popcode];
110: if (*iop == 0 || PREFER(p, &(insttab - 1)[*iop]))
111: *iop = p - (insttab - 1);
112: }
113: #undef PREFER
114: }
115:
116: /*
117: * Global variables for communication between the minions and printins.
118: */
119: static int idsp; /* which space we are in (INSTR or DATA) */
120: static int argno; /* which argument we are working on */
121: static int dotoff; /* offset from dot for this arg */
122: static int vset[7]; /* set by savevar, cleared by clrvar */
123:
124: #define savevar(v) (vset[argno] = 1, var[argno] = v)
125: #define clrvar(v) (vset[argno] = 0, var[argno] = 0x80000000)
126:
127: /*
128: * Read some bytes, checking for errors, and updating the offset.
129: */
130: #define getsomebytes(ptr, nbytes) \
131: (void) adbread(idsp, inkdot(dotoff), ptr, nbytes); \
132: checkerr(); \
133: dotoff += (nbytes)
134:
135: /*
136: * Read one byte, and advance the offset.
137: */
138: static int
139: getbyte()
140: {
141: u_char c;
142:
143: getsomebytes(&c, sizeof(c));
144: return (c);
145: }
146:
147: /*
148: * adb's view: printins() prints one instruction, and sets dotinc.
149: */
150: printins(space)
151: int space;
152: {
153: register u_char *ap;
154: register struct insttab *ip;
155: int ins, mode, optype, mapchar, t;
156: char *lastix, *ixreg;
157: char *operandout();
158:
159: /*
160: * Set up the module variables, pick up the instruction, and
161: * find its table entry.
162: */
163: idsp = space;
164: dotoff = 0;
165: ins = idsp == SP_NONE ? (u_char)dot : getbyte();
166: if ((mapchar = mapescbyte(ins)) != 0) {
167: t = getbyte();
168: if (ioptab[mapchar][t] == 0) {
169: /*
170: * Oops; not a defined instruction; back over this
171: * escape byte.
172: */
173: dotoff--;
174: mapchar = 0;
175: } else
176: ins = t;
177: }
178: if ((t = ioptab[mapchar][ins]) == 0) {
179: adbprintf("<undefined operator byte>: %x", ins);
180: dotinc = 1;
181: return;
182: }
183: ip = &(insttab - 1)[t];
184: adbprintf("%s%8t", ip->iname);
185:
186: /*
187: * For each argument, decode that argument.
188: * We set t if we notice something fishy.
189: */
190: t = 0;
191: for (ap = ip->argtype, argno = 0; argno < ip->nargs; argno++) {
192: optype = *ap++;
193: clrvar();
194: if (argno != 0)
195: printc(',');
196: /*
197: * lastix and ixreg track the register indexed addressing
198: * mode, which is written as <stuff>[reg] but encoded as
199: * [reg]<stuff>. Only one [reg] is legal.
200: */
201: lastix = NULL;
202: do {
203: /* check for special pc-relative (branch) */
204: if (A_ACCEXT(optype) & ACCB) {
205: switch (A_TYPEXT(optype)) {
206: case TYPB:
207: mode = OC_CONS(OC_BDISP, R_PC);
208: break;
209: case TYPW:
210: mode = OC_CONS(OC_WDISP, R_PC);
211: break;
212: }
213: } else
214: mode = getbyte();
215: ixreg = operandout(mode, optype, ins == CHMK);
216: if (lastix) {
217: adbprintf("[%s]", lastix);
218: if (ixreg)
219: t = 1;
220: }
221: } while ((lastix = ixreg) != NULL);
222: }
223: if (t)
224: adbprintf("%4t# not code? illegal arguments detected ");
225: switch (ins) {
226: case CASEB:
227: case CASEW:
228: case CASEL:
229: if (mapchar == 0 && vset[1] && vset[2])
230: casebody(var[1], var[2]);
231: else
232: adbprintf("\n%4t# not code? non-constant cases ");
233: }
234: dotinc = dotoff;
235: }
236:
237: /*
238: * Print out the locations to which each of the cases branch.
239: * This routine carefully allows expressions such as
240: *
241: * casel <val>,$<const>,$0x7fffffff
242: *
243: * even though they do not fit on a VAX.
244: */
245: static
246: casebody(base, limit)
247: register expr_t base, limit;
248: {
249: register expr_t i = -1;
250: register addr_t a, baseaddr = inkdot(dotoff);
251: short displ;
252:
253: argno = 0;
254: do {
255: i++;
256: adbprintf("\n %R: ", base++);
257: getsomebytes(&displ, sizeof(displ));
258: a = displ + baseaddr;
259: psymoff("%R", a, SP_DATA, maxoff, "");
260: savevar(a);
261: } while (i != limit);
262: }
263:
264: /*
265: * Handle a normal operand. Return pointer to register
266: * name if this is an index instruction, else return NULL.
267: */
268: static char *
269: operandout(mode, optype, ischmk)
270: register int mode;
271: int optype, ischmk;
272: {
273: register char *r;
274: register int regnumber, nbytes, n;
275: union {
276: char b;
277: short w;
278: int l;
279: } displ;
280: extern char *syscalls[];
281: extern int nsys;
282:
283: regnumber = OC_REGEXT(mode);
284: r = regname[regnumber];
285: switch (OC_AMEXT(mode)) {
286:
287: case OC_IMM0: case OC_IMM1:
288: case OC_IMM2: case OC_IMM3:
289: savevar(mode);
290: printc('$');
291: #ifdef notyet
292: if (ty_float[A_TYPEXT(optype)])
293: prints(fltimm[mode]);
294: else if (ischmk && (u_int)mode < nsys && syscalls[mode])
295: prints(syscalls[mode]);
296: else
297: adbprintf("%V", mode);
298: #else
299: switch (A_TYPEXT(optype)) {
300:
301: case TYPF:
302: case TYPD:
303: case TYPG:
304: case TYPH:
305: prints(fltimm[mode]);
306: break;
307:
308: default:
309: if (ischmk && (u_int)mode < nsys && syscalls[mode])
310: prints(syscalls[mode]);
311: else
312: adbprintf("%V", mode);
313: break;
314: }
315: #endif
316: return (0);
317:
318: case OC_INDEX:
319: return (r); /* will be printed later */
320:
321: case OC_REG:
322: adbprintf("%s", r);
323: return (0);
324:
325: case OC_DREG:
326: adbprintf("(%s)", r);
327: return (0);
328:
329: case OC_ADREG:
330: adbprintf("-(%s)", r);
331: return (0);
332:
333: case OC_DAIREG:
334: printc('*');
335: /* FALLTHROUGH */
336:
337: case OC_AIREG:
338: if (regnumber != R_PC) {
339: adbprintf("(%s)+", r);
340: return (0);
341: }
342: /* PC immediate */
343: printc('$');
344: if (mode == OC_CONS(OC_DAIREG, R_PC))
345: /* PC absolute, always 4 bytes */
346: nbytes = 4;
347: else {
348: nbytes = ty_nbyte[A_TYPEXT(optype)];
349: if (ty_NORELOC[A_TYPEXT(optype)]) {
350: bignumprint(nbytes, optype);
351: return (0);
352: }
353: }
354: break;
355:
356: case OC_DBDISP:
357: printc('*');
358: /* FALLTHROUGH */
359:
360: case OC_BDISP:
361: nbytes = 1;
362: break;
363:
364: case OC_DWDISP:
365: printc('*');
366: /* FALLTHROUGH */
367:
368: case OC_WDISP:
369: nbytes = 2;
370: break;
371:
372: case OC_DLDISP:
373: printc('*');
374: /* FALLTHROUGH */
375:
376: case OC_LDISP:
377: nbytes = 4;
378: break;
379:
380: default:
381: panic("operandout 1");
382: /* NOTREACHED */
383: }
384:
385: /*
386: * Print a displacement format.
387: */
388: getsomebytes(&displ, nbytes);
389: switch (nbytes) {
390: case 1:
391: n = displ.b;
392: break;
393: case 2:
394: n = displ.w;
395: break;
396: case 4:
397: n = displ.l;
398: break;
399: default:
400: panic("operandout 2");
401: /* NOTREACHED */
402: }
403: if (regnumber == R_PC) {
404: switch (OC_AMEXT(mode)) {
405:
406: case OC_DAIREG:
407: if (ischmk && (u_int)n < nsys && syscalls[n]) {
408: prints(syscalls[n]);
409: return (0);
410: }
411: break;
412:
413: case OC_BDISP: case OC_DBDISP:
414: case OC_WDISP: case OC_DWDISP:
415: case OC_LDISP: case OC_DLDISP:
416: /* PC offset */
417: n += dot + dotoff;
418: }
419: psymoff("%V", (addr_t)n, SP_DATA, maxoff, "");
420: } else
421: adbprintf("%V(%s)", (expr_t)n, regname[regnumber]);
422: savevar(n);
423: return (0);
424: }
425:
426: /*
427: * Print an F-float, D-float, G-float, H-float, quadword, or octaword.
428: * F- and D-floating values are printed as themselves, unless they are
429: * reserved operand bit patterns; these, and the others, are printed
430: * instead in hex, with leading zeroes suppressed.
431: */
432: static
433: bignumprint(nbytes, optype)
434: int nbytes, optype;
435: {
436: register char *p;
437: register int i;
438: union {
439: float f; /* if f-floating */
440: double d; /* if d-floating */
441: u_char c[16]; /* if G, H, Q, or O */
442: } n;
443: char expbuf[4*8+1]; /* max 4 8-character hex ints */
444: static char tohex[] = "0123456789abcdef";
445:
446: /*
447: * Read in the number, then figure out how to print it.
448: */
449: getsomebytes(&n, nbytes);
450: switch (A_TYPEXT(optype)) {
451:
452: case TYPF:
453: if ((p = checkfloat((caddr_t)&n.f, 0)) == NULL) {
454: adbprintf("0f%f", n.f);
455: return;
456: }
457: adbprintf("%s 0f::", p);
458: break;
459:
460: case TYPD:
461: if ((p = checkfloat((caddr_t)&n.d, 1)) == NULL) {
462: adbprintf("0d%f", n.d);
463: return;
464: }
465: adbprintf("%s 0d::", p);
466: break;
467:
468: case TYPG:
469: adbprintf("0g::");
470: break;
471:
472: case TYPH:
473: adbprintf("0h::");
474: break;
475:
476: case TYPQ:
477: case TYPO:
478: break;
479:
480: default:
481: panic("bignumprint");
482: }
483:
484: /*
485: * Expand the number into expbuf, then skip leading zeroes.
486: * Be careful not to skip the entire number.
487: */
488: for (p = expbuf, i = nbytes; --i >= 0;) {
489: *p++ = tohex[n.c[i] >> 4];
490: *p++ = tohex[n.c[i] & 15];
491: }
492: for (p = expbuf; *p == '0'; p++)
493: /* void */;
494: prints(*p ? p : p - 1);
495: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.