xref: /original-bsd/sys/vax/vax/kdb_opset.c (revision df6dbad5)
1 /*
2  *	@(#)kdb_opset.c	7.2 (Berkeley) 05/07/88
3  */
4 
5 #include "../kdb/defs.h"
6 
7 /*
8  * Instruction printing.
9  */
10 REGLIST reglist [] = {
11 	"p1lr",	&pcb.pcb_p1lr,	"p1br",	(int *)&pcb.pcb_p1br,
12 	"p0lr",	&pcb.pcb_p0lr,	"p0br",	(int *)&pcb.pcb_p0br,
13 	"ksp",	&pcb.pcb_ksp,	"esp",	&pcb.pcb_esp,
14 	"ssp",	&pcb.pcb_ssp,	"psl",	&pcb.pcb_psl,
15 	"pc",	&pcb.pcb_pc,	"usp",	&pcb.pcb_usp,
16 	"fp",	&pcb.pcb_fp,	"ap",	&pcb.pcb_ap,
17 	"r11",	&pcb.pcb_r11,	"r10",	&pcb.pcb_r10,
18 	"r9",	&pcb.pcb_r9,	"r8",	&pcb.pcb_r8,
19 	"r7",	&pcb.pcb_r7,	"r6",	&pcb.pcb_r6,
20 	"r5",	&pcb.pcb_r5,	"r4",	&pcb.pcb_r4,
21 	"r3",	&pcb.pcb_r3,	"r2",	&pcb.pcb_r2,
22 	"r1",	&pcb.pcb_r1,	"r0",	&pcb.pcb_r0,
23 };
24 
25 /*
26  * Argument data types
27  *
28  * If you change these definitions, you must also change the tables
29  * in assizetab.c
30  */
31 #define	TYPB		000	/* byte integer */
32 #define	TYPW		001	/* word integer */
33 #define	TYPL		002	/* long integer */
34 #define	TYPQ		003	/* quad integer */
35 #define	TYPO		004	/* octa integer */
36 #define	TYPF		005	/* F float */
37 #define	TYPD		006	/* D float */
38 #define	TYPG		007	/* G float */
39 #define	TYPH		010	/* H float */
40 #define	TYPUNPACKED	011	/* when unpacked into mantissa & exponent */
41 #define	TYPNONE		012	/* when nothing */
42 #define	TYPLG		4	/* number of bits the above take up */
43 
44 #define	TYPMASK	((1<<TYPLG)-1)	/* the mask (assumes 2's comp arith) */
45 /*
46  * Constructors and extractors for argument access kinds and types
47  */
48 #define A_CONS(access, type)	((access) | (type))
49 #define	A_ACCEXT(consed)	((consed) & (TYPMASK << TYPLG))
50 #define	A_TYPEXT(consed)	((consed) & TYPMASK)
51 
52 /*
53  * Argument access types used to test validity of operands to operators
54  */
55 #define	ACCR	(1<<TYPLG)			/* read */
56 #define	ACCW	(2<<TYPLG)			/* write */
57 #define	ACCB	(4<<TYPLG)			/* branch displacement */
58 #define	ACCA	(8<<TYPLG)			/* address only */
59 #define	ACCV	(8<<TYPLG)			/* address only */
60 #define	ACCM	(ACCR | ACCW)			/* modify */
61 #define	ACCI	(ACCB | ACCR)			/* XFC code */
62 
63 #define ACCESSMASK	(ACCA | ACCR | ACCW | ACCB)	/* the mask */
64 
65 /*
66  * Construction of TYPX and ACCX, to make the instrs table
67  * easy to use and read.
68  */
69 /*
70  * For real memory address
71  */
72 #define	A_AB	A_CONS(ACCA, TYPB)
73 #define	A_AW	A_CONS(ACCA, TYPW)
74 #define	A_AL	A_CONS(ACCA, TYPL)
75 #define	A_AQ	A_CONS(ACCA, TYPQ)
76 #define	A_AO	A_CONS(ACCA, TYPO)
77 #define	A_AF	A_CONS(ACCA, TYPF)
78 #define	A_AD	A_CONS(ACCA, TYPD)
79 #define	A_AG	A_CONS(ACCA, TYPG)
80 #define	A_AH	A_CONS(ACCA, TYPH)
81 /*
82  * For real memory addresses, or register addresses [sic]
83  *
84  * CHEAT! we just call these read access, since
85  * registers are allowed. All field instruction, except insv,
86  * are are read access fields.
87  */
88 #define	A_VB	A_CONS(ACCR, TYPB)
89 #define	A_VW	A_CONS(ACCR, TYPW)
90 #define	A_VL	A_CONS(ACCR, TYPL)
91 #define	A_VQ	A_CONS(ACCR, TYPQ)
92 #define	A_VO	A_CONS(ACCR, TYPO)
93 #define	A_VF	A_CONS(ACCR, TYPF)
94 #define	A_VD	A_CONS(ACCR, TYPD)
95 #define	A_VG	A_CONS(ACCR, TYPG)
96 #define	A_VH	A_CONS(ACCR, TYPH)
97 /*
98  * For branch displacement
99  */
100 #define	A_BB	A_CONS(ACCB, TYPB)
101 #define	A_BW	A_CONS(ACCB, TYPW)
102 /*
103  * For modification
104  */
105 #define	A_MB	A_CONS(ACCM, TYPB)
106 #define	A_MW	A_CONS(ACCM, TYPW)
107 #define	A_ML	A_CONS(ACCM, TYPL)
108 #define	A_MF	A_CONS(ACCM, TYPF)
109 #define	A_MD	A_CONS(ACCM, TYPD)
110 #define	A_MG	A_CONS(ACCM, TYPG)
111 #define	A_MH	A_CONS(ACCM, TYPH)
112 /*
113  * For reading
114  */
115 #define	A_RB	A_CONS(ACCR, TYPB)
116 #define	A_RW	A_CONS(ACCR, TYPW)
117 #define	A_RL	A_CONS(ACCR, TYPL)
118 #define	A_RQ	A_CONS(ACCR, TYPQ)
119 #define	A_RO	A_CONS(ACCR, TYPO)
120 #define	A_RF	A_CONS(ACCR, TYPF)
121 #define	A_RD	A_CONS(ACCR, TYPD)
122 #define	A_RG	A_CONS(ACCR, TYPG)
123 #define	A_RH	A_CONS(ACCR, TYPH)
124 /*
125  * For writing
126  */
127 #define	A_WB	A_CONS(ACCW, TYPB)
128 #define	A_WW	A_CONS(ACCW, TYPW)
129 #define	A_WL	A_CONS(ACCW, TYPL)
130 #define	A_WQ	A_CONS(ACCW, TYPQ)
131 #define	A_WO	A_CONS(ACCW, TYPO)
132 #define	A_WF	A_CONS(ACCW, TYPF)
133 #define	A_WD	A_CONS(ACCW, TYPD)
134 #define	A_WG	A_CONS(ACCW, TYPG)
135 #define	A_WH	A_CONS(ACCW, TYPH)
136 
137 struct insttab {
138 	char	*iname;
139 	u_char	eopcode;
140 	u_char	popcode;
141 	char	nargs;
142 	u_char	argtype[6];
143 };
144 
145 #define OP(name,eopcode,popdcode,nargs,a1,a2,a3,a4,a5,a6) \
146 	{name,eopcode,popdcode,nargs,a1,a2,a3,a4,a5,a6}
147 /*
148  * Definitions for the escape bytes
149  */
150 #define	CORE	0
151 #define	NEW	1
152 #define	ESCD	0xfd
153 #define	ESCF	0xff
154 #define	mapescbyte(b)	((b) == ESCD ? 1 : (b) == ESCF ? 2 : 0)
155 
156 static	struct insttab insttab[] = {
157 #include "../vax/kdb_instrs"
158 0};
159 
160 /*
161  * Convert TYP[BWLQOFDGH] into {1 if relocation not OK}
162  */
163 int	ty_NORELOC[] = {
164 	0,	/* TYPB */
165 	0,	/* TYPW */
166 	0,	/* TYPL */
167 	1,	/* TYPQ */
168 	1,	/* TYPO */
169 	1,	/* TYPF */
170 	1,	/* TYPD */
171 	1,	/* TYPG */
172 	1,	/* TYPH */
173 	1	/* TYPNONE */
174 };
175 
176 /*
177  * Convert TYP[BWLQOFDGH] into {1 ... 16}
178  */
179 int	ty_nbyte[] = {
180 	1,	/* TYPB */
181 	2,	/* TYPW */
182 	4,	/* TYPL */
183 	8,	/* TYPQ */
184 	16,	/* TYPO */
185 	4,	/* TYPF */
186 	8,	/* TYPD */
187 	8,	/* TYPG */
188 	16,	/* TYPH */
189 	0	/* TYPNONE */
190 };
191 
192 static	char *regname[] = {
193 	"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
194 	"r8", "r9", "r10","r11","ap", "fp", "sp", "pc"
195 };
196 static	char *fltimm[] = {
197 "0.5", "0.5625", "0.625", "0.6875", "0.75", "0.8125", "0.875", "0.9375",
198 "1.0", "1.125", "1.25", "1.375", "1.5", "1.625", "1.75", "1.875",
199 "2.0", "2.25", "2.5", "2.75", "3.0", "3.25", "3.5", "3.75",
200 "4.0", "4.5", "5.0", "5.5", "6.0", "6.5", "7.0", "7.5",
201 "8.0", "9.0", "10.0", "11.0", "12.0", "13.0", "14.0", "15.0",
202 "16.0", "18.0", "20.0", "22.0", "24.0", "26.0", "28.0", "30.0",
203 "32.0", "36.0", "40.0", "44.0", "48.0", "52.0", "56.0", "60.0",
204 "64.0", "72.0", "80.0", "88.0", "96.0", "104.0", "112.0", "120.0"
205 };
206 
207 static	int type, space, incp;
208 static	long insoutvar[36];
209 /*
210  * Definitions for registers and for operand classes
211  */
212 static	char *insregname();	/* how to print a register */
213 
214 #define	R_PC		0xF
215 
216 #define	OC_IMM0		0x0
217 #define	OC_IMM1		0x1
218 #define	OC_IMM2		0x2
219 #define	OC_IMM3		0x3
220 #define	OC_INDEX	0x4
221 #define	OC_REG		0x5
222 #define	OC_DREG		0x6
223 #define	OC_ADREG	0x7
224 #define	OC_AIREG	0x8
225 #define	OC_DAIREG	0x9
226 
227 #define	OC_BDISP	0xA
228 #define	OC_DBDISP	0xB
229 #define	OC_WDISP	0xC
230 #define	OC_DWDISP	0xD
231 #define	OC_LDISP	0xE
232 #define	OC_DLDISP	0xF
233 
234 #define	OC_SHIFT	4
235 #define	OC_CONS(oc,reg)	(((oc & 0xF) << OC_SHIFT) | (reg & 0xF))
236 #define	OC_AMEXT(x)	(((x) >> OC_SHIFT) & 0xF)
237 #define	OC_REGEXT(x)	((x) & 0xF)
238 
239 /*
240  * Definitions for large numbers
241  */
242 #include "asnumber.h"
243 typedef	struct	as_number	*numberp;
244 static	numberp snarf();
245 static	numberp snarfreloc();
246 /*
247  * Definitions for special instructions
248  */
249 #define	CASEB	0x8F
250 #define	CASEW	0xAF
251 #define	CASEL	0xCF
252 
253 /* two level 1-based index by opcode into insttab */
254 static	short ioptab[3][256];
255 
256 kdbsetup()
257 {
258 	register struct insttab *p;
259 		int	mapchar;
260 
261 	for(p = insttab; p->iname; p++){
262 		mapchar = mapescbyte(p->eopcode);
263 		if (ioptab[mapchar][p->popcode])
264 			continue;
265 		ioptab[mapchar][p->popcode] = (p - insttab) + 1;
266 	}
267 }
268 
269 static	u_char snarfuchar();
270 /*
271  * Global variables for communicating with the minions and printins
272  */
273 static	int	idsp;
274 static	short	argno;		/* which argument one is working on */
275 static	char	insoutfmt[2];	/* how to format the relocated symbols */
276 
277 static savevar(val)
278 	long	val;
279 {
280 	var[argno] = val;
281 	insoutvar[argno] = val;
282 }
283 
284 printins(fmt, Idsp, ins)
285 	char	fmt;
286 	u_char	ins;
287 	int	Idsp;
288 {
289 		u_char	mode;		/* mode */
290 		u_char	ins2;
291 		char	*indexreg;	/* print of which register indexes */
292 		char	*indexed;	/* we indexed */
293 		char	*operandout();
294 	register u_char 	*ap;
295 	register struct insttab *ip;
296 		u_char	optype;
297 		int	mapchar;
298 
299 	idsp = Idsp;
300 	type = DSYM;
301 	space = idsp;
302 	insoutfmt[0] = 0;
303 
304 	incp = 1;
305 	if ((mapchar = mapescbyte(ins)) != 0){
306 		ins2 = snarfuchar();
307 		if (ioptab[mapchar][ins2] == 0){
308 			/*
309 			 *	Oops; not a defined instruction;
310 			 *	back over this escape byte.
311 			 */
312 			incp -= 1;
313 			mapchar = 0;
314 		} else {
315 			ins = ins2;
316 		}
317 	}
318 	if (ioptab[mapchar][ins] == 0){
319 		printf("<undefined operator byte>: %x", ins);
320 		goto ret;
321 	}
322 	ip = &insttab[ioptab[mapchar][ins] - 1];
323 	printf("%s\t", ip->iname);
324 
325 	for (ap = ip->argtype, argno = 0; argno < ip->nargs; argno++, ap++) {
326 		savevar(0x80000000);	/* an illegal symbol */
327 		optype = *ap;
328 		if (argno != 0)
329 			printc(',');
330 		indexreg = 0;
331 		indexed = 0;
332 		do{
333 			if (A_ACCEXT(optype) & ACCB){
334 				switch(A_TYPEXT(optype)){
335 				case TYPB:
336 					mode = OC_CONS(OC_BDISP, R_PC);
337 					break;
338 				case TYPW:
339 					mode = OC_CONS(OC_WDISP, R_PC);
340 					break;
341 				}
342 			} else {
343 				mode = snarfuchar();
344 			}
345 			indexreg = operandout(mode, optype);
346 			if (indexed)
347 				printf("[%s]", indexed);
348 			indexed = indexreg;
349 		} while(indexed);
350 	}
351 	if (mapchar == 0){
352 		switch(ins){
353 		case CASEB:
354 		case CASEW:
355 		case CASEL:
356 			casebody(insoutvar[1], insoutvar[2]);
357 			break;
358 		default:
359 			break;
360 		}
361 	}
362    ret: ;
363 
364 	dotinc = incp;
365 }
366 
367 casebody(base, limit)
368 	long	base;
369 	long	limit;
370 {
371 	int	i;
372 	u_int	baseincp;
373 	u_int	advincp;
374 	struct	as_number	*valuep;
375 #define	OSIZE (sizeof(short))
376 	argno = 0;
377 	baseincp = incp;
378 	for (i = 0; i <= limit; i++) {
379 		printc(EOR);
380 		printf("    %R:  ", i + base);
381 		valuep = snarfreloc(OSIZE, 0);
382 		advincp = incp;
383 		incp = baseincp;
384 		dispaddress(valuep, OC_CONS(OC_WDISP, R_PC));
385 		incp = advincp;
386 	}
387 }
388 
389 /*
390  * magic values to mung an offset to a register into
391  * something that psymoff can understand.. all magic
392  */
393 			      /* 0	1	2	3	4 */
394 static long magic_masks[5] =	{0,	0x80,	0x8000,	0,	0};
395 static long magic_compl[5] =	{0,	0x100,	0x10000,0,	0};
396 /*
397  * Snarf up some bytes, and put in the magic relocation flags
398  */
399 static numberp snarfreloc(nbytes)
400 	int	nbytes;
401 {
402 	numberp	back;
403 	back = snarf(nbytes);
404 	if (back->num_ulong[0] & magic_masks[nbytes])
405 		back->num_ulong[0] -= magic_compl[nbytes];
406 	return(back);
407 }
408 /*
409  * The following code is NOT portable from the PDP 11 to the VAX
410  * because of the byte ordering problem.
411  */
412 static numberp snarf(nbytes)
413 	int	nbytes;
414 {
415 	register	int	i;
416 
417 	static	struct	as_number	backnumber;
418 	static	struct	as_number	znumber;	/* init'ed to 0 */
419 
420 	backnumber = znumber;
421 	for (i = 0; i < nbytes; i++)
422 		backnumber.num_uchar[i] = snarfuchar();
423 	return(&backnumber);
424 }
425 
426 /*
427  * Read one single character, and advance the dot
428  */
429 static u_char
430 snarfuchar()
431 {
432 	u_char	back;
433 	/*
434 	 *	assert: bchkget and inkdot don't have side effects
435 	 */
436 	back = (u_char)bchkget(inkdot(incp), idsp);
437 	incp += 1;
438 	return(back);
439 }
440 
441 /*
442  * normal operand; return non zero pointer to register
443  * name if this is an index instruction.
444  */
445 char *operandout(mode, optype)
446 	u_char	mode;
447 	u_char	optype;
448 {
449 	char	*r;
450 	int	regnumber;
451 	int	nbytes;
452 
453 	regnumber = OC_REGEXT(mode);
454 	r = insregname(regnumber);
455 	switch (OC_AMEXT(mode)){
456 	case OC_IMM0:
457 	case OC_IMM1:
458 	case OC_IMM2:
459 	case OC_IMM3:
460 		shortliteral(mode, optype);
461 		return(0);
462 	case OC_INDEX:
463 		return(r);		/* will be printed later */
464 	case OC_REG:
465 		printf("%s", r);
466 		return(0);
467 	case OC_DREG:
468 		printf("(%s)", r);
469 		return(0);
470 	case OC_ADREG:
471 		printf("-(%s)", r);
472 		return(0);
473 	case OC_DAIREG:
474 		printc('*');
475 	case OC_AIREG:
476 		if (regnumber == R_PC){
477 			pcimmediate(mode, optype);
478 		} else {
479 			printf("(%s)+", r);
480 		}
481 		return(0);
482 	case OC_DBDISP:
483 		printc('*');
484 	case OC_BDISP:
485 		nbytes = 1;
486 		break;
487 	case OC_DWDISP:
488 		printc('*');
489 	case OC_WDISP:
490 		nbytes = 2;
491 		break;
492 	case OC_DLDISP:
493 		printc('*');
494 	case OC_LDISP:
495 		nbytes = 4;
496 		break;
497 	}
498 	dispaddress(snarfreloc(nbytes), mode);
499 	return(0);
500 }
501 
502 dispaddress(valuep, mode)
503 	numberp	valuep;
504 	u_char	mode;
505 {
506 	int	regnumber = OC_REGEXT(mode);
507 
508 	switch(OC_AMEXT(mode)){
509 	case OC_BDISP:
510 	case OC_DBDISP:
511 	case OC_WDISP:
512 	case OC_DWDISP:
513 	case OC_LDISP:
514 	case OC_DLDISP:
515 		if (regnumber == R_PC){
516 			/* PC offset addressing */
517 			valuep->num_ulong[0] += inkdot(incp);
518 		}
519 	}
520 	if (regnumber == R_PC)
521 		psymoff(valuep->num_ulong[0], type, &insoutfmt[0]);
522 	else {				/* } */
523 		printf(LPRMODE, valuep->num_ulong[0]);
524 		printf(insoutfmt);
525 		printf("(%s)", insregname(regnumber));
526 	}
527 	savevar((long)valuep->num_ulong[0]);
528 }
529 
530 /*
531  * get a register name
532  */
533 static char *
534 insregname(regnumber)
535 	int	regnumber;
536 {
537 	char	*r;
538 	r = regname[regnumber];
539 	return(r);
540 }
541 
542 /*
543  * print out a short literal
544  */
545 shortliteral(mode, optype)
546 	u_char	mode;
547 	u_char	optype;
548 {
549 	savevar((long)mode);
550 	switch(A_TYPEXT(optype)){
551 	case TYPF:
552 	case TYPD:
553 	case TYPG:
554 	case TYPH:
555 		printf("$%s", fltimm[mode]);
556 		break;
557 	default:
558 		printf("$%r", mode);
559 		break;
560 	}
561 }
562 
563 pcimmediate(mode, optype)
564 	u_char	mode;
565 	u_char	optype;
566 {
567 	int	nbytes;
568 
569 	printc('$');
570 	if (mode == OC_CONS(OC_DAIREG, R_PC)){	/* PC absolute, always 4 bytes*/
571 		dispaddress(snarfreloc(4), mode);
572 		return;
573 	}
574 	nbytes = ty_nbyte[A_TYPEXT(optype)];
575 	if (! ty_NORELOC[A_TYPEXT(optype)]){
576 		dispaddress(snarfreloc(nbytes), mode);
577 		return;
578 	}
579 	bignumprint(nbytes, optype);
580 }
581 
582 bignumprint(nbytes, optype)
583 	int	nbytes;
584 	u_char	optype;
585 {
586 	numberp	valuep;
587 	int	leading_zero = 1;
588 	register int	bindex;
589 	register int	nindex;
590 	register int	ch;
591 
592 	valuep = snarf(nbytes);
593 	switch(A_TYPEXT(optype)){
594 	case TYPF:
595 		printf("0f%f", valuep->num_num.numFf_float.Ff_value);
596 		break;
597 	case TYPD:
598 		printf("0d%f", valuep->num_num.numFd_float.Fd_value);
599 		break;
600 	case TYPG:
601 		printf("0g::"); goto qprint;
602 	case TYPH:
603 		printf("0h::"); goto qprint;
604 	case TYPQ:
605 	case TYPO:
606 	qprint:
607 		for (bindex = nbytes - 1; bindex >= 0; --bindex){
608 			for (nindex = 4; nindex >= 0; nindex -= 4){
609 				ch = (valuep->num_uchar[bindex] >> nindex);
610 				ch &= 0x0F;
611 				if ( ! (leading_zero &= (ch == 0) ) ){
612 					if (ch <= 0x09)
613 						printc(ch + '0');
614 					else
615 						printc(ch - 0x0A + 'a');
616 				}
617 			}
618 		}
619 		break;
620 	}
621 }
622