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