xref: /original-bsd/sys/vax/vax/kdb_opset.c (revision be29bfce)
1 /*
2  *	@(#)kdb_opset.c	7.3 (Berkeley) 05/26/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 /* ARGSUSED */
285 printins(fmt, Idsp, ins)
286 	char	fmt;
287 	u_char	ins;
288 	int	Idsp;
289 {
290 		u_char	mode;		/* mode */
291 		u_char	ins2;
292 		char	*indexreg;	/* print of which register indexes */
293 		char	*indexed;	/* we indexed */
294 		char	*operandout();
295 	register u_char 	*ap;
296 	register struct insttab *ip;
297 		u_char	optype;
298 		int	mapchar;
299 
300 	idsp = Idsp;
301 	type = DSYM;
302 	space = idsp;
303 	insoutfmt[0] = 0;
304 
305 	incp = 1;
306 	if ((mapchar = mapescbyte(ins)) != 0){
307 		ins2 = snarfuchar();
308 		if (ioptab[mapchar][ins2] == 0){
309 			/*
310 			 *	Oops; not a defined instruction;
311 			 *	back over this escape byte.
312 			 */
313 			incp -= 1;
314 			mapchar = 0;
315 		} else {
316 			ins = ins2;
317 		}
318 	}
319 	if (ioptab[mapchar][ins] == 0){
320 		printf("<undefined operator byte>: %x", ins);
321 		goto ret;
322 	}
323 	ip = &insttab[ioptab[mapchar][ins] - 1];
324 	printf("%s\t", ip->iname);
325 
326 	for (ap = ip->argtype, argno = 0; argno < ip->nargs; argno++, ap++) {
327 		savevar(0x80000000);	/* an illegal symbol */
328 		optype = *ap;
329 		if (argno != 0)
330 			printc(',');
331 		indexreg = 0;
332 		indexed = 0;
333 		do{
334 			if (A_ACCEXT(optype) & ACCB){
335 				switch(A_TYPEXT(optype)){
336 				case TYPB:
337 					mode = OC_CONS(OC_BDISP, R_PC);
338 					break;
339 				case TYPW:
340 					mode = OC_CONS(OC_WDISP, R_PC);
341 					break;
342 				}
343 			} else {
344 				mode = snarfuchar();
345 			}
346 			indexreg = operandout(mode, optype);
347 			if (indexed)
348 				printf("[%s]", indexed);
349 			indexed = indexreg;
350 		} while(indexed);
351 	}
352 	if (mapchar == 0){
353 		switch(ins){
354 		case CASEB:
355 		case CASEW:
356 		case CASEL:
357 			casebody(insoutvar[1], insoutvar[2]);
358 			break;
359 		default:
360 			break;
361 		}
362 	}
363    ret: ;
364 
365 	dotinc = incp;
366 }
367 
368 casebody(base, limit)
369 	long	base;
370 	long	limit;
371 {
372 	int	i;
373 	u_int	baseincp;
374 	u_int	advincp;
375 	struct	as_number	*valuep;
376 #define	OSIZE (sizeof(short))
377 	argno = 0;
378 	baseincp = incp;
379 	for (i = 0; i <= limit; i++) {
380 		printc(EOR);
381 		printf("    %R:  ", i + base);
382 		valuep = snarfreloc(OSIZE, 0);
383 		advincp = incp;
384 		incp = baseincp;
385 		dispaddress(valuep, OC_CONS(OC_WDISP, R_PC));
386 		incp = advincp;
387 	}
388 }
389 
390 /*
391  * magic values to mung an offset to a register into
392  * something that psymoff can understand.. all magic
393  */
394 			      /* 0	1	2	3	4 */
395 static long magic_masks[5] =	{0,	0x80,	0x8000,	0,	0};
396 static long magic_compl[5] =	{0,	0x100,	0x10000,0,	0};
397 /*
398  * Snarf up some bytes, and put in the magic relocation flags
399  */
400 static numberp snarfreloc(nbytes)
401 	int	nbytes;
402 {
403 	numberp	back;
404 	back = snarf(nbytes);
405 	if (back->num_ulong[0] & magic_masks[nbytes])
406 		back->num_ulong[0] -= magic_compl[nbytes];
407 	return(back);
408 }
409 /*
410  * The following code is NOT portable from the PDP 11 to the VAX
411  * because of the byte ordering problem.
412  */
413 static numberp snarf(nbytes)
414 	int	nbytes;
415 {
416 	register	int	i;
417 
418 	static	struct	as_number	backnumber;
419 	static	struct	as_number	znumber;	/* init'ed to 0 */
420 
421 	backnumber = znumber;
422 	for (i = 0; i < nbytes; i++)
423 		backnumber.num_uchar[i] = snarfuchar();
424 	return(&backnumber);
425 }
426 
427 /*
428  * Read one single character, and advance the dot
429  */
430 static u_char
431 snarfuchar()
432 {
433 	u_char	back;
434 	/*
435 	 *	assert: bchkget and inkdot don't have side effects
436 	 */
437 	back = (u_char)bchkget(inkdot(incp), idsp);
438 	incp += 1;
439 	return(back);
440 }
441 
442 /*
443  * normal operand; return non zero pointer to register
444  * name if this is an index instruction.
445  */
446 char *operandout(mode, optype)
447 	u_char	mode;
448 	u_char	optype;
449 {
450 	char	*r;
451 	int	regnumber;
452 	int	nbytes;
453 
454 	regnumber = OC_REGEXT(mode);
455 	r = insregname(regnumber);
456 	switch (OC_AMEXT(mode)){
457 	case OC_IMM0:
458 	case OC_IMM1:
459 	case OC_IMM2:
460 	case OC_IMM3:
461 		shortliteral(mode, optype);
462 		return(0);
463 	case OC_INDEX:
464 		return(r);		/* will be printed later */
465 	case OC_REG:
466 		printf("%s", r);
467 		return(0);
468 	case OC_DREG:
469 		printf("(%s)", r);
470 		return(0);
471 	case OC_ADREG:
472 		printf("-(%s)", r);
473 		return(0);
474 	case OC_DAIREG:
475 		printc('*');
476 	case OC_AIREG:
477 		if (regnumber == R_PC){
478 			pcimmediate(mode, optype);
479 		} else {
480 			printf("(%s)+", r);
481 		}
482 		return(0);
483 	case OC_DBDISP:
484 		printc('*');
485 	case OC_BDISP:
486 		nbytes = 1;
487 		break;
488 	case OC_DWDISP:
489 		printc('*');
490 	case OC_WDISP:
491 		nbytes = 2;
492 		break;
493 	case OC_DLDISP:
494 		printc('*');
495 	case OC_LDISP:
496 		nbytes = 4;
497 		break;
498 	}
499 	dispaddress(snarfreloc(nbytes), mode);
500 	return(0);
501 }
502 
503 dispaddress(valuep, mode)
504 	numberp	valuep;
505 	u_char	mode;
506 {
507 	int	regnumber = OC_REGEXT(mode);
508 
509 	switch(OC_AMEXT(mode)){
510 	case OC_BDISP:
511 	case OC_DBDISP:
512 	case OC_WDISP:
513 	case OC_DWDISP:
514 	case OC_LDISP:
515 	case OC_DLDISP:
516 		if (regnumber == R_PC){
517 			/* PC offset addressing */
518 			valuep->num_ulong[0] += inkdot(incp);
519 		}
520 	}
521 	if (regnumber == R_PC)
522 		psymoff(valuep->num_ulong[0], type, &insoutfmt[0]);
523 	else {				/* } */
524 		printf(LPRMODE, valuep->num_ulong[0]);
525 		printf(insoutfmt);
526 		printf("(%s)", insregname(regnumber));
527 	}
528 	savevar((long)valuep->num_ulong[0]);
529 }
530 
531 /*
532  * get a register name
533  */
534 static char *
535 insregname(regnumber)
536 	int	regnumber;
537 {
538 	char	*r;
539 	r = regname[regnumber];
540 	return(r);
541 }
542 
543 /*
544  * print out a short literal
545  */
546 shortliteral(mode, optype)
547 	u_char	mode;
548 	u_char	optype;
549 {
550 	savevar((long)mode);
551 	switch(A_TYPEXT(optype)){
552 	case TYPF:
553 	case TYPD:
554 	case TYPG:
555 	case TYPH:
556 		printf("$%s", fltimm[mode]);
557 		break;
558 	default:
559 		printf("$%r", mode);
560 		break;
561 	}
562 }
563 
564 pcimmediate(mode, optype)
565 	u_char	mode;
566 	u_char	optype;
567 {
568 	int	nbytes;
569 
570 	printc('$');
571 	if (mode == OC_CONS(OC_DAIREG, R_PC)){	/* PC absolute, always 4 bytes*/
572 		dispaddress(snarfreloc(4), mode);
573 		return;
574 	}
575 	nbytes = ty_nbyte[A_TYPEXT(optype)];
576 	if (! ty_NORELOC[A_TYPEXT(optype)]){
577 		dispaddress(snarfreloc(nbytes), mode);
578 		return;
579 	}
580 	bignumprint(nbytes, optype);
581 }
582 
583 bignumprint(nbytes, optype)
584 	int	nbytes;
585 	u_char	optype;
586 {
587 	numberp	valuep;
588 	int	leading_zero = 1;
589 	register int	bindex;
590 	register int	nindex;
591 	register int	ch;
592 
593 	valuep = snarf(nbytes);
594 	switch(A_TYPEXT(optype)){
595 	case TYPF:
596 		printf("0f%f", valuep->num_num.numFf_float.Ff_value);
597 		break;
598 	case TYPD:
599 		printf("0d%f", valuep->num_num.numFd_float.Fd_value);
600 		break;
601 	case TYPG:
602 		printf("0g::"); goto qprint;
603 	case TYPH:
604 		printf("0h::"); goto qprint;
605 	case TYPQ:
606 	case TYPO:
607 	qprint:
608 		for (bindex = nbytes - 1; bindex >= 0; --bindex){
609 			for (nindex = 4; nindex >= 0; nindex -= 4){
610 				ch = (valuep->num_uchar[bindex] >> nindex);
611 				ch &= 0x0F;
612 				if ( ! (leading_zero &= (ch == 0) ) ){
613 					if (ch <= 0x09)
614 						printc(ch + '0');
615 					else
616 						printc(ch - 0x0A + 'a');
617 				}
618 			}
619 		}
620 		break;
621 	}
622 }
623