xref: /csrg-svn/old/as.vax/ascode.c (revision 13083)
15822Srrh /*
25822Srrh  *	Copyright (c) 1982 Regents of the University of California
35822Srrh  */
45822Srrh #ifndef lint
5*13083Srrh static char sccsid[] = "@(#)ascode.c 4.9 06/13/83";
65822Srrh #endif not lint
75822Srrh 
8592Sbill #include <stdio.h>
9592Sbill #include "as.h"
10592Sbill #include "assyms.h"
11592Sbill 
125822Srrh insout(opcode, ap, nact)
135822Srrh 	struct	Opcode	opcode;
145822Srrh 	struct	arg	*ap;
155822Srrh 	int	nact;
165822Srrh {
175822Srrh 	int	jxxflg;
185822Srrh 	reg	struct	instab	*ip;		/* the instruction */
195822Srrh 	reg	struct	arg	*ap_walk;	/* actual param walk */
205822Srrh 	reg	int	i;
215822Srrh 	reg	int	ap_type;		/* actual param type */
225822Srrh 	reg	int	ap_type_mask;		/* masked actual param */
23673Shenry 
24592Sbill 	jxxflg = nact;
25592Sbill 	if (nact < 0)
26592Sbill 		nact = -nact;
27592Sbill 	if (passno == 1) {
285822Srrh 		if (!(ITABCHECK(opcode)))
295822Srrh 			panic("Botched reference into itab");
305822Srrh 		ip = ITABFETCH(opcode);
315822Srrh 		if (nact < ip->i_nargs)
325822Srrh 			yyerror("Too few arguments");
335822Srrh 		if (nact > ip->i_nargs) {
345822Srrh 			yyerror("Too many arguments");
355822Srrh 			nact = ip->i_nargs;
365822Srrh 		}
37667Shenry 	    /*
38667Shenry 	     *	Check argument compatability with instruction template
39667Shenry 	     */
40667Shenry 	    for (ap_walk = ap, i = 1; i <= nact; ap_walk++, i++){
41673Shenry 		ap_type = ap_walk->a_atype;
42667Shenry 		ap_type_mask = ap_type & AMASK;
431746Shenry 		/*
445822Srrh 		 *	The switch value is >> by TYPLG so that the switch
451746Shenry 		 *	code is dense, not implemented as a sequence
461746Shenry 		 *	of branches but implemented as a casel.
471746Shenry 		 *	In addition, cases ACCI and ACCR are added to force
481746Shenry 		 *	dense switch code.
495822Srrh 		 *	switch on the type of fp
501746Shenry 		 */
515822Srrh 		switch( ((fetcharg(ip, i-1)) & ACCESSMASK) >> TYPLG){
525822Srrh 		case ACCI >> TYPLG:
535822Srrh 		case ACCR >> TYPLG:
541746Shenry 			break;
555822Srrh 		case ACCB >> TYPLG:
56667Shenry 			if ( !((ap_type_mask == AEXP) || (ap_type_mask == AIMM)) ){
57667Shenry 				yyerror("arg %d, branch displacement must be an expression",i);
58667Shenry 				return;
59667Shenry 			}
60667Shenry 			break;
615822Srrh 		case ACCA >> TYPLG:
62667Shenry 			switch(ap_type_mask){
63667Shenry 			case AREG:	yyerror("arg %d, addressing a register",i);
64667Shenry 					return;
65667Shenry 			case AIMM:	if ( !(ap_type & ASTAR) ){
66667Shenry 					 yyerror("arg %d, addressing an immediate operand",i);
67667Shenry 					 return;
68667Shenry 					}
69667Shenry 			}
70667Shenry 			break;
715822Srrh 		case ACCM >> TYPLG:
725822Srrh 		case ACCW >> TYPLG:
73667Shenry 			switch(ap_type_mask){
74667Shenry 			case AIMM:	if (!(ap_type&ASTAR)) {
75667Shenry 					 yyerror("arg %d, modifying a constant",i);
76667Shenry 					 return;
77667Shenry 					}
78667Shenry 			}
79667Shenry 			break;
80667Shenry 		}	/* end of the switch on fp_type */
81667Shenry 		if (ap_type & AINDX) {
82667Shenry 			if (ap_walk->a_areg2==0xF) {
83667Shenry 				yyerror("arg %d, PC used as index",i);
84667Shenry 				return;
85667Shenry 			}
86667Shenry 			switch(ap_type_mask){
87667Shenry 			case AREG:	yyerror("arg %d, indexing the register file",i);
88667Shenry 					return;
89667Shenry 			case AIMM:	yyerror("arg %d, indexing a constant",i);
90667Shenry 					return;
91673Shenry 			case ADECR:
92673Shenry 			case AINCR:	if (ap_walk->a_areg1==ap_walk->a_areg2) {
93667Shenry 						yyerror("arg %d, indexing with modified register",i);
94667Shenry 						return;
95667Shenry 					}
96667Shenry 					break;
97667Shenry 			}	/* end of switch on ap_type_mask */
98667Shenry 		} /* end of AINDX */
99667Shenry 	   }
100667Shenry 	} /* both passes here */
101592Sbill 	if (jxxflg < 0)
1025822Srrh 		ijxout(opcode, ap, nact);
1035822Srrh 	else
1045822Srrh 		putins(opcode, ap, nact);
105592Sbill }
106592Sbill 
107592Sbill extern	int d124;
108592Sbill 
1095822Srrh putins(opcode, ap, n)
1105822Srrh 	struct	Opcode	opcode;
111592Sbill 	register struct arg *ap;
1125822Srrh 	int	n;			/* Must be positive */
113592Sbill {
1145822Srrh 	reg	struct exp 	*xp;
1155822Srrh 	reg	int 	argtype;
1165822Srrh 		int 	i;
1175822Srrh 		int	reloc_how;
1185822Srrh 		int	value;
119592Sbill 
120592Sbill #ifdef DEBUG
121592Sbill 	fflush(stdout);
122592Sbill #endif
123592Sbill 	if (passno == 2)
124592Sbill 		goto PASS2;
125592Sbill 
1265822Srrh 	dotp->e_xvalue += n;		/* at least one byte per arg */
1275822Srrh 	switch(opcode.Op_eopcode){
1285822Srrh 	case NEW:
1295822Srrh 	case CORE:
1305822Srrh 		dotp->e_xvalue += 1;	/* 1 byte opcode */
1315822Srrh 		break;
1325822Srrh 	case ESCD:
1335822Srrh 	case ESCF:
1345822Srrh 		dotp->e_xvalue += 2;	/* 2 byte opcode */
1355822Srrh 		break;
1365822Srrh 	default:
1375822Srrh 		panic("Bad escape opcode");
1385822Srrh 	}
1395822Srrh 
140629Shenry 	for (i=0; i<n; i++,ap++) {	/* some args take more than 1 byte */
141853Shenry 	    argtype = ap->a_atype;
142853Shenry 	    if (argtype & AINDX)
143629Shenry 		dotp->e_xvalue++;
1441746Shenry 	    /*
1451746Shenry 	     *	This switch has been fixed by enumerating the no action
1461746Shenry 	     *	alternatives (those that have 1 one byte of code)
1471746Shenry 	     *	so that a casel instruction is emitted.
1481746Shenry 	     */
149853Shenry 	    switch (argtype&~(AINDX|ASTAR)) {
1501746Shenry 		case AREG:
1511746Shenry 		case ABASE:
1521746Shenry 		case ADECR:
1531746Shenry 		case AINCR:
1541746Shenry 			break;
155592Sbill 		case AEXP:
1565822Srrh 			argtype = fetcharg(ITABFETCH(opcode), i);
1575822Srrh 			if (argtype == A_BB)
158592Sbill 				break;
1595822Srrh 			if (argtype == A_BW){
160629Shenry 				dotp->e_xvalue++;
161592Sbill 				break;
162592Sbill 			}
163592Sbill 			/*
164592Sbill 			 *	Reduces to PC relative
165592Sbill 			 */
166629Shenry 			dotp->e_xvalue += ap->a_dispsize;
167592Sbill 			break;
168592Sbill 
169592Sbill 		case ADISP:
170629Shenry 			xp=ap->a_xp;
171629Shenry 			if ((xp->e_xtype&XTYPE)!=XABS || xp->e_xtype&XFORW){
172629Shenry 				dotp->e_xvalue += ap->a_dispsize;
173592Sbill 				break;
174592Sbill 			}
175853Shenry 			if (xp->e_xvalue==0 && !(argtype&ASTAR))
176592Sbill 				break;
1775822Srrh 			dotp->e_xvalue += 1;
1785822Srrh 			if (ISBYTE(xp->e_xvalue))
1795822Srrh 				break;
1805822Srrh 			dotp->e_xvalue += 1;
1815822Srrh 			if (ISWORD(xp->e_xvalue))
1825822Srrh 				break;
1835822Srrh 			dotp->e_xvalue += 2;
184592Sbill 			break;
185592Sbill 
186592Sbill 		case AIMM:
1875822Srrh 			if (ap->a_atype&ASTAR) {
1885822Srrh 				argtype=TYPL;
1895822Srrh 			} else {
1905822Srrh 				argtype = fetcharg(ITABFETCH(opcode), i);
191853Shenry 				if (argtype&ACCA)
192853Shenry 					argtype = TYPL;
193592Sbill 				else
194853Shenry 					argtype &= TYPMASK;
195629Shenry 				xp = ap->a_xp;
1965822Srrh 				if (immconstant(ap->a_xp, argtype, &value))
1975822Srrh 					break;
198592Sbill 			}
1995822Srrh 			dotp->e_xvalue += ty_nbyte[argtype];
200592Sbill 	    }	/*end of the switch on the type*/
201592Sbill 	}	/*end of looping for all arguments*/
202592Sbill 	return;
203592Sbill 
204592Sbill PASS2:
2055822Srrh 	/*
2065822Srrh 	 *	Output the opcode
2075822Srrh 	 */
2085822Srrh 	switch(opcode.Op_eopcode){
2095822Srrh 	case NEW:
2105822Srrh 		nnewopcodes++;
2115822Srrh 		break;
2125822Srrh 	case ESCD:
2135822Srrh 	case ESCF:
2145822Srrh 		nGHopcodes++;
2155822Srrh 		Outb(opcode.Op_eopcode);
2165822Srrh 		break;
2175822Srrh 	case CORE:
2185822Srrh 		break;
2195822Srrh 	default:
2205822Srrh 		panic("Bad escape opcode");
2215822Srrh 	}
2225822Srrh 	Outb(opcode.Op_popcode);
223592Sbill 
224592Sbill 	for (i=0; i<n; i++,ap++) {/* now for the arguments */
225853Shenry 		argtype=ap->a_atype;
226629Shenry 		xp=ap->a_xp;
227673Shenry 		reloc_how = TYPNONE;
228853Shenry 		if (argtype&AINDX) {
2295822Srrh 			{ Outb(0x40 | ap->a_areg2); }
230853Shenry 			argtype &= ~AINDX;
231592Sbill 		}
232853Shenry 		if (argtype&ASTAR) {
233629Shenry 			ap->a_areg1 |= 0x10;
234853Shenry 			argtype &= ~ASTAR;
235592Sbill 		}
236853Shenry 		switch (argtype) {
237592Sbill 		case AREG:		/* %r */
238629Shenry 			ap->a_areg1 |= 0x50;
239592Sbill 			break;
240592Sbill 		case ABASE:		/* (%r) */
241629Shenry 			ap->a_areg1 |= 0x60;
242592Sbill 			break;
243592Sbill 		case ADECR: 		/* -(%r) */
244629Shenry 			ap->a_areg1 |= 0x70;
245592Sbill 			break;
246665Shenry 		case AINCR:		/* (%r)+ */
247629Shenry 			ap->a_areg1 |= 0x80;
248592Sbill 			break;
249592Sbill 		case AEXP: /* expr */
2505822Srrh 			argtype = fetcharg(ITABFETCH(opcode), i);
2515822Srrh 			if (argtype == A_BB) {
252853Shenry 				ap->a_areg1 = argtype =
253629Shenry 					xp->e_xvalue - (dotp->e_xvalue + 1);
2545822Srrh 				if (xp->e_xtype & XXTRN)
2555822Srrh 					yywarning("%s: destination label is external",
2565822Srrh 						ITABFETCH(opcode)->s_name);
2575822Srrh 				if (!ISBYTE(argtype))
258*13083Srrh 					yyerror("%s: Branch too far(%db): try -J flag",
2595822Srrh 						ITABFETCH(opcode)->s_name,
2605822Srrh 						argtype);
2615822Srrh 				break;
262592Sbill 			}
2635822Srrh 			if (argtype == A_BW) {
264853Shenry 				ap->a_areg1 = argtype = xp->e_xvalue
265629Shenry 					-= dotp->e_xvalue + 2;
2665822Srrh 				if (xp->e_xtype & XXTRN)
2675822Srrh 					yywarning("%s: destination label is external",
2685822Srrh 						ITABFETCH(opcode)->s_name);
269629Shenry 				xp->e_xtype = XABS;
2705822Srrh 				if (!ISWORD(argtype))
271*13083Srrh 					yyerror("%s: Branch too far(%db): try -J flag",
2725822Srrh 						ITABFETCH(opcode)->s_name,
2735822Srrh 						argtype);
274853Shenry 				xp->e_xvalue = argtype>>8;
275673Shenry 				reloc_how = TYPB;
276592Sbill 				break;
277592Sbill 			}
278592Sbill 			/* reduces to expr(pc) mode */
279629Shenry 			ap->a_areg1 |= (0xAF + mod124[ap->a_dispsize]);
280673Shenry 			reloc_how = type_124[ap->a_dispsize] + RELOC_PCREL;
281592Sbill 			break;
282592Sbill 
283592Sbill 		case ADISP: /* expr(%r) */
284629Shenry 			ap->a_areg1 |= 0xA0;
285629Shenry 			if ((xp->e_xtype&XTYPE)!=XABS || xp->e_xtype&XFORW){
286629Shenry 				ap->a_areg1 += mod124[ap->a_dispsize];
287673Shenry 				reloc_how = type_124[ap->a_dispsize];
288592Sbill 				break;
289592Sbill 			}
290629Shenry 			if (xp->e_xvalue==0 && !(ap->a_areg1&0x10)) {
291629Shenry 				ap->a_areg1 ^= 0xC0;
292592Sbill 				break;
293592Sbill 			}
294673Shenry 			reloc_how = TYPB;
2955822Srrh 			if (ISBYTE(xp->e_xvalue))
2965822Srrh 				break;
2975822Srrh 			ap->a_areg1 += 0x20;
2985822Srrh 			reloc_how = TYPW;
2995822Srrh 			if (ISWORD(xp->e_xvalue))
3005822Srrh 				break;
3015822Srrh 			ap->a_areg1 += 0x20;
3025822Srrh 			reloc_how = TYPL;
303592Sbill 			break;
304592Sbill 
305592Sbill 		case AIMM:  /* $expr */
3065822Srrh 			if (ap->a_atype&ASTAR) {
307853Shenry 				argtype=TYPL;
3085822Srrh 			} else {
3095822Srrh 				argtype = fetcharg(ITABFETCH(opcode), i);
310853Shenry 				if (argtype&ACCA)
3115822Srrh 					argtype = TYPL;
312592Sbill 				else
313853Shenry 					argtype &= TYPMASK;
3145822Srrh 				if (immconstant(xp, argtype, &value)){
3155822Srrh 					reloc_how = TYPNONE;
3165822Srrh 					ap->a_areg1 = value;
317592Sbill 					break;
318592Sbill 				}
319592Sbill 			}
320629Shenry 			ap->a_areg1 |= 0x8F;
321853Shenry 			reloc_how = argtype;
322592Sbill 			break;
323592Sbill 
324853Shenry 		}	/*end of the switch on argtype*/
325592Sbill 		/*
326592Sbill 		 *	use the first byte to describe the argument
327592Sbill 		 */
3285822Srrh 		Outb(ap->a_areg1);
329592Sbill #ifdef VMS
330592Sbill 		if ((vms_obj_ptr-sobuf) > 400) {
331592Sbill 			write(objfil,sobuf,vms_obj_ptr-sobuf);
332592Sbill 			vms_obj_ptr=sobuf+1;
333592Sbill 		}
334592Sbill #endif VMS
335673Shenry 		if (reloc_how != TYPNONE)
336673Shenry 			outrel(xp, reloc_how);
337592Sbill 	}	/*end of the for to pick up all arguments*/
338592Sbill }
3395822Srrh /*
3405822Srrh  *	Is xp an immediate constant?
3415822Srrh  *	argtype: how the instruction will interpret the bytes
3425822Srrh  *	xp->e_number.num_tag ("numtype"): the kind of number given
3435822Srrh  *
3445822Srrh  *	Use the following table:
3455822Srrh  *	float: TYPF, TYPD, TYPG, TYPH
3465822Srrh  *	quad: TYPQ, TYPO
3475822Srrh  *	int: TYPG, TYPW, TYPL
3485822Srrh  *
3495822Srrh  *				numtype
3505822Srrh  *	argtype		float	quad	int
3515822Srrh  *
3525822Srrh  *	float		slitflt	slitflt	slitflt
3535822Srrh  *	quad		0	0	0
3545822Srrh  *	int		0..63	0	0..63
3555822Srrh  *
3565822Srrh  *	Where the table entry implies the predicate to return.
3575822Srrh  */
3585822Srrh #define	IMMFLT	1		/* these flags are not used by anybody (yet) */
3595822Srrh #define	IMMINT	2
3605822Srrh 
3615822Srrh int immconstant(xp, argtype, valuep)
3625822Srrh 	reg	struct	exp	*xp;
3635822Srrh 		int	argtype;
3645822Srrh 		int	*valuep;
3655822Srrh {
3665822Srrh 	reg	int	back = 0;
3675822Srrh 		int	numtype;
3685822Srrh 	reg	int	fits;
3695822Srrh 
3705822Srrh 	if ((xp->e_xtype & XTYPE) != XABS)
3715822Srrh 		return(0);
3725822Srrh 	if ((xp->e_xtype & XFORW) != 0)
3735822Srrh 		return(0);
3745822Srrh 	numtype = xp->e_number.num_tag;
3755822Srrh 
3765822Srrh 	fits = 1;
3775822Srrh 	if (passno == 2) switch(argtype){
3785822Srrh 	case TYPB:
3795822Srrh 		switch(numtype){
3805822Srrh 		default:	fits = 0; break;
3815822Srrh 		case TYPB:	fits = 1; break;
3825822Srrh 		case TYPW:
3835822Srrh 		case TYPL:
3845822Srrh 			fits = ISBYTE(xp->e_xvalue) || ISUBYTE(xp->e_xvalue);
3855822Srrh 			break;
3865822Srrh 		}
3875822Srrh 		break;
3885822Srrh 	case TYPW:
3895822Srrh 		switch(numtype){
3905822Srrh 		default:	fits = 0; break;
3915822Srrh 		case TYPB:
3925822Srrh 		case TYPW:	fits = 1; break;
3935822Srrh 		case TYPL:
3945822Srrh 			fits = ISWORD(xp->e_xvalue) || ISUWORD(xp->e_xvalue);
3955822Srrh 			break;
3965822Srrh 		}
3975822Srrh 		break;
3985822Srrh 	case TYPF:
3995822Srrh 		if (numtype == TYPD){	/* same format for first 32 bits */
4005822Srrh 			fits = 1;
4015822Srrh 			break;
4025822Srrh 		}
4035822Srrh 		/*FALLTHROUGH*/
4045822Srrh 	default:
4055822Srrh 		fits = ty_nbyte[argtype] >= ty_nbyte[numtype];
4065822Srrh 	}
4075822Srrh 	if (!fits){
4085822Srrh 	  yywarning("Immediate constant type %s mismatches instruction type %s",
4095822Srrh 		ty_string[numtype],
4105822Srrh 		ty_string[argtype]);
4115822Srrh 	}
4125822Srrh 
4135822Srrh 	switch(argtype){
4145822Srrh 	case TYPF:
4155822Srrh 	case TYPG:
4165822Srrh 	case TYPD:
4175822Srrh 	case TYPH:
4185822Srrh 		back = slitflt(xp->e_number, argtype, valuep);
4195822Srrh 		break;
4205822Srrh 	case TYPO:
4215822Srrh 	case TYPQ:
4225822Srrh 		back = 0;
4235822Srrh 		break;
4245822Srrh 	case TYPB:
4255822Srrh 	case TYPW:
4265822Srrh 	case TYPL:
4275822Srrh 		switch(numtype){
4285822Srrh 		case TYPO:
4295822Srrh 		case TYPQ:
4305822Srrh 			back = 0;
4315822Srrh 			break;
4325822Srrh 		default:
4335822Srrh 			*valuep = xp->e_xvalue;
4345822Srrh 			back = ISLIT(xp->e_xvalue);
4355822Srrh 			break;
4365822Srrh 		}
4375822Srrh 		break;
4385822Srrh 	}
4395822Srrh 	return(back);
4405822Srrh }
441