xref: /csrg-svn/old/as.vax/ascode.c (revision 592)
1*592Sbill /* Copyright (c) 1980 Regents of the University of California */
2*592Sbill static	char sccsid[] = "@(#)ascode.c 4.1 08/13/80";
3*592Sbill #include <stdio.h>
4*592Sbill #include <sys/types.h>
5*592Sbill #include <a.out.h>
6*592Sbill #include "as.h"
7*592Sbill #include "assyms.h"
8*592Sbill 
9*592Sbill insout(op, ap, nact)
10*592Sbill 	struct arg *ap;
11*592Sbill {
12*592Sbill 	int jxxflg;
13*592Sbill 
14*592Sbill 	op &= 0xFF;
15*592Sbill 	jxxflg = nact;
16*592Sbill 	if (nact < 0)
17*592Sbill 		nact = -nact;
18*592Sbill 	if (passno == 1) {
19*592Sbill 		register struct arg 	*ap2;
20*592Sbill 		register struct instab 	*ip;
21*592Sbill 		int 			i,nexp;
22*592Sbill 		ip = itab[op];
23*592Sbill 		nexp = ip->nargs;
24*592Sbill 		if (nact < nexp)
25*592Sbill 			yyerror("Too few arguments");
26*592Sbill 		if (nact > nexp) {
27*592Sbill 			yyerror("Too many arguments");
28*592Sbill 			nact = nexp;
29*592Sbill 		}
30*592Sbill 		/*
31*592Sbill 		 *	Check argument compatability with instruction template
32*592Sbill 		 */
33*592Sbill 		for (ap2 = ap+nact, i = nact; --i >= 0;)
34*592Sbill 			argcompat(--ap2, ip->argtype[i], i+1);
35*592Sbill 	}
36*592Sbill 	if (jxxflg < 0)
37*592Sbill 		ijxout(op, ap, nact);
38*592Sbill 	else putins(op, ap, nact);
39*592Sbill }
40*592Sbill 
41*592Sbill argcompat(act, exp, i)
42*592Sbill 	struct arg *act;
43*592Sbill 	int exp,i;
44*592Sbill {
45*592Sbill 	register 	at,atm;
46*592Sbill 
47*592Sbill 	at = act->atype;
48*592Sbill 	atm = at & AMASK;
49*592Sbill 
50*592Sbill 	if ( (exp & ACCB) && (!((atm == AEXP) || (atm == AIMM))) ){
51*592Sbill 		yyerror("arg %d, branch displacement must be an expression",i);
52*592Sbill 		return;
53*592Sbill 	}
54*592Sbill 	if ((exp & ACCA) && (atm == AREG)) {
55*592Sbill 		yyerror("arg %d, addressing a register",i);
56*592Sbill 		return;
57*592Sbill 	}
58*592Sbill 	if ((exp&ACCW) && (atm==AIMM) && !(at&ASTAR)) {
59*592Sbill 		yyerror("arg %d, modifying a constant",i);
60*592Sbill 		return;
61*592Sbill 	}
62*592Sbill 	if (at & AINDX) {
63*592Sbill 		if (act->areg2==017) {
64*592Sbill 			yyerror("arg %d, PC used as index",i);
65*592Sbill 			return;
66*592Sbill 		}
67*592Sbill 		if (atm==AREG) {
68*592Sbill 			yyerror("arg %d, indexing the register file",i);
69*592Sbill 			return;
70*592Sbill 		}
71*592Sbill 		if (atm==AIMM) {
72*592Sbill 			yyerror("arg %d, indexing a constant",i);
73*592Sbill 			return;
74*592Sbill 		}
75*592Sbill 		if (((atm==ADECR) || (atm==AINCR)) && (act->areg1==act->areg2)) {
76*592Sbill 			yyerror("arg %d, indexing with modified register",i);
77*592Sbill 			return;
78*592Sbill 		}
79*592Sbill 	}
80*592Sbill }
81*592Sbill 
82*592Sbill extern	int d124;
83*592Sbill 	int len124[] = 	{0,LEN1,LEN2,0,LEN4};
84*592Sbill 	char mod124[] = {0,0x00,0x20,0,0x40};
85*592Sbill 
86*592Sbill putins(op, ap, n)
87*592Sbill 	/*
88*592Sbill 	 *	n had better be positive
89*592Sbill 	 */
90*592Sbill 	register struct arg *ap;
91*592Sbill {
92*592Sbill 	register struct exp 	*xp;
93*592Sbill 	register int 		a;
94*592Sbill 	int 			i,xtrab;
95*592Sbill 
96*592Sbill #ifdef DEBUG
97*592Sbill 	fflush(stdout);
98*592Sbill #endif
99*592Sbill 	if (passno == 2)
100*592Sbill 		goto PASS2;
101*592Sbill 
102*592Sbill 	dotp->xvalue += n+1;	/* 1 for the opcode, at least 1 per arg */
103*592Sbill 	for (i=0; i<n; i++,ap++) {/* some args take more than 1 byte */
104*592Sbill 	    xtrab = 0;
105*592Sbill 	    a=ap->atype;
106*592Sbill 	    if (a & AINDX)
107*592Sbill 		dotp->xvalue++;
108*592Sbill 	    switch (a&~(AINDX|ASTAR)) {
109*592Sbill 		case AEXP:
110*592Sbill 			a = itab[op]->argtype[i];
111*592Sbill 			if (a == ACCB+TYPB)
112*592Sbill 				break;
113*592Sbill 			if (a==ACCB+TYPW){
114*592Sbill 				dotp->xvalue++;
115*592Sbill 				break;
116*592Sbill 			}
117*592Sbill 			/*
118*592Sbill 			 *	Reduces to PC relative
119*592Sbill 			 */
120*592Sbill 			xtrab++;
121*592Sbill 			dotp->xvalue += ap->dispsize;
122*592Sbill 			break;
123*592Sbill 
124*592Sbill 		case ADISP:
125*592Sbill 			xp=ap->xp;
126*592Sbill 			if ((xp->xtype&XTYPE)!=XABS || xp->xtype&XFORW){
127*592Sbill 				dotp->xvalue += ap->dispsize;
128*592Sbill 				break;
129*592Sbill 			}
130*592Sbill 			if (xp->xvalue==0 && !(a&ASTAR))
131*592Sbill 				break;
132*592Sbill 			dotp->xvalue++;
133*592Sbill 			if ((xp->xvalue<MINBYTE) || (xp->xvalue>MAXBYTE))
134*592Sbill 				dotp->xvalue++;
135*592Sbill 			if ((xp->xvalue<MINWORD) || (xp->xvalue>MAXWORD))
136*592Sbill 				dotp->xvalue += 2;
137*592Sbill 			break;
138*592Sbill 
139*592Sbill 		case AIMM:
140*592Sbill 			if (ap->atype&ASTAR) a=TYPL;
141*592Sbill 			else {
142*592Sbill 				a = itab[op]->argtype[i];
143*592Sbill 				if (a&ACCA)
144*592Sbill 					a = TYPL;
145*592Sbill 				else
146*592Sbill 					a &= TYPMASK;
147*592Sbill 				xp = ap->xp;
148*592Sbill 				if (   ((xp->xtype&XTYPE)==XABS)
149*592Sbill 				    && (!(xp->xtype&XFORW))
150*592Sbill 				    && (xp->xvalue>=0)
151*592Sbill 				    && (xp->xvalue<=63)
152*592Sbill 				    && (xp->yvalue == 0)
153*592Sbill 				    && (a != TYPD)
154*592Sbill 				    && (a != TYPF)
155*592Sbill 				)
156*592Sbill 						break;
157*592Sbill 			}
158*592Sbill 			switch (a) {
159*592Sbill 			case TYPD:
160*592Sbill 			case TYPF:
161*592Sbill 				if (   !(((xp->xtype&XTYPE)==XABS)
162*592Sbill 				    && (!(xp->xtype&XFORW))
163*592Sbill 				    && (slitflt(xp)))
164*592Sbill 				){
165*592Sbill 				/* it is NOT short */
166*592Sbill 					dotp->xvalue += ((a==TYPF)?
167*592Sbill 						4 : 8);
168*592Sbill 				}
169*592Sbill 				break;
170*592Sbill 			case TYPQ:
171*592Sbill 				dotp->xvalue += 8;break;
172*592Sbill 			case TYPL:
173*592Sbill 				dotp->xvalue += 4;break;
174*592Sbill 			case TYPW:
175*592Sbill 				dotp->xvalue += 2;break;
176*592Sbill 			case TYPB:
177*592Sbill 				dotp->xvalue += 1;break;
178*592Sbill 			}	/*end of the switch on a*/
179*592Sbill 	    }	/*end of the switch on the type*/
180*592Sbill 	}	/*end of looping for all arguments*/
181*592Sbill 	return;
182*592Sbill 
183*592Sbill PASS2:
184*592Sbill 
185*592Sbill #ifdef UNIX
186*592Sbill 	outb(op); /* the opcode */
187*592Sbill #endif UNIX
188*592Sbill #ifdef VMS
189*592Sbill 	*vms_obj_ptr++ = -1; *vms_obj_ptr++ = (char)op;
190*592Sbill 	dotp->xvalue += 1;
191*592Sbill #endif VMS
192*592Sbill 
193*592Sbill 	for (i=0; i<n; i++,ap++) {/* now for the arguments */
194*592Sbill 		a=ap->atype;
195*592Sbill 		xp=ap->xp;
196*592Sbill 		xtrab=0;
197*592Sbill 		if (a&AINDX) {
198*592Sbill #ifdef UNIX
199*592Sbill 			{ outb(0x40 | ap->areg2); }
200*592Sbill #endif UNIX
201*592Sbill #ifdef VMS
202*592Sbill 			{ *vms_obj_ptr++ = -1;
203*592Sbill 			  *vms_obj_ptr++ = (0x40 | ap->areg2);
204*592Sbill 			  dotp->xvalue += 1; }
205*592Sbill #endif VMS
206*592Sbill 			a &= ~AINDX;
207*592Sbill 		}
208*592Sbill 		if (a&ASTAR) {
209*592Sbill 			ap->areg1 |= 0x10;
210*592Sbill 			a &= ~ASTAR;
211*592Sbill 		}
212*592Sbill 		switch (a) {
213*592Sbill 		case AREG:		/* %r */
214*592Sbill 			ap->areg1 |= 0x50;
215*592Sbill 			break;
216*592Sbill 		case ABASE:		/* (%r) */
217*592Sbill 			ap->areg1 |= 0x60;
218*592Sbill 			break;
219*592Sbill 		case ADECR: 		/* -(%r) */
220*592Sbill 			ap->areg1 |= 0x70;
221*592Sbill 			break;
222*592Sbill 		case AINCR:		/* (%r) */
223*592Sbill 			ap->areg1 |= 0x80;
224*592Sbill 			break;
225*592Sbill 		case AEXP: /* expr */
226*592Sbill 			a = itab[op]->argtype[i];
227*592Sbill 			if (a == ACCB+TYPB) {
228*592Sbill 				ap->areg1 = a =
229*592Sbill 					xp->xvalue - (dotp->xvalue + 1);
230*592Sbill 				if (a<MINBYTE || a>MAXBYTE)
231*592Sbill 					yyerror("Branch too far"); break;
232*592Sbill 			}
233*592Sbill 			if (a == ACCB+TYPW) {
234*592Sbill 				ap->areg1 = a = xp->xvalue
235*592Sbill 					-= dotp->xvalue + 2;
236*592Sbill 				xp->xtype = XABS;
237*592Sbill 				if (a<MINWORD || a>MAXWORD)
238*592Sbill 					yyerror("Branch too far");
239*592Sbill 				xp->xvalue = a>>8;
240*592Sbill 				xtrab = LEN1;
241*592Sbill 				break;
242*592Sbill 			}
243*592Sbill 			/* reduces to expr(pc) mode */
244*592Sbill 			ap->areg1 |= (0xAF + mod124[ap->dispsize]);
245*592Sbill 			xtrab = len124[ap->dispsize]+PCREL;
246*592Sbill 			break;
247*592Sbill 
248*592Sbill 		case ADISP: /* expr(%r) */
249*592Sbill 			ap->areg1 |= 0xA0;
250*592Sbill 			if ((xp->xtype&XTYPE)!=XABS || xp->xtype&XFORW){
251*592Sbill 				ap->areg1 += mod124[ap->dispsize];
252*592Sbill 				xtrab=len124[ap->dispsize];
253*592Sbill 				break;
254*592Sbill 			}
255*592Sbill 			if (xp->xvalue==0 && !(ap->areg1&0x10)) {
256*592Sbill 				ap->areg1 ^= 0xC0;
257*592Sbill 				break;
258*592Sbill 			}
259*592Sbill 			xtrab=LEN1;
260*592Sbill 			if ((xp->xvalue<MINBYTE) || (xp->xvalue>MAXBYTE)){
261*592Sbill 				ap->areg1 += 0x20;
262*592Sbill 				xtrab=LEN2;
263*592Sbill 			}
264*592Sbill 			if ((xp->xvalue<MINWORD) || (xp->xvalue>MAXWORD)){
265*592Sbill 				ap->areg1 += 0x20;
266*592Sbill 				xtrab=LEN4;
267*592Sbill 			}
268*592Sbill 			break;
269*592Sbill 
270*592Sbill 		case AIMM:  /* $expr */
271*592Sbill 			if (ap->atype&ASTAR)
272*592Sbill 				a=TYPL;
273*592Sbill 			else {
274*592Sbill 				a = itab[op]->argtype[i];
275*592Sbill 				if (a&ACCA)
276*592Sbill 					a=TYPL;
277*592Sbill 				else
278*592Sbill 					a &= TYPMASK;
279*592Sbill 				if (    ( (xp->xtype&XTYPE) == XABS)
280*592Sbill 				    && !(xp->xtype&XFORW)
281*592Sbill 				    &&  (xp->xvalue >= 0)
282*592Sbill 				    &&  (xp->xvalue <= 63)
283*592Sbill 				    &&  (xp->yvalue == 0)
284*592Sbill 				    &&  (a != TYPF)
285*592Sbill 				    &&  (a != TYPD) ) {
286*592Sbill 					ap->areg1 = xp->xvalue;
287*592Sbill 					break;
288*592Sbill 				}
289*592Sbill 			}
290*592Sbill 			ap->areg1 |= 0x8F;
291*592Sbill 			switch (a) {
292*592Sbill 			case TYPD:
293*592Sbill 			case TYPF:
294*592Sbill 				if (   ((xp->xtype&XTYPE)==XABS)
295*592Sbill 				    && (!(xp->xtype&XFORW))
296*592Sbill 				    && (slitflt(xp))
297*592Sbill 				){
298*592Sbill 					ap->areg1=extlitflt(xp);
299*592Sbill 				} else {
300*592Sbill 					xtrab = (a==TYPF) ? LEN4: LEN8;
301*592Sbill 				}
302*592Sbill 				break;
303*592Sbill 			case TYPQ: xtrab = LEN8; break;
304*592Sbill 			case TYPL: xtrab = LEN4; break;
305*592Sbill 			case TYPW: xtrab = LEN2; break;
306*592Sbill 			case TYPB: xtrab = LEN1; break;
307*592Sbill 			}
308*592Sbill 			break;
309*592Sbill 
310*592Sbill 		}	/*end of the switch on a*/
311*592Sbill 		/*
312*592Sbill 		 *	use the first byte to describe the argument
313*592Sbill 		 */
314*592Sbill #ifdef UNIX
315*592Sbill 		outb(ap->areg1);
316*592Sbill #endif UNIX
317*592Sbill #ifdef VMS
318*592Sbill 		*vms_obj_ptr++ = -1; *vms_obj_ptr++ = (char)(ap->areg1);
319*592Sbill 		dotp->xvalue += 1;
320*592Sbill 		if ((vms_obj_ptr-sobuf) > 400) {
321*592Sbill 			write(objfil,sobuf,vms_obj_ptr-sobuf);
322*592Sbill 			vms_obj_ptr=sobuf+1;
323*592Sbill 		}
324*592Sbill #endif VMS
325*592Sbill 		if (xtrab)
326*592Sbill 			/*
327*592Sbill 			 *	Floating point numbers are written to a.out
328*592Sbill 			 *	by outrel; they require that the least significant
329*592Sbill 			 *	4 bytes of an 8 byte double precision number
330*592Sbill 			 *	immediately follow the field xvalue, which
331*592Sbill 			 *	they do.
332*592Sbill 			 */
333*592Sbill 			outrel(&xp->xvalue, xtrab, xp->xtype, xp->xname);
334*592Sbill 	}	/*end of the for to pick up all arguments*/
335*592Sbill }
336