xref: /csrg-svn/old/as.vax/ascode.c (revision 5822)
1*5822Srrh /*
2*5822Srrh  *	Copyright (c) 1982 Regents of the University of California
3*5822Srrh  */
4*5822Srrh #ifndef lint
5*5822Srrh static char sccsid[] = "@(#)ascode.c 4.8 02/14/82";
6*5822Srrh #endif not lint
7*5822Srrh 
8592Sbill #include <stdio.h>
9592Sbill #include "as.h"
10592Sbill #include "assyms.h"
11592Sbill 
12*5822Srrh insout(opcode, ap, nact)
13*5822Srrh 	struct	Opcode	opcode;
14*5822Srrh 	struct	arg	*ap;
15*5822Srrh 	int	nact;
16*5822Srrh {
17*5822Srrh 	int	jxxflg;
18*5822Srrh 	reg	struct	instab	*ip;		/* the instruction */
19*5822Srrh 	reg	struct	arg	*ap_walk;	/* actual param walk */
20*5822Srrh 	reg	int	i;
21*5822Srrh 	reg	int	ap_type;		/* actual param type */
22*5822Srrh 	reg	int	ap_type_mask;		/* masked actual param */
23673Shenry 
24592Sbill 	jxxflg = nact;
25592Sbill 	if (nact < 0)
26592Sbill 		nact = -nact;
27592Sbill 	if (passno == 1) {
28*5822Srrh 		if (!(ITABCHECK(opcode)))
29*5822Srrh 			panic("Botched reference into itab");
30*5822Srrh 		ip = ITABFETCH(opcode);
31*5822Srrh 		if (nact < ip->i_nargs)
32*5822Srrh 			yyerror("Too few arguments");
33*5822Srrh 		if (nact > ip->i_nargs) {
34*5822Srrh 			yyerror("Too many arguments");
35*5822Srrh 			nact = ip->i_nargs;
36*5822Srrh 		}
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 		/*
44*5822Srrh 		 *	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.
49*5822Srrh 		 *	switch on the type of fp
501746Shenry 		 */
51*5822Srrh 		switch( ((fetcharg(ip, i-1)) & ACCESSMASK) >> TYPLG){
52*5822Srrh 		case ACCI >> TYPLG:
53*5822Srrh 		case ACCR >> TYPLG:
541746Shenry 			break;
55*5822Srrh 		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;
61*5822Srrh 		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;
71*5822Srrh 		case ACCM >> TYPLG:
72*5822Srrh 		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)
102*5822Srrh 		ijxout(opcode, ap, nact);
103*5822Srrh 	else
104*5822Srrh 		putins(opcode, ap, nact);
105592Sbill }
106592Sbill 
107592Sbill extern	int d124;
108592Sbill 
109*5822Srrh putins(opcode, ap, n)
110*5822Srrh 	struct	Opcode	opcode;
111592Sbill 	register struct arg *ap;
112*5822Srrh 	int	n;			/* Must be positive */
113592Sbill {
114*5822Srrh 	reg	struct exp 	*xp;
115*5822Srrh 	reg	int 	argtype;
116*5822Srrh 		int 	i;
117*5822Srrh 		int	reloc_how;
118*5822Srrh 		int	value;
119592Sbill 
120592Sbill #ifdef DEBUG
121592Sbill 	fflush(stdout);
122592Sbill #endif
123592Sbill 	if (passno == 2)
124592Sbill 		goto PASS2;
125592Sbill 
126*5822Srrh 	dotp->e_xvalue += n;		/* at least one byte per arg */
127*5822Srrh 	switch(opcode.Op_eopcode){
128*5822Srrh 	case NEW:
129*5822Srrh 	case CORE:
130*5822Srrh 		dotp->e_xvalue += 1;	/* 1 byte opcode */
131*5822Srrh 		break;
132*5822Srrh 	case ESCD:
133*5822Srrh 	case ESCF:
134*5822Srrh 		dotp->e_xvalue += 2;	/* 2 byte opcode */
135*5822Srrh 		break;
136*5822Srrh 	default:
137*5822Srrh 		panic("Bad escape opcode");
138*5822Srrh 	}
139*5822Srrh 
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:
156*5822Srrh 			argtype = fetcharg(ITABFETCH(opcode), i);
157*5822Srrh 			if (argtype == A_BB)
158592Sbill 				break;
159*5822Srrh 			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;
177*5822Srrh 			dotp->e_xvalue += 1;
178*5822Srrh 			if (ISBYTE(xp->e_xvalue))
179*5822Srrh 				break;
180*5822Srrh 			dotp->e_xvalue += 1;
181*5822Srrh 			if (ISWORD(xp->e_xvalue))
182*5822Srrh 				break;
183*5822Srrh 			dotp->e_xvalue += 2;
184592Sbill 			break;
185592Sbill 
186592Sbill 		case AIMM:
187*5822Srrh 			if (ap->a_atype&ASTAR) {
188*5822Srrh 				argtype=TYPL;
189*5822Srrh 			} else {
190*5822Srrh 				argtype = fetcharg(ITABFETCH(opcode), i);
191853Shenry 				if (argtype&ACCA)
192853Shenry 					argtype = TYPL;
193592Sbill 				else
194853Shenry 					argtype &= TYPMASK;
195629Shenry 				xp = ap->a_xp;
196*5822Srrh 				if (immconstant(ap->a_xp, argtype, &value))
197*5822Srrh 					break;
198592Sbill 			}
199*5822Srrh 			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:
205*5822Srrh 	/*
206*5822Srrh 	 *	Output the opcode
207*5822Srrh 	 */
208*5822Srrh 	switch(opcode.Op_eopcode){
209*5822Srrh 	case NEW:
210*5822Srrh 		nnewopcodes++;
211*5822Srrh 		break;
212*5822Srrh 	case ESCD:
213*5822Srrh 	case ESCF:
214*5822Srrh 		nGHopcodes++;
215*5822Srrh 		Outb(opcode.Op_eopcode);
216*5822Srrh 		break;
217*5822Srrh 	case CORE:
218*5822Srrh 		break;
219*5822Srrh 	default:
220*5822Srrh 		panic("Bad escape opcode");
221*5822Srrh 	}
222*5822Srrh 	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) {
229*5822Srrh 			{ 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 */
250*5822Srrh 			argtype = fetcharg(ITABFETCH(opcode), i);
251*5822Srrh 			if (argtype == A_BB) {
252853Shenry 				ap->a_areg1 = argtype =
253629Shenry 					xp->e_xvalue - (dotp->e_xvalue + 1);
254*5822Srrh 				if (xp->e_xtype & XXTRN)
255*5822Srrh 					yywarning("%s: destination label is external",
256*5822Srrh 						ITABFETCH(opcode)->s_name);
257*5822Srrh 				if (!ISBYTE(argtype))
258*5822Srrh 					yyerror("%s: Branch too far: %d",
259*5822Srrh 						ITABFETCH(opcode)->s_name,
260*5822Srrh 						argtype);
261*5822Srrh 				break;
262592Sbill 			}
263*5822Srrh 			if (argtype == A_BW) {
264853Shenry 				ap->a_areg1 = argtype = xp->e_xvalue
265629Shenry 					-= dotp->e_xvalue + 2;
266*5822Srrh 				if (xp->e_xtype & XXTRN)
267*5822Srrh 					yywarning("%s: destination label is external",
268*5822Srrh 						ITABFETCH(opcode)->s_name);
269629Shenry 				xp->e_xtype = XABS;
270*5822Srrh 				if (!ISWORD(argtype))
271*5822Srrh 					yyerror("%s: Branch too far: %d",
272*5822Srrh 						ITABFETCH(opcode)->s_name,
273*5822Srrh 						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;
295*5822Srrh 			if (ISBYTE(xp->e_xvalue))
296*5822Srrh 				break;
297*5822Srrh 			ap->a_areg1 += 0x20;
298*5822Srrh 			reloc_how = TYPW;
299*5822Srrh 			if (ISWORD(xp->e_xvalue))
300*5822Srrh 				break;
301*5822Srrh 			ap->a_areg1 += 0x20;
302*5822Srrh 			reloc_how = TYPL;
303592Sbill 			break;
304592Sbill 
305592Sbill 		case AIMM:  /* $expr */
306*5822Srrh 			if (ap->a_atype&ASTAR) {
307853Shenry 				argtype=TYPL;
308*5822Srrh 			} else {
309*5822Srrh 				argtype = fetcharg(ITABFETCH(opcode), i);
310853Shenry 				if (argtype&ACCA)
311*5822Srrh 					argtype = TYPL;
312592Sbill 				else
313853Shenry 					argtype &= TYPMASK;
314*5822Srrh 				if (immconstant(xp, argtype, &value)){
315*5822Srrh 					reloc_how = TYPNONE;
316*5822Srrh 					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 		 */
328*5822Srrh 		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 }
339*5822Srrh /*
340*5822Srrh  *	Is xp an immediate constant?
341*5822Srrh  *	argtype: how the instruction will interpret the bytes
342*5822Srrh  *	xp->e_number.num_tag ("numtype"): the kind of number given
343*5822Srrh  *
344*5822Srrh  *	Use the following table:
345*5822Srrh  *	float: TYPF, TYPD, TYPG, TYPH
346*5822Srrh  *	quad: TYPQ, TYPO
347*5822Srrh  *	int: TYPG, TYPW, TYPL
348*5822Srrh  *
349*5822Srrh  *				numtype
350*5822Srrh  *	argtype		float	quad	int
351*5822Srrh  *
352*5822Srrh  *	float		slitflt	slitflt	slitflt
353*5822Srrh  *	quad		0	0	0
354*5822Srrh  *	int		0..63	0	0..63
355*5822Srrh  *
356*5822Srrh  *	Where the table entry implies the predicate to return.
357*5822Srrh  */
358*5822Srrh #define	IMMFLT	1		/* these flags are not used by anybody (yet) */
359*5822Srrh #define	IMMINT	2
360*5822Srrh 
361*5822Srrh int immconstant(xp, argtype, valuep)
362*5822Srrh 	reg	struct	exp	*xp;
363*5822Srrh 		int	argtype;
364*5822Srrh 		int	*valuep;
365*5822Srrh {
366*5822Srrh 	reg	int	back = 0;
367*5822Srrh 		int	numtype;
368*5822Srrh 	reg	int	fits;
369*5822Srrh 
370*5822Srrh 	if ((xp->e_xtype & XTYPE) != XABS)
371*5822Srrh 		return(0);
372*5822Srrh 	if ((xp->e_xtype & XFORW) != 0)
373*5822Srrh 		return(0);
374*5822Srrh 	numtype = xp->e_number.num_tag;
375*5822Srrh 
376*5822Srrh 	fits = 1;
377*5822Srrh 	if (passno == 2) switch(argtype){
378*5822Srrh 	case TYPB:
379*5822Srrh 		switch(numtype){
380*5822Srrh 		default:	fits = 0; break;
381*5822Srrh 		case TYPB:	fits = 1; break;
382*5822Srrh 		case TYPW:
383*5822Srrh 		case TYPL:
384*5822Srrh 			fits = ISBYTE(xp->e_xvalue) || ISUBYTE(xp->e_xvalue);
385*5822Srrh 			break;
386*5822Srrh 		}
387*5822Srrh 		break;
388*5822Srrh 	case TYPW:
389*5822Srrh 		switch(numtype){
390*5822Srrh 		default:	fits = 0; break;
391*5822Srrh 		case TYPB:
392*5822Srrh 		case TYPW:	fits = 1; break;
393*5822Srrh 		case TYPL:
394*5822Srrh 			fits = ISWORD(xp->e_xvalue) || ISUWORD(xp->e_xvalue);
395*5822Srrh 			break;
396*5822Srrh 		}
397*5822Srrh 		break;
398*5822Srrh 	case TYPF:
399*5822Srrh 		if (numtype == TYPD){	/* same format for first 32 bits */
400*5822Srrh 			fits = 1;
401*5822Srrh 			break;
402*5822Srrh 		}
403*5822Srrh 		/*FALLTHROUGH*/
404*5822Srrh 	default:
405*5822Srrh 		fits = ty_nbyte[argtype] >= ty_nbyte[numtype];
406*5822Srrh 	}
407*5822Srrh 	if (!fits){
408*5822Srrh 	  yywarning("Immediate constant type %s mismatches instruction type %s",
409*5822Srrh 		ty_string[numtype],
410*5822Srrh 		ty_string[argtype]);
411*5822Srrh 	}
412*5822Srrh 
413*5822Srrh 	switch(argtype){
414*5822Srrh 	case TYPF:
415*5822Srrh 	case TYPG:
416*5822Srrh 	case TYPD:
417*5822Srrh 	case TYPH:
418*5822Srrh 		back = slitflt(xp->e_number, argtype, valuep);
419*5822Srrh 		break;
420*5822Srrh 	case TYPO:
421*5822Srrh 	case TYPQ:
422*5822Srrh 		back = 0;
423*5822Srrh 		break;
424*5822Srrh 	case TYPB:
425*5822Srrh 	case TYPW:
426*5822Srrh 	case TYPL:
427*5822Srrh 		switch(numtype){
428*5822Srrh 		case TYPO:
429*5822Srrh 		case TYPQ:
430*5822Srrh 			back = 0;
431*5822Srrh 			break;
432*5822Srrh 		default:
433*5822Srrh 			*valuep = xp->e_xvalue;
434*5822Srrh 			back = ISLIT(xp->e_xvalue);
435*5822Srrh 			break;
436*5822Srrh 		}
437*5822Srrh 		break;
438*5822Srrh 	}
439*5822Srrh 	return(back);
440*5822Srrh }
441