xref: /csrg-svn/old/adb/adb.vax/opset.c (revision 21098)
18912Srrh #ifndef lint
2*21098Sedward static	char sccsid[] = "@(#)opset.c 4.5 05/27/85";
38912Srrh #endif lint
43760Sroot /*
53760Sroot  *	UNIX debugger
68912Srrh  *	Instruction printing routines.
78912Srrh  *	MACHINE DEPENDENT
83760Sroot  */
93760Sroot 
108912Srrh #ifdef ADB
113760Sroot #include "defs.h"
128912Srrh #endif ADB
138912Srrh #ifdef SDB
148912Srrh #include "head.h"
158912Srrh #endif SDB
163760Sroot 
173760Sroot L_INT		dot;
183760Sroot INT		dotinc;
198912Srrh L_INT		insoutvar[36];
208912Srrh #ifdef ADB
218912Srrh L_INT		var[36];
228912Srrh #endif ADB
233760Sroot 
248912Srrh #undef	INSTTAB
258912Srrh #include "instrs.h"
263760Sroot 
278912Srrh STRING	regname[];
288912Srrh STRING	fltimm[];
298912Srrh POS	type, space, incp;
303760Sroot /*
318912Srrh  *	Definitions for registers and for operand classes
323760Sroot  */
338912Srrh char	*insregname();	/* how to print a register */
343760Sroot 
358912Srrh #define	R_PC		0xF
368912Srrh 
378912Srrh #define	OC_IMM0		0x0
388912Srrh #define	OC_IMM1		0x1
398912Srrh #define	OC_IMM2		0x2
408912Srrh #define	OC_IMM3		0x3
418912Srrh #define	OC_INDEX	0x4
428912Srrh #define	OC_REG		0x5
438912Srrh #define	OC_DREG		0x6
448912Srrh #define	OC_ADREG	0x7
458912Srrh #define	OC_AIREG	0x8
468912Srrh #define	OC_DAIREG	0x9
478912Srrh 
488912Srrh #define	OC_BDISP	0xA
498912Srrh #define	OC_DBDISP	0xB
508912Srrh #define	OC_WDISP	0xC
518912Srrh #define	OC_DWDISP	0xD
528912Srrh #define	OC_LDISP	0xE
538912Srrh #define	OC_DLDISP	0xF
548912Srrh 
558912Srrh #define	OC_SHIFT	4
568912Srrh #define	OC_CONS(oc,reg)	(((oc & 0xF) << OC_SHIFT) | (reg & 0xF))
578912Srrh #define	OC_AMEXT(x)	(((x) >> OC_SHIFT) & 0xF)
588912Srrh #define	OC_REGEXT(x)	((x) & 0xF)
598912Srrh 
603760Sroot /*
618912Srrh  *	Definitions for large numbers
623760Sroot  */
638912Srrh #include "asnumber.h"
648912Srrh typedef	struct	as_number	*numberp;
658912Srrh numberp snarf();
668912Srrh numberp snarfreloc();
678912Srrh /*
688912Srrh  *	Definitions for special instructions
698912Srrh  */
708912Srrh #define	CASEB	0x8F
718912Srrh #define	CASEW	0xAF
728912Srrh #define	CASEL	0xCF
738912Srrh /*
748912Srrh  *	Definitions for converting TYP's into numbers, booleans, etc.
758912Srrh  *	These are shared with the assembler.
768912Srrh  */
778912Srrh extern	int	ty_NORELOC[];
788912Srrh extern	int	ty_float[];
798912Srrh extern	int	ty_nbyte[];
808912Srrh extern	int	ty_nlg[];
818912Srrh extern	char	*ty_string[];
823760Sroot 
8312402Srrh short ioptab[3][256];	/* two level 1-based index by opcode into insttab */
843760Sroot 
858912Srrh int mapescbyte(byte)
868912Srrh 	u_char	byte;
878912Srrh {
888912Srrh 	switch(byte){
898912Srrh 	default:	return(0);
908912Srrh 	case ESCD:	return(1);
918912Srrh 	case ESCF:	return(2);
928912Srrh 	}
938912Srrh }
943760Sroot 
958912Srrh mkioptab()
968912Srrh {
978912Srrh 	REG	struct insttab *p;
988912Srrh 		int	mapchar;
993760Sroot 
1008912Srrh 	for(p = insttab; p->iname; p++){
1018912Srrh 		mapchar = mapescbyte(p->eopcode);
1028912Srrh 		if (ioptab[mapchar][p->popcode])
1038912Srrh 			continue;
10412402Srrh 		ioptab[mapchar][p->popcode] = (p - insttab) + 1;
1053760Sroot 	}
1063760Sroot }
1073760Sroot 
1088912Srrh u_char snarfuchar();
1098912Srrh /*
1108912Srrh  *	Global variables for communicating with the minions and printins
1118912Srrh  */
1128912Srrh static	int	idsp;
1138912Srrh static	short	argno;		/* which argument one is working on */
1148912Srrh static	char	insoutfmt[2];	/* how to format the relocated symbols */
1158912Srrh #ifdef SDB
1168912Srrh static	struct	proct	*procp;
1178912Srrh #endif SDB
1183760Sroot 
1198912Srrh static savevar(val)
1208912Srrh 	long	val;
1218912Srrh {
1228912Srrh 	var[argno] = val;
1238912Srrh 	insoutvar[argno] = val;
1248912Srrh }
1258912Srrh 
1268912Srrh printins(fmt, Idsp, ins)
1278912Srrh 	char	fmt;
1283760Sroot #ifndef vax
1298912Srrh 	u_char	ins;
1303760Sroot #else
1318912Srrh 	u_char	ins;
1323760Sroot #endif
1338912Srrh 	int	Idsp;
1343760Sroot {
1358912Srrh 		u_char	mode;		/* mode */
1368912Srrh 		u_char	ins2;
1378912Srrh 		char	*indexreg;	/* print of which register indexes */
1388912Srrh 		char	*indexed;	/* we indexed */
1398912Srrh 		char	*operandout();
1408912Srrh 	REG	u_char 	*ap;
1418912Srrh 	REG	struct insttab *ip;
1428912Srrh 		u_char	optype;
1438912Srrh 		int	mapchar;
1443760Sroot 
1458912Srrh 	idsp = Idsp;
1463760Sroot 	type = DSYM;
1473760Sroot 	space = idsp;
1488912Srrh #ifdef SDB
1498912Srrh 	procp = adrtoprocp(dot);
1508912Srrh 	if (procp->paddr == dot){
1518912Srrh 		printf("0x%04.4x", ins);
1528912Srrh 		incp = 2;
1538912Srrh 		goto ret;
1548912Srrh 	}
1558912Srrh #endif SDB
1568912Srrh 
1578912Srrh #ifdef ADB
1588912Srrh 	insoutfmt[0] = 0;
1598912Srrh #endif ADB
1608912Srrh #ifdef SDB
1618912Srrh 	insoutfmt[0] = fmt;
1628912Srrh #endif SDB
1638912Srrh 
1643760Sroot 	incp = 1;
1658912Srrh 	if ((mapchar = mapescbyte(ins)) != 0){
1668912Srrh 		ins2 = snarfuchar();
1678912Srrh 		if (ioptab[mapchar][ins2] == 0){
1688912Srrh 			/*
1698912Srrh 			 *	Oops; not a defined instruction;
1708912Srrh 			 *	back over this escape byte.
1718912Srrh 			 */
1728912Srrh 			incp -= 1;
1738912Srrh 			mapchar = 0;
1748912Srrh 		} else {
1758912Srrh 			ins = ins2;
1763760Sroot 		}
1778912Srrh 	}
1788912Srrh 	if (ioptab[mapchar][ins] == 0){
1798912Srrh 		printf("<undefined operator byte>: %x", ins);
1808912Srrh 		goto ret;
1818912Srrh 	}
18212402Srrh 	ip = &insttab[ioptab[mapchar][ins] - 1];
1838912Srrh 	printf("%s\t", ip->iname);
1848912Srrh 
1858912Srrh 	for (ap = ip->argtype, argno = 0; argno < ip->nargs; argno++, ap++) {
1868912Srrh 		savevar(0x80000000);	/* an illegal symbol */
1878912Srrh 		optype = *ap;
1888912Srrh 		if (argno != 0)
1898912Srrh 			printc(',');
1908912Srrh 		indexreg = 0;
1918912Srrh 		indexed = 0;
1928912Srrh 		do{
1938912Srrh 			if (A_ACCEXT(optype) & ACCB){
1948912Srrh 				switch(A_TYPEXT(optype)){
1958912Srrh 				case TYPB:
1968912Srrh 					mode = OC_CONS(OC_BDISP, R_PC);
1973760Sroot 					break;
1988912Srrh 				case TYPW:
1998912Srrh 					mode = OC_CONS(OC_WDISP, R_PC);
2003760Sroot 					break;
2018912Srrh 				}
2028912Srrh 			} else {
2038912Srrh 				mode = snarfuchar();
2048912Srrh 			}
2058912Srrh 			indexreg = operandout(mode, optype);
2068912Srrh 			if (indexed)
2078912Srrh 				printf("[%s]", indexed);
2088912Srrh 			indexed = indexreg;
2098912Srrh 		} while(indexed);
2103760Sroot 	}
2118912Srrh 	if (mapchar == 0){
2128912Srrh 		switch(ins){
2138912Srrh 		case CASEB:
2148912Srrh 		case CASEW:
2158912Srrh 		case CASEL:
2168912Srrh 			casebody(insoutvar[1], insoutvar[2]);
2178912Srrh 			break;
2188912Srrh 		default:
2198912Srrh 			break;
2203760Sroot 		}
2213760Sroot 	}
2228912Srrh    ret: ;
2238912Srrh 
2248912Srrh #ifdef SDB
2258912Srrh 	oincr = incp;
2268912Srrh #endif SDB
2278912Srrh #ifdef ADB
2288912Srrh 	dotinc = incp;
2298912Srrh #endif ADB
2303760Sroot }
2313760Sroot 
2328912Srrh casebody(base, limit)
2338912Srrh 	long	base;
2348912Srrh 	long	limit;
2358912Srrh {
2368912Srrh 	int	i;
2378912Srrh 	POS	baseincp;
2388912Srrh 	POS	advincp;
2398912Srrh 	struct	as_number	*valuep;
2408912Srrh #define	OSIZE (sizeof(short))
2418912Srrh 	argno = 0;
2428912Srrh 	baseincp = incp;
2438912Srrh 	for (i = 0; i <= limit; i++) {
2448912Srrh 		printc(EOR);
2458912Srrh #ifdef SDB
2468912Srrh 		printf("    %d:  ", i + base);
2478912Srrh #endif SDB
2488912Srrh #ifdef ADB
2498912Srrh 		printf("    %R:  ", i + base);
2508912Srrh #endif ADB
2518912Srrh 		valuep = snarfreloc(OSIZE, 0);
2528912Srrh 		advincp = incp;
2538912Srrh 		incp = baseincp;
2548912Srrh 		dispaddress(valuep, OC_CONS(OC_WDISP, R_PC));
2558912Srrh 		incp = advincp;
2568912Srrh 	}
2578912Srrh }
2588912Srrh 
2593760Sroot /*
2603760Sroot  *	magic values to mung an offset to a register into
2613760Sroot  *	something that psymoff can understand.. all magic
2623760Sroot  */
2633760Sroot 			      /* 0	1	2	3	4 */
2643760Sroot static long magic_masks[5] =	{0,	0x80,	0x8000,	0,	0};
2653760Sroot static long magic_compl[5] =	{0,	0x100,	0x10000,0,	0};
2668912Srrh /*
2678912Srrh  *	Snarf up some bytes, and put in the magic relocation flags
2688912Srrh  */
2698912Srrh numberp snarfreloc(nbytes)
2708912Srrh 	int	nbytes;
2718912Srrh {
2728912Srrh 	numberp	back;
2738912Srrh 	back = snarf(nbytes);
2748912Srrh 	if (back->num_ulong[0] & magic_masks[nbytes])
2758912Srrh 		back->num_ulong[0] -= magic_compl[nbytes];
2768912Srrh 	return(back);
2778912Srrh }
2788912Srrh /*
2798912Srrh  *	The following code is NOT portable from the PDP 11 to the VAX
2808912Srrh  *	because of the byte ordering problem.
2818912Srrh  */
2828912Srrh numberp snarf(nbytes)
2838912Srrh 	int	nbytes;
2848912Srrh {
2858912Srrh 	REG	int	i;
2863760Sroot 
2878912Srrh 	static	struct	as_number	backnumber;
2888912Srrh 	static	struct	as_number	znumber;	/* init'ed to 0 */
2898912Srrh 
2908912Srrh 	backnumber = znumber;
2918912Srrh 	for (i = 0; i < nbytes; i++)
2928912Srrh 		backnumber.num_uchar[i] = snarfuchar();
2938912Srrh 	return(&backnumber);
2948912Srrh }
2953760Sroot /*
2968912Srrh  *	Read one single character, and advance the dot
2973760Sroot  */
2988912Srrh u_char snarfuchar()
2993760Sroot {
3008912Srrh 	u_char	back;
3018912Srrh 	/*
3028912Srrh 	 *	assert: bchkget and inkdot don't have side effects
3038912Srrh 	 */
3048912Srrh 	back = (u_char)bchkget(inkdot(incp), idsp);
3058912Srrh 	incp += 1;
3068912Srrh 	return(back);
3078912Srrh }
3088912Srrh /*
3098912Srrh  *	normal operand; return non zero pointer to register
3108912Srrh  *	name if this is an index instruction.
3118912Srrh  */
3128912Srrh char *operandout(mode, optype)
3138912Srrh 	u_char	mode;
3148912Srrh 	u_char	optype;
3158912Srrh {
3168912Srrh 	char	*r;
3178912Srrh 	int	regnumber;
3188912Srrh 	int	nbytes;
3193760Sroot 
3208912Srrh 	regnumber = OC_REGEXT(mode);
3218912Srrh 	r = insregname(regnumber);
3228912Srrh 	switch (OC_AMEXT(mode)){
3238912Srrh 	case OC_IMM0:
3248912Srrh 	case OC_IMM1:
3258912Srrh 	case OC_IMM2:
3268912Srrh 	case OC_IMM3:
3278912Srrh 		shortliteral(mode, optype);
3288912Srrh 		return(0);
3298912Srrh 	case OC_INDEX:
3308912Srrh 		return(r);		/* will be printed later */
3318912Srrh 	case OC_REG:
3328912Srrh 		printf("%s", r);
3338912Srrh 		return(0);
3348912Srrh 	case OC_DREG:
3358912Srrh 		printf("(%s)", r);
3368912Srrh 		return(0);
3378912Srrh 	case OC_ADREG:
3388912Srrh 		printf("-(%s)", r);
3398912Srrh 		return(0);
3408912Srrh 	case OC_DAIREG:
3418912Srrh 		printc('*');
3428912Srrh 	case OC_AIREG:
3438912Srrh 		if (regnumber == R_PC){
3448912Srrh 			pcimmediate(mode, optype);
3458912Srrh 		} else {
3468912Srrh 			printf("(%s)+", r);
3478912Srrh 		}
3488912Srrh 		return(0);
3498912Srrh 	case OC_DBDISP:
3508912Srrh 		printc('*');
3518912Srrh 	case OC_BDISP:
3528912Srrh 		nbytes = 1;
3538912Srrh 		break;
3548912Srrh 	case OC_DWDISP:
3558912Srrh 		printc('*');
3568912Srrh 	case OC_WDISP:
3578912Srrh 		nbytes = 2;
3588912Srrh 		break;
3598912Srrh 	case OC_DLDISP:
3608912Srrh 		printc('*');
3618912Srrh 	case OC_LDISP:
3628912Srrh 		nbytes = 4;
3638912Srrh 		break;
3643760Sroot 	}
3658912Srrh 	dispaddress(snarfreloc(nbytes), mode);
3668912Srrh 	return(0);
3673760Sroot }
3683760Sroot 
3698912Srrh dispaddress(valuep, mode)
3708912Srrh 	numberp	valuep;
3718912Srrh 	u_char	mode;
3723760Sroot {
3738912Srrh 	int	regnumber = OC_REGEXT(mode);
3743760Sroot 
3758912Srrh 	switch(OC_AMEXT(mode)){
3768912Srrh 	case OC_BDISP:
3778912Srrh 	case OC_DBDISP:
3788912Srrh 	case OC_WDISP:
3798912Srrh 	case OC_DWDISP:
3808912Srrh 	case OC_LDISP:
3818912Srrh 	case OC_DLDISP:
3828912Srrh 		if (regnumber == R_PC){
3838912Srrh 			/* PC offset addressing */
3848912Srrh 			valuep->num_ulong[0] += inkdot(incp);
3858912Srrh 		}
3868912Srrh 	}
3878912Srrh #ifdef ADB
388*21098Sedward 	if (regnumber == R_PC)
389*21098Sedward 		psymoff(valuep->num_ulong[0], type, &insoutfmt[0]);
390*21098Sedward 	else {				/* } */
391*21098Sedward 		printf(LPRMODE, valuep->num_ulong[0]);
392*21098Sedward 		printf(insoutfmt);
3938912Srrh #endif ADB
3948912Srrh #ifdef SDB
3958912Srrh 	if(psymoff(valuep->num_ulong[0], regnumber, &insoutfmt[0])
3968912Srrh 	   && (regnumber != R_PC)){
3978912Srrh #endif SDB
3988912Srrh 		printf("(%s)", insregname(regnumber));
3998912Srrh 	}
4008912Srrh 	savevar((long)valuep->num_ulong[0]);
4013760Sroot }
4028912Srrh /*
4038912Srrh  *	get a register name
4048912Srrh  */
4058912Srrh char *insregname(regnumber)
4068912Srrh 	int	regnumber;
4078912Srrh {
4088912Srrh 	char	*r;
4098912Srrh 	r = regname[regnumber];
4108912Srrh #ifdef SDB
4118912Srrh 	if (   (insoutfmt[0] == 'i')
4128912Srrh 	    && (regnumber >= 6)
4138912Srrh 	    && (regnumber <= 11)
4148912Srrh 	    && (adrtoregvar(regnumber, procp) != -1)) {
4158912Srrh 		r = sl_name;
4168912Srrh 	}
4178912Srrh #endif SDB
4188912Srrh 	return(r);
4198912Srrh }
4208912Srrh /*
4218912Srrh  *	print out a short literal
4228912Srrh  */
4238912Srrh shortliteral(mode, optype)
4248912Srrh 	u_char	mode;
4258912Srrh 	u_char	optype;
4268912Srrh {
4278912Srrh 	savevar((long)mode);
4288912Srrh 	switch(A_TYPEXT(optype)){
4298912Srrh 	case TYPF:
4308912Srrh 	case TYPD:
4318912Srrh 	case TYPG:
4328912Srrh 	case TYPH:
4338912Srrh 		printf("$%s", fltimm[mode]);
4348912Srrh 		break;
4358912Srrh 	default:
4368912Srrh #ifdef ADB
4378912Srrh 		printf("$%r", mode);
4388912Srrh #endif ADB
4398912Srrh #ifdef SDB
4408912Srrh 		printf("$%d", mode);
4418912Srrh #endif SDB
4428912Srrh 		break;
4438912Srrh 	}
4448912Srrh }
4453760Sroot 
4468912Srrh pcimmediate(mode, optype)
4478912Srrh 	u_char	mode;
4488912Srrh 	u_char	optype;
4493760Sroot {
4508912Srrh 	int	nbytes;
4518912Srrh 
4528912Srrh 	printc('$');
45312171Ssam 	if (mode == OC_CONS(OC_DAIREG, R_PC)){	/* PC absolute, always 4 bytes*/
4548912Srrh 		dispaddress(snarfreloc(4), mode);
4558912Srrh 		return;
4568912Srrh 	}
4578912Srrh 	nbytes = ty_nbyte[A_TYPEXT(optype)];
4588912Srrh 	if (! ty_NORELOC[A_TYPEXT(optype)]){
4598912Srrh 		dispaddress(snarfreloc(nbytes), mode);
4608912Srrh 		return;
4618912Srrh 	}
4628912Srrh 	bignumprint(nbytes, optype);
4638912Srrh }
4648912Srrh 
4658912Srrh bignumprint(nbytes, optype)
4668912Srrh 	int	nbytes;
4678912Srrh 	u_char	optype;
4688912Srrh {
4698912Srrh 	numberp	valuep;
4703760Sroot 	int	leading_zero = 1;
4718912Srrh 	REG	int	bindex;
4728912Srrh 	REG	int	nindex;
4738912Srrh 	REG	int	ch;
4743760Sroot 
4758912Srrh 	valuep = snarf(nbytes);
4768912Srrh 	switch(A_TYPEXT(optype)){
4778912Srrh 	case TYPF:
4788912Srrh 		printf("0f%f", valuep->num_num.numFf_float.Ff_value);
4798912Srrh 		break;
4808912Srrh 	case TYPD:
4818912Srrh 		printf("0d%f", valuep->num_num.numFd_float.Fd_value);
4828912Srrh 		break;
4838912Srrh 	case TYPG:
4848912Srrh 		printf("0g::"); goto qprint;
4858912Srrh 	case TYPH:
4868912Srrh 		printf("0h::"); goto qprint;
4878912Srrh 	case TYPQ:
4888912Srrh 	case TYPO:
4898912Srrh 	qprint:
4908912Srrh 		for (bindex = nbytes - 1; bindex >= 0; --bindex){
4918912Srrh 			for (nindex = 4; nindex >= 0; nindex -= 4){
4928912Srrh 				ch = (valuep->num_uchar[bindex] >> nindex);
4938912Srrh 				ch &= 0x0F;
4948912Srrh 				if ( ! (leading_zero &= (ch == 0) ) ){
4958912Srrh 					if (ch <= 0x09)
4968912Srrh 						printc(ch + '0');
4978912Srrh 					else
4988912Srrh 						printc(ch - 0x0A + 'a');
4998912Srrh 				}
5003760Sroot 			}
5013760Sroot 		}
5028912Srrh 		break;
5033760Sroot 	}
5043760Sroot }
5058912Srrh #ifdef SDB
5068912Srrh 
5078912Srrh L_INT inkdot(incr)
5088912Srrh 	int	incr;
5098912Srrh {
5108912Srrh 	L_INT		newdot;
5118912Srrh 
5128912Srrh 	newdot = dot + incr;
5138912Srrh 	return(newdot);
5148912Srrh }
5158912Srrh 
5168912Srrh printc(c)
5178912Srrh 	char c;
5188912Srrh {
5198912Srrh 	printf("%c", c);
5208912Srrh }
5218912Srrh 
5228912Srrh psymoff(v, regnumber, fmt)
5238912Srrh 	L_INT	v;
5248912Srrh 	char	*fmt;
5258912Srrh {
5268912Srrh 	struct	proct	*procp;
5278912Srrh 	REG	int diff;
5288912Srrh 	if (fmt[0] == 'i') {
5298912Srrh 		switch(regnumber){
5308912Srrh 		case 12:	/* parameter */
5318912Srrh 			if ((diff = adrtoparam((ADDR) v, adrtoprocp(dot)))
5328912Srrh 					!= -1) {
5338912Srrh 				printf("%s", sl_name);
5348912Srrh 				prdiff(diff);
5358912Srrh 				return(0);
5368912Srrh 			}
5378912Srrh 			break;
5388912Srrh 		case 13:	/* local */
5398912Srrh 			if ((diff = adrtolocal((ADDR) -v, adrtoprocp(dot))
5408912Srrh 					) != -1) {
5418912Srrh 				printf("%s", sl_name);
5428912Srrh 				prdiff(diff);
5438912Srrh 				return(0);
5448912Srrh 			}
5458912Srrh 			break;
5468912Srrh 		default:
5478912Srrh 			break;
5488912Srrh 		}
5498912Srrh 		if (v < firstdata) {
5508912Srrh 			if ((procp = adrtoprocp((ADDR) v)) != badproc) {
5518912Srrh 				prlnoff(procp, v);
5528912Srrh 				return(0);
5538912Srrh 			}
5548912Srrh 		} else {
5558912Srrh 			if ((diff = adrtoext((ADDR) v)) != -1) {
5568912Srrh 				printf("%s", sl_name);
5578912Srrh 				prdiff(diff);
5588912Srrh 				return(0);
5598912Srrh 			}
5608912Srrh 		}
5618912Srrh 	}
5628912Srrh 	prhex(v);
5638912Srrh 	return(1);
5648912Srrh }
5658912Srrh 
5668912Srrh prdiff(diff)
5678912Srrh {
5688912Srrh 	if (diff) {
5698912Srrh 		printf("+");
5708912Srrh 		prhex(diff);
5718912Srrh 	}
5728912Srrh }
5738912Srrh 
5748912Srrh #endif SDB
575