xref: /csrg-svn/old/as.vax/ascode.c (revision 629)
1592Sbill /* Copyright (c) 1980 Regents of the University of California */
2*629Shenry static	char sccsid[] = "@(#)ascode.c 4.2 08/15/80";
3592Sbill #include <stdio.h>
4592Sbill #include "as.h"
5592Sbill #include "assyms.h"
6592Sbill 
7592Sbill insout(op, ap, nact)
8592Sbill 	struct arg *ap;
9592Sbill {
10592Sbill 	int jxxflg;
11592Sbill 
12592Sbill 	op &= 0xFF;
13592Sbill 	jxxflg = nact;
14592Sbill 	if (nact < 0)
15592Sbill 		nact = -nact;
16592Sbill 	if (passno == 1) {
17592Sbill 		register struct arg 	*ap2;
18592Sbill 		register struct instab 	*ip;
19592Sbill 		int 			i,nexp;
20592Sbill 		ip = itab[op];
21*629Shenry 		nexp = ip->i_nargs;
22592Sbill 		if (nact < nexp)
23592Sbill 			yyerror("Too few arguments");
24592Sbill 		if (nact > nexp) {
25592Sbill 			yyerror("Too many arguments");
26592Sbill 			nact = nexp;
27592Sbill 		}
28592Sbill 		/*
29592Sbill 		 *	Check argument compatability with instruction template
30592Sbill 		 */
31592Sbill 		for (ap2 = ap+nact, i = nact; --i >= 0;)
32*629Shenry 			argcompat(--ap2, fetcharg(ip, i), i+1);
33592Sbill 	}
34592Sbill 	if (jxxflg < 0)
35592Sbill 		ijxout(op, ap, nact);
36592Sbill 	else putins(op, ap, nact);
37592Sbill }
38592Sbill 
39592Sbill argcompat(act, exp, i)
40592Sbill 	struct arg *act;
41592Sbill 	int exp,i;
42592Sbill {
43592Sbill 	register 	at,atm;
44592Sbill 
45*629Shenry 	at = act->a_atype;
46592Sbill 	atm = at & AMASK;
47592Sbill 
48592Sbill 	if ( (exp & ACCB) && (!((atm == AEXP) || (atm == AIMM))) ){
49592Sbill 		yyerror("arg %d, branch displacement must be an expression",i);
50592Sbill 		return;
51592Sbill 	}
52592Sbill 	if ((exp & ACCA) && (atm == AREG)) {
53592Sbill 		yyerror("arg %d, addressing a register",i);
54592Sbill 		return;
55592Sbill 	}
56592Sbill 	if ((exp&ACCW) && (atm==AIMM) && !(at&ASTAR)) {
57592Sbill 		yyerror("arg %d, modifying a constant",i);
58592Sbill 		return;
59592Sbill 	}
60592Sbill 	if (at & AINDX) {
61*629Shenry 		if (act->a_areg2==017) {
62592Sbill 			yyerror("arg %d, PC used as index",i);
63592Sbill 			return;
64592Sbill 		}
65592Sbill 		if (atm==AREG) {
66592Sbill 			yyerror("arg %d, indexing the register file",i);
67592Sbill 			return;
68592Sbill 		}
69592Sbill 		if (atm==AIMM) {
70592Sbill 			yyerror("arg %d, indexing a constant",i);
71592Sbill 			return;
72592Sbill 		}
73*629Shenry 		if (((atm==ADECR) || (atm==AINCR)) && (act->a_areg1==act->a_areg2)) {
74592Sbill 			yyerror("arg %d, indexing with modified register",i);
75592Sbill 			return;
76592Sbill 		}
77592Sbill 	}
78592Sbill }
79592Sbill 
80592Sbill extern	int d124;
81592Sbill 	int len124[] = 	{0,LEN1,LEN2,0,LEN4};
82592Sbill 	char mod124[] = {0,0x00,0x20,0,0x40};
83592Sbill 
84592Sbill putins(op, ap, n)
85592Sbill 	/*
86592Sbill 	 *	n had better be positive
87592Sbill 	 */
88592Sbill 	register struct arg *ap;
89592Sbill {
90592Sbill 	register struct exp 	*xp;
91592Sbill 	register int 		a;
92592Sbill 	int 			i,xtrab;
93592Sbill 
94592Sbill #ifdef DEBUG
95592Sbill 	fflush(stdout);
96592Sbill #endif
97592Sbill 	if (passno == 2)
98592Sbill 		goto PASS2;
99592Sbill 
100*629Shenry 	dotp->e_xvalue += n+1;		/* 1 for the opcode, at least 1 per arg */
101*629Shenry 	for (i=0; i<n; i++,ap++) {	/* some args take more than 1 byte */
102*629Shenry 	    a = ap->a_atype;
103592Sbill 	    if (a & AINDX)
104*629Shenry 		dotp->e_xvalue++;
105592Sbill 	    switch (a&~(AINDX|ASTAR)) {
106592Sbill 		case AEXP:
107*629Shenry 			a = fetcharg(itab[op], i);
108592Sbill 			if (a == ACCB+TYPB)
109592Sbill 				break;
110592Sbill 			if (a==ACCB+TYPW){
111*629Shenry 				dotp->e_xvalue++;
112592Sbill 				break;
113592Sbill 			}
114592Sbill 			/*
115592Sbill 			 *	Reduces to PC relative
116592Sbill 			 */
117*629Shenry 			dotp->e_xvalue += ap->a_dispsize;
118592Sbill 			break;
119592Sbill 
120592Sbill 		case ADISP:
121*629Shenry 			xp=ap->a_xp;
122*629Shenry 			if ((xp->e_xtype&XTYPE)!=XABS || xp->e_xtype&XFORW){
123*629Shenry 				dotp->e_xvalue += ap->a_dispsize;
124592Sbill 				break;
125592Sbill 			}
126*629Shenry 			if (xp->e_xvalue==0 && !(a&ASTAR))
127592Sbill 				break;
128*629Shenry 			dotp->e_xvalue++;
129*629Shenry 			if ((xp->e_xvalue<MINBYTE) || (xp->e_xvalue>MAXBYTE))
130*629Shenry 				dotp->e_xvalue++;
131*629Shenry 			if ((xp->e_xvalue<MINWORD) || (xp->e_xvalue>MAXWORD))
132*629Shenry 				dotp->e_xvalue += 2;
133592Sbill 			break;
134592Sbill 
135592Sbill 		case AIMM:
136*629Shenry 			if (ap->a_atype&ASTAR) a=TYPL;
137592Sbill 			else {
138*629Shenry 				a = fetcharg(itab[op], i);
139592Sbill 				if (a&ACCA)
140592Sbill 					a = TYPL;
141592Sbill 				else
142592Sbill 					a &= TYPMASK;
143*629Shenry 				xp = ap->a_xp;
144*629Shenry 				if (   ((xp->e_xtype&XTYPE)==XABS)
145*629Shenry 				    && (!(xp->e_xtype&XFORW))
146*629Shenry 				    && (xp->e_xvalue>=0)
147*629Shenry 				    && (xp->e_xvalue<=63)
148*629Shenry 				    && (xp->e_yvalue == 0)
149592Sbill 				    && (a != TYPD)
150592Sbill 				    && (a != TYPF)
151592Sbill 				)
152592Sbill 						break;
153592Sbill 			}
154592Sbill 			switch (a) {
155592Sbill 			case TYPD:
156592Sbill 			case TYPF:
157*629Shenry 				if (   !(((xp->e_xtype&XTYPE)==XABS)
158*629Shenry 				    && (!(xp->e_xtype&XFORW))
159592Sbill 				    && (slitflt(xp)))
160592Sbill 				){
161592Sbill 				/* it is NOT short */
162*629Shenry 					dotp->e_xvalue += ((a==TYPF)?
163592Sbill 						4 : 8);
164592Sbill 				}
165592Sbill 				break;
166592Sbill 			case TYPQ:
167*629Shenry 				dotp->e_xvalue += 8;break;
168592Sbill 			case TYPL:
169*629Shenry 				dotp->e_xvalue += 4;break;
170592Sbill 			case TYPW:
171*629Shenry 				dotp->e_xvalue += 2;break;
172592Sbill 			case TYPB:
173*629Shenry 				dotp->e_xvalue += 1;break;
174592Sbill 			}	/*end of the switch on a*/
175592Sbill 	    }	/*end of the switch on the type*/
176592Sbill 	}	/*end of looping for all arguments*/
177592Sbill 	return;
178592Sbill 
179592Sbill PASS2:
180592Sbill 
181592Sbill #ifdef UNIX
182592Sbill 	outb(op); /* the opcode */
183592Sbill #endif UNIX
184592Sbill #ifdef VMS
185592Sbill 	*vms_obj_ptr++ = -1; *vms_obj_ptr++ = (char)op;
186*629Shenry 	dotp->e_xvalue += 1;
187592Sbill #endif VMS
188592Sbill 
189592Sbill 	for (i=0; i<n; i++,ap++) {/* now for the arguments */
190*629Shenry 		a=ap->a_atype;
191*629Shenry 		xp=ap->a_xp;
192592Sbill 		xtrab=0;
193592Sbill 		if (a&AINDX) {
194592Sbill #ifdef UNIX
195*629Shenry 			{ outb(0x40 | ap->a_areg2); }
196592Sbill #endif UNIX
197592Sbill #ifdef VMS
198592Sbill 			{ *vms_obj_ptr++ = -1;
199*629Shenry 			  *vms_obj_ptr++ = (0x40 | ap->a_areg2);
200*629Shenry 			  dotp->e_xvalue += 1; }
201592Sbill #endif VMS
202592Sbill 			a &= ~AINDX;
203592Sbill 		}
204592Sbill 		if (a&ASTAR) {
205*629Shenry 			ap->a_areg1 |= 0x10;
206592Sbill 			a &= ~ASTAR;
207592Sbill 		}
208592Sbill 		switch (a) {
209592Sbill 		case AREG:		/* %r */
210*629Shenry 			ap->a_areg1 |= 0x50;
211592Sbill 			break;
212592Sbill 		case ABASE:		/* (%r) */
213*629Shenry 			ap->a_areg1 |= 0x60;
214592Sbill 			break;
215592Sbill 		case ADECR: 		/* -(%r) */
216*629Shenry 			ap->a_areg1 |= 0x70;
217592Sbill 			break;
218592Sbill 		case AINCR:		/* (%r) */
219*629Shenry 			ap->a_areg1 |= 0x80;
220592Sbill 			break;
221592Sbill 		case AEXP: /* expr */
222*629Shenry 			a = fetcharg(itab[op], i);
223592Sbill 			if (a == ACCB+TYPB) {
224*629Shenry 				ap->a_areg1 = a =
225*629Shenry 					xp->e_xvalue - (dotp->e_xvalue + 1);
226592Sbill 				if (a<MINBYTE || a>MAXBYTE)
227592Sbill 					yyerror("Branch too far"); break;
228592Sbill 			}
229592Sbill 			if (a == ACCB+TYPW) {
230*629Shenry 				ap->a_areg1 = a = xp->e_xvalue
231*629Shenry 					-= dotp->e_xvalue + 2;
232*629Shenry 				xp->e_xtype = XABS;
233592Sbill 				if (a<MINWORD || a>MAXWORD)
234592Sbill 					yyerror("Branch too far");
235*629Shenry 				xp->e_xvalue = a>>8;
236592Sbill 				xtrab = LEN1;
237592Sbill 				break;
238592Sbill 			}
239592Sbill 			/* reduces to expr(pc) mode */
240*629Shenry 			ap->a_areg1 |= (0xAF + mod124[ap->a_dispsize]);
241*629Shenry 			xtrab = len124[ap->a_dispsize]+PCREL;
242592Sbill 			break;
243592Sbill 
244592Sbill 		case ADISP: /* expr(%r) */
245*629Shenry 			ap->a_areg1 |= 0xA0;
246*629Shenry 			if ((xp->e_xtype&XTYPE)!=XABS || xp->e_xtype&XFORW){
247*629Shenry 				ap->a_areg1 += mod124[ap->a_dispsize];
248*629Shenry 				xtrab=len124[ap->a_dispsize];
249592Sbill 				break;
250592Sbill 			}
251*629Shenry 			if (xp->e_xvalue==0 && !(ap->a_areg1&0x10)) {
252*629Shenry 				ap->a_areg1 ^= 0xC0;
253592Sbill 				break;
254592Sbill 			}
255592Sbill 			xtrab=LEN1;
256*629Shenry 			if ((xp->e_xvalue<MINBYTE) || (xp->e_xvalue>MAXBYTE)){
257*629Shenry 				ap->a_areg1 += 0x20;
258592Sbill 				xtrab=LEN2;
259592Sbill 			}
260*629Shenry 			if ((xp->e_xvalue<MINWORD) || (xp->e_xvalue>MAXWORD)){
261*629Shenry 				ap->a_areg1 += 0x20;
262592Sbill 				xtrab=LEN4;
263592Sbill 			}
264592Sbill 			break;
265592Sbill 
266592Sbill 		case AIMM:  /* $expr */
267*629Shenry 			if (ap->a_atype&ASTAR)
268592Sbill 				a=TYPL;
269592Sbill 			else {
270*629Shenry 				a = fetcharg(itab[op], i);
271592Sbill 				if (a&ACCA)
272592Sbill 					a=TYPL;
273592Sbill 				else
274592Sbill 					a &= TYPMASK;
275*629Shenry 				if (    ( (xp->e_xtype&XTYPE) == XABS)
276*629Shenry 				    && !(xp->e_xtype&XFORW)
277*629Shenry 				    &&  (xp->e_xvalue >= 0)
278*629Shenry 				    &&  (xp->e_xvalue <= 63)
279*629Shenry 				    &&  (xp->e_yvalue == 0)
280592Sbill 				    &&  (a != TYPF)
281592Sbill 				    &&  (a != TYPD) ) {
282*629Shenry 					ap->a_areg1 = xp->e_xvalue;
283592Sbill 					break;
284592Sbill 				}
285592Sbill 			}
286*629Shenry 			ap->a_areg1 |= 0x8F;
287592Sbill 			switch (a) {
288592Sbill 			case TYPD:
289592Sbill 			case TYPF:
290*629Shenry 				if (   ((xp->e_xtype&XTYPE)==XABS)
291*629Shenry 				    && (!(xp->e_xtype&XFORW))
292592Sbill 				    && (slitflt(xp))
293592Sbill 				){
294*629Shenry 					ap->a_areg1=extlitflt(xp);
295592Sbill 				} else {
296592Sbill 					xtrab = (a==TYPF) ? LEN4: LEN8;
297592Sbill 				}
298592Sbill 				break;
299592Sbill 			case TYPQ: xtrab = LEN8; break;
300592Sbill 			case TYPL: xtrab = LEN4; break;
301592Sbill 			case TYPW: xtrab = LEN2; break;
302592Sbill 			case TYPB: xtrab = LEN1; break;
303592Sbill 			}
304592Sbill 			break;
305592Sbill 
306592Sbill 		}	/*end of the switch on a*/
307592Sbill 		/*
308592Sbill 		 *	use the first byte to describe the argument
309592Sbill 		 */
310592Sbill #ifdef UNIX
311*629Shenry 		outb(ap->a_areg1);
312592Sbill #endif UNIX
313592Sbill #ifdef VMS
314*629Shenry 		*vms_obj_ptr++ = -1; *vms_obj_ptr++ = (char)(ap->a_areg1);
315*629Shenry 		dotp->e_xvalue += 1;
316592Sbill 		if ((vms_obj_ptr-sobuf) > 400) {
317592Sbill 			write(objfil,sobuf,vms_obj_ptr-sobuf);
318592Sbill 			vms_obj_ptr=sobuf+1;
319592Sbill 		}
320592Sbill #endif VMS
321592Sbill 		if (xtrab)
322592Sbill 			/*
323592Sbill 			 *	Floating point numbers are written to a.out
324592Sbill 			 *	by outrel; they require that the least significant
325592Sbill 			 *	4 bytes of an 8 byte double precision number
326592Sbill 			 *	immediately follow the field xvalue, which
327592Sbill 			 *	they do.
328592Sbill 			 */
329*629Shenry 			outrel(&xp->e_xvalue, xtrab, xp->e_xtype, xp->e_xname);
330592Sbill 	}	/*end of the for to pick up all arguments*/
331592Sbill }
332