xref: /csrg-svn/old/adb/adb.vax/opset.c (revision 36564)
1 #ifndef lint
2 static char sccsid[] = "@(#)opset.c	4.8 (Berkeley) 01/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 }
496