xref: /csrg-svn/old/as.vax/ascode.c (revision 18714)
15822Srrh /*
2*18714Sdist  * Copyright (c) 1982 Regents of the University of California.
3*18714Sdist  * All rights reserved.  The Berkeley software License Agreement
4*18714Sdist  * specifies the terms and conditions for redistribution.
55822Srrh  */
6*18714Sdist 
75822Srrh #ifndef lint
8*18714Sdist static char sccsid[] = "@(#)ascode.c	5.1 (Berkeley) 04/24/85";
95822Srrh #endif not lint
105822Srrh 
11592Sbill #include <stdio.h>
12592Sbill #include "as.h"
13592Sbill #include "assyms.h"
14592Sbill 
155822Srrh insout(opcode, ap, nact)
165822Srrh 	struct	Opcode	opcode;
175822Srrh 	struct	arg	*ap;
185822Srrh 	int	nact;
195822Srrh {
205822Srrh 	int	jxxflg;
215822Srrh 	reg	struct	instab	*ip;		/* the instruction */
225822Srrh 	reg	struct	arg	*ap_walk;	/* actual param walk */
235822Srrh 	reg	int	i;
245822Srrh 	reg	int	ap_type;		/* actual param type */
255822Srrh 	reg	int	ap_type_mask;		/* masked actual param */
26673Shenry 
27592Sbill 	jxxflg = nact;
28592Sbill 	if (nact < 0)
29592Sbill 		nact = -nact;
30592Sbill 	if (passno == 1) {
315822Srrh 		if (!(ITABCHECK(opcode)))
325822Srrh 			panic("Botched reference into itab");
335822Srrh 		ip = ITABFETCH(opcode);
345822Srrh 		if (nact < ip->i_nargs)
355822Srrh 			yyerror("Too few arguments");
365822Srrh 		if (nact > ip->i_nargs) {
375822Srrh 			yyerror("Too many arguments");
385822Srrh 			nact = ip->i_nargs;
395822Srrh 		}
40667Shenry 	    /*
41667Shenry 	     *	Check argument compatability with instruction template
42667Shenry 	     */
43667Shenry 	    for (ap_walk = ap, i = 1; i <= nact; ap_walk++, i++){
44673Shenry 		ap_type = ap_walk->a_atype;
45667Shenry 		ap_type_mask = ap_type & AMASK;
461746Shenry 		/*
475822Srrh 		 *	The switch value is >> by TYPLG so that the switch
481746Shenry 		 *	code is dense, not implemented as a sequence
491746Shenry 		 *	of branches but implemented as a casel.
501746Shenry 		 *	In addition, cases ACCI and ACCR are added to force
511746Shenry 		 *	dense switch code.
525822Srrh 		 *	switch on the type of fp
531746Shenry 		 */
545822Srrh 		switch( ((fetcharg(ip, i-1)) & ACCESSMASK) >> TYPLG){
555822Srrh 		case ACCI >> TYPLG:
565822Srrh 		case ACCR >> TYPLG:
571746Shenry 			break;
585822Srrh 		case ACCB >> TYPLG:
59667Shenry 			if ( !((ap_type_mask == AEXP) || (ap_type_mask == AIMM)) ){
60667Shenry 				yyerror("arg %d, branch displacement must be an expression",i);
61667Shenry 				return;
62667Shenry 			}
63667Shenry 			break;
645822Srrh 		case ACCA >> TYPLG:
65667Shenry 			switch(ap_type_mask){
66667Shenry 			case AREG:	yyerror("arg %d, addressing a register",i);
67667Shenry 					return;
68667Shenry 			case AIMM:	if ( !(ap_type & ASTAR) ){
69667Shenry 					 yyerror("arg %d, addressing an immediate operand",i);
70667Shenry 					 return;
71667Shenry 					}
72667Shenry 			}
73667Shenry 			break;
745822Srrh 		case ACCM >> TYPLG:
755822Srrh 		case ACCW >> TYPLG:
76667Shenry 			switch(ap_type_mask){
77667Shenry 			case AIMM:	if (!(ap_type&ASTAR)) {
78667Shenry 					 yyerror("arg %d, modifying a constant",i);
79667Shenry 					 return;
80667Shenry 					}
81667Shenry 			}
82667Shenry 			break;
83667Shenry 		}	/* end of the switch on fp_type */
84667Shenry 		if (ap_type & AINDX) {
85667Shenry 			if (ap_walk->a_areg2==0xF) {
86667Shenry 				yyerror("arg %d, PC used as index",i);
87667Shenry 				return;
88667Shenry 			}
89667Shenry 			switch(ap_type_mask){
90667Shenry 			case AREG:	yyerror("arg %d, indexing the register file",i);
91667Shenry 					return;
92667Shenry 			case AIMM:	yyerror("arg %d, indexing a constant",i);
93667Shenry 					return;
94673Shenry 			case ADECR:
95673Shenry 			case AINCR:	if (ap_walk->a_areg1==ap_walk->a_areg2) {
96667Shenry 						yyerror("arg %d, indexing with modified register",i);
97667Shenry 						return;
98667Shenry 					}
99667Shenry 					break;
100667Shenry 			}	/* end of switch on ap_type_mask */
101667Shenry 		} /* end of AINDX */
102667Shenry 	   }
103667Shenry 	} /* both passes here */
104592Sbill 	if (jxxflg < 0)
1055822Srrh 		ijxout(opcode, ap, nact);
1065822Srrh 	else
1075822Srrh 		putins(opcode, ap, nact);
108592Sbill }
109592Sbill 
110592Sbill extern	int d124;
111592Sbill 
1125822Srrh putins(opcode, ap, n)
1135822Srrh 	struct	Opcode	opcode;
114592Sbill 	register struct arg *ap;
1155822Srrh 	int	n;			/* Must be positive */
116592Sbill {
1175822Srrh 	reg	struct exp 	*xp;
1185822Srrh 	reg	int 	argtype;
1195822Srrh 		int 	i;
1205822Srrh 		int	reloc_how;
1215822Srrh 		int	value;
122592Sbill 
123592Sbill #ifdef DEBUG
124592Sbill 	fflush(stdout);
125592Sbill #endif
126592Sbill 	if (passno == 2)
127592Sbill 		goto PASS2;
128592Sbill 
1295822Srrh 	dotp->e_xvalue += n;		/* at least one byte per arg */
1305822Srrh 	switch(opcode.Op_eopcode){
1315822Srrh 	case NEW:
1325822Srrh 	case CORE:
1335822Srrh 		dotp->e_xvalue += 1;	/* 1 byte opcode */
1345822Srrh 		break;
1355822Srrh 	case ESCD:
1365822Srrh 	case ESCF:
1375822Srrh 		dotp->e_xvalue += 2;	/* 2 byte opcode */
1385822Srrh 		break;
1395822Srrh 	default:
1405822Srrh 		panic("Bad escape opcode");
1415822Srrh 	}
1425822Srrh 
143629Shenry 	for (i=0; i<n; i++,ap++) {	/* some args take more than 1 byte */
144853Shenry 	    argtype = ap->a_atype;
145853Shenry 	    if (argtype & AINDX)
146629Shenry 		dotp->e_xvalue++;
1471746Shenry 	    /*
1481746Shenry 	     *	This switch has been fixed by enumerating the no action
1491746Shenry 	     *	alternatives (those that have 1 one byte of code)
1501746Shenry 	     *	so that a casel instruction is emitted.
1511746Shenry 	     */
152853Shenry 	    switch (argtype&~(AINDX|ASTAR)) {
1531746Shenry 		case AREG:
1541746Shenry 		case ABASE:
1551746Shenry 		case ADECR:
1561746Shenry 		case AINCR:
1571746Shenry 			break;
158592Sbill 		case AEXP:
1595822Srrh 			argtype = fetcharg(ITABFETCH(opcode), i);
1605822Srrh 			if (argtype == A_BB)
161592Sbill 				break;
1625822Srrh 			if (argtype == A_BW){
163629Shenry 				dotp->e_xvalue++;
164592Sbill 				break;
165592Sbill 			}
166592Sbill 			/*
167592Sbill 			 *	Reduces to PC relative
168592Sbill 			 */
169629Shenry 			dotp->e_xvalue += ap->a_dispsize;
170592Sbill 			break;
171592Sbill 
172592Sbill 		case ADISP:
173629Shenry 			xp=ap->a_xp;
174629Shenry 			if ((xp->e_xtype&XTYPE)!=XABS || xp->e_xtype&XFORW){
175629Shenry 				dotp->e_xvalue += ap->a_dispsize;
176592Sbill 				break;
177592Sbill 			}
178853Shenry 			if (xp->e_xvalue==0 && !(argtype&ASTAR))
179592Sbill 				break;
1805822Srrh 			dotp->e_xvalue += 1;
1815822Srrh 			if (ISBYTE(xp->e_xvalue))
1825822Srrh 				break;
1835822Srrh 			dotp->e_xvalue += 1;
1845822Srrh 			if (ISWORD(xp->e_xvalue))
1855822Srrh 				break;
1865822Srrh 			dotp->e_xvalue += 2;
187592Sbill 			break;
188592Sbill 
189592Sbill 		case AIMM:
1905822Srrh 			if (ap->a_atype&ASTAR) {
1915822Srrh 				argtype=TYPL;
1925822Srrh 			} else {
1935822Srrh 				argtype = fetcharg(ITABFETCH(opcode), i);
194853Shenry 				if (argtype&ACCA)
195853Shenry 					argtype = TYPL;
196592Sbill 				else
197853Shenry 					argtype &= TYPMASK;
198629Shenry 				xp = ap->a_xp;
1995822Srrh 				if (immconstant(ap->a_xp, argtype, &value))
2005822Srrh 					break;
201592Sbill 			}
2025822Srrh 			dotp->e_xvalue += ty_nbyte[argtype];
203592Sbill 	    }	/*end of the switch on the type*/
204592Sbill 	}	/*end of looping for all arguments*/
205592Sbill 	return;
206592Sbill 
207592Sbill PASS2:
2085822Srrh 	/*
2095822Srrh 	 *	Output the opcode
2105822Srrh 	 */
2115822Srrh 	switch(opcode.Op_eopcode){
2125822Srrh 	case NEW:
2135822Srrh 		nnewopcodes++;
2145822Srrh 		break;
2155822Srrh 	case ESCD:
2165822Srrh 	case ESCF:
2175822Srrh 		nGHopcodes++;
2185822Srrh 		Outb(opcode.Op_eopcode);
2195822Srrh 		break;
2205822Srrh 	case CORE:
2215822Srrh 		break;
2225822Srrh 	default:
2235822Srrh 		panic("Bad escape opcode");
2245822Srrh 	}
2255822Srrh 	Outb(opcode.Op_popcode);
226592Sbill 
227592Sbill 	for (i=0; i<n; i++,ap++) {/* now for the arguments */
228853Shenry 		argtype=ap->a_atype;
229629Shenry 		xp=ap->a_xp;
230673Shenry 		reloc_how = TYPNONE;
231853Shenry 		if (argtype&AINDX) {
2325822Srrh 			{ Outb(0x40 | ap->a_areg2); }
233853Shenry 			argtype &= ~AINDX;
234592Sbill 		}
235853Shenry 		if (argtype&ASTAR) {
236629Shenry 			ap->a_areg1 |= 0x10;
237853Shenry 			argtype &= ~ASTAR;
238592Sbill 		}
239853Shenry 		switch (argtype) {
240592Sbill 		case AREG:		/* %r */
241629Shenry 			ap->a_areg1 |= 0x50;
242592Sbill 			break;
243592Sbill 		case ABASE:		/* (%r) */
244629Shenry 			ap->a_areg1 |= 0x60;
245592Sbill 			break;
246592Sbill 		case ADECR: 		/* -(%r) */
247629Shenry 			ap->a_areg1 |= 0x70;
248592Sbill 			break;
249665Shenry 		case AINCR:		/* (%r)+ */
250629Shenry 			ap->a_areg1 |= 0x80;
251592Sbill 			break;
252592Sbill 		case AEXP: /* expr */
2535822Srrh 			argtype = fetcharg(ITABFETCH(opcode), i);
2545822Srrh 			if (argtype == A_BB) {
255853Shenry 				ap->a_areg1 = argtype =
256629Shenry 					xp->e_xvalue - (dotp->e_xvalue + 1);
25716764Sralph 				if ((xp->e_xtype & XTYPE) == XUNDEF)
2585822Srrh 					yywarning("%s: destination label is external",
25913511Srrh 						FETCHNAME(ITABFETCH(opcode)));
2605822Srrh 				if (!ISBYTE(argtype))
26113083Srrh 					yyerror("%s: Branch too far(%db): try -J flag",
26213511Srrh 						FETCHNAME(ITABFETCH(opcode)),
2635822Srrh 						argtype);
2645822Srrh 				break;
265592Sbill 			}
2665822Srrh 			if (argtype == A_BW) {
267853Shenry 				ap->a_areg1 = argtype = xp->e_xvalue
268629Shenry 					-= dotp->e_xvalue + 2;
26916764Sralph 				if ((xp->e_xtype & XTYPE) == XUNDEF)
2705822Srrh 					yywarning("%s: destination label is external",
27113511Srrh 						FETCHNAME(ITABFETCH(opcode)));
272629Shenry 				xp->e_xtype = XABS;
2735822Srrh 				if (!ISWORD(argtype))
27413083Srrh 					yyerror("%s: Branch too far(%db): try -J flag",
27513511Srrh 						FETCHNAME(ITABFETCH(opcode)),
2765822Srrh 						argtype);
277853Shenry 				xp->e_xvalue = argtype>>8;
278673Shenry 				reloc_how = TYPB;
279592Sbill 				break;
280592Sbill 			}
281592Sbill 			/* reduces to expr(pc) mode */
282629Shenry 			ap->a_areg1 |= (0xAF + mod124[ap->a_dispsize]);
283673Shenry 			reloc_how = type_124[ap->a_dispsize] + RELOC_PCREL;
284592Sbill 			break;
285592Sbill 
286592Sbill 		case ADISP: /* expr(%r) */
287629Shenry 			ap->a_areg1 |= 0xA0;
288629Shenry 			if ((xp->e_xtype&XTYPE)!=XABS || xp->e_xtype&XFORW){
289629Shenry 				ap->a_areg1 += mod124[ap->a_dispsize];
290673Shenry 				reloc_how = type_124[ap->a_dispsize];
291592Sbill 				break;
292592Sbill 			}
293629Shenry 			if (xp->e_xvalue==0 && !(ap->a_areg1&0x10)) {
294629Shenry 				ap->a_areg1 ^= 0xC0;
295592Sbill 				break;
296592Sbill 			}
297673Shenry 			reloc_how = TYPB;
2985822Srrh 			if (ISBYTE(xp->e_xvalue))
2995822Srrh 				break;
3005822Srrh 			ap->a_areg1 += 0x20;
3015822Srrh 			reloc_how = TYPW;
3025822Srrh 			if (ISWORD(xp->e_xvalue))
3035822Srrh 				break;
3045822Srrh 			ap->a_areg1 += 0x20;
3055822Srrh 			reloc_how = TYPL;
306592Sbill 			break;
307592Sbill 
308592Sbill 		case AIMM:  /* $expr */
3095822Srrh 			if (ap->a_atype&ASTAR) {
310853Shenry 				argtype=TYPL;
3115822Srrh 			} else {
3125822Srrh 				argtype = fetcharg(ITABFETCH(opcode), i);
313853Shenry 				if (argtype&ACCA)
3145822Srrh 					argtype = TYPL;
315592Sbill 				else
316853Shenry 					argtype &= TYPMASK;
3175822Srrh 				if (immconstant(xp, argtype, &value)){
3185822Srrh 					reloc_how = TYPNONE;
3195822Srrh 					ap->a_areg1 = value;
320592Sbill 					break;
321592Sbill 				}
322592Sbill 			}
323629Shenry 			ap->a_areg1 |= 0x8F;
324853Shenry 			reloc_how = argtype;
325592Sbill 			break;
326592Sbill 
327853Shenry 		}	/*end of the switch on argtype*/
328592Sbill 		/*
329592Sbill 		 *	use the first byte to describe the argument
330592Sbill 		 */
3315822Srrh 		Outb(ap->a_areg1);
332673Shenry 		if (reloc_how != TYPNONE)
333673Shenry 			outrel(xp, reloc_how);
334592Sbill 	}	/*end of the for to pick up all arguments*/
335592Sbill }
3365822Srrh /*
3375822Srrh  *	Is xp an immediate constant?
3385822Srrh  *	argtype: how the instruction will interpret the bytes
3395822Srrh  *	xp->e_number.num_tag ("numtype"): the kind of number given
3405822Srrh  *
3415822Srrh  *	Use the following table:
3425822Srrh  *	float: TYPF, TYPD, TYPG, TYPH
3435822Srrh  *	quad: TYPQ, TYPO
3445822Srrh  *	int: TYPG, TYPW, TYPL
3455822Srrh  *
3465822Srrh  *				numtype
3475822Srrh  *	argtype		float	quad	int
3485822Srrh  *
3495822Srrh  *	float		slitflt	slitflt	slitflt
3505822Srrh  *	quad		0	0	0
3515822Srrh  *	int		0..63	0	0..63
3525822Srrh  *
3535822Srrh  *	Where the table entry implies the predicate to return.
3545822Srrh  */
3555822Srrh #define	IMMFLT	1		/* these flags are not used by anybody (yet) */
3565822Srrh #define	IMMINT	2
3575822Srrh 
immconstant(xp,argtype,valuep)3585822Srrh int immconstant(xp, argtype, valuep)
3595822Srrh 	reg	struct	exp	*xp;
3605822Srrh 		int	argtype;
3615822Srrh 		int	*valuep;
3625822Srrh {
3635822Srrh 	reg	int	back = 0;
3645822Srrh 		int	numtype;
3655822Srrh 	reg	int	fits;
3665822Srrh 
3675822Srrh 	if ((xp->e_xtype & XTYPE) != XABS)
3685822Srrh 		return(0);
3695822Srrh 	if ((xp->e_xtype & XFORW) != 0)
3705822Srrh 		return(0);
3715822Srrh 	numtype = xp->e_number.num_tag;
3725822Srrh 
3735822Srrh 	fits = 1;
3745822Srrh 	if (passno == 2) switch(argtype){
3755822Srrh 	case TYPB:
3765822Srrh 		switch(numtype){
3775822Srrh 		default:	fits = 0; break;
3785822Srrh 		case TYPB:	fits = 1; break;
3795822Srrh 		case TYPW:
3805822Srrh 		case TYPL:
3815822Srrh 			fits = ISBYTE(xp->e_xvalue) || ISUBYTE(xp->e_xvalue);
3825822Srrh 			break;
3835822Srrh 		}
3845822Srrh 		break;
3855822Srrh 	case TYPW:
3865822Srrh 		switch(numtype){
3875822Srrh 		default:	fits = 0; break;
3885822Srrh 		case TYPB:
3895822Srrh 		case TYPW:	fits = 1; break;
3905822Srrh 		case TYPL:
3915822Srrh 			fits = ISWORD(xp->e_xvalue) || ISUWORD(xp->e_xvalue);
3925822Srrh 			break;
3935822Srrh 		}
3945822Srrh 		break;
3955822Srrh 	case TYPF:
3965822Srrh 		if (numtype == TYPD){	/* same format for first 32 bits */
3975822Srrh 			fits = 1;
3985822Srrh 			break;
3995822Srrh 		}
4005822Srrh 		/*FALLTHROUGH*/
4015822Srrh 	default:
4025822Srrh 		fits = ty_nbyte[argtype] >= ty_nbyte[numtype];
4035822Srrh 	}
4045822Srrh 	if (!fits){
4055822Srrh 	  yywarning("Immediate constant type %s mismatches instruction type %s",
4065822Srrh 		ty_string[numtype],
4075822Srrh 		ty_string[argtype]);
4085822Srrh 	}
4095822Srrh 
4105822Srrh 	switch(argtype){
4115822Srrh 	case TYPF:
4125822Srrh 	case TYPG:
4135822Srrh 	case TYPD:
4145822Srrh 	case TYPH:
4155822Srrh 		back = slitflt(xp->e_number, argtype, valuep);
4165822Srrh 		break;
4175822Srrh 	case TYPO:
4185822Srrh 	case TYPQ:
4195822Srrh 		back = 0;
4205822Srrh 		break;
4215822Srrh 	case TYPB:
4225822Srrh 	case TYPW:
4235822Srrh 	case TYPL:
4245822Srrh 		switch(numtype){
4255822Srrh 		case TYPO:
4265822Srrh 		case TYPQ:
4275822Srrh 			back = 0;
4285822Srrh 			break;
4295822Srrh 		default:
4305822Srrh 			*valuep = xp->e_xvalue;
4315822Srrh 			back = ISLIT(xp->e_xvalue);
4325822Srrh 			break;
4335822Srrh 		}
4345822Srrh 		break;
4355822Srrh 	}
4365822Srrh 	return(back);
4375822Srrh }
438