xref: /csrg-svn/old/as.vax/ascode.c (revision 667)
1592Sbill /* Copyright (c) 1980 Regents of the University of California */
2*667Shenry static	char sccsid[] = "@(#)ascode.c 4.4 08/19/80";
3592Sbill #include <stdio.h>
4592Sbill #include "as.h"
5592Sbill #include "assyms.h"
6592Sbill 
7592Sbill insout(op, ap, nact)
8592Sbill 	struct arg *ap;
9592Sbill {
10*667Shenry 	int		jxxflg;
11*667Shenry 	register	struct	instab	*ip;		/* the instruction */
12*667Shenry 	register	struct	arg	*ap_walk;	/* actual param walk */
13*667Shenry 	register	int	i;
14*667Shenry 	register	int	ap_type;		/* actual param type */
15*667Shenry 	register	int	ap_type_mask;		/* masked actual param */
16592Sbill 	op &= 0xFF;
17592Sbill 	jxxflg = nact;
18592Sbill 	if (nact < 0)
19592Sbill 		nact = -nact;
20592Sbill 	if (passno == 1) {
21*667Shenry 	    ip = itab[op];
22*667Shenry 	    if (nact < ip->i_nargs)
23*667Shenry 		yyerror("Too few arguments");
24*667Shenry 	    if (nact > ip->i_nargs) {
25*667Shenry 		yyerror("Too many arguments");
26*667Shenry 		nact = ip->i_nargs;
27*667Shenry 	    }
28*667Shenry 	    /*
29*667Shenry 	     *	Check argument compatability with instruction template
30*667Shenry 	     */
31*667Shenry 	    for (ap_walk = ap, i = 1; i <= nact; ap_walk++, i++){
32*667Shenry 		ap_type = ap_walk->a_type;
33*667Shenry 		ap_type_mask = ap_type & AMASK;
34*667Shenry 		switch( (fetcharg(ip, i-1)) & AMASK){	/* type of fp */
35*667Shenry 		case ACCB:
36*667Shenry 			if ( !((ap_type_mask == AEXP) || (ap_type_mask == AIMM)) ){
37*667Shenry 				yyerror("arg %d, branch displacement must be an expression",i);
38*667Shenry 				return;
39*667Shenry 			}
40*667Shenry 			break;
41*667Shenry 		case ACCA:
42*667Shenry 			switch(ap_type_mask){
43*667Shenry 			case AREG:	yyerror("arg %d, addressing a register",i);
44*667Shenry 					return;
45*667Shenry 			case AIMM:	if ( !(ap_type & ASTAR) ){
46*667Shenry 					 yyerror("arg %d, addressing an immediate operand",i);
47*667Shenry 					 return;
48*667Shenry 					}
49*667Shenry 			}
50*667Shenry 			break;
51*667Shenry 		case ACCM:
52*667Shenry 		case ACCW:
53*667Shenry 			switch(ap_type_mask){
54*667Shenry 			case AIMM:	if (!(ap_type&ASTAR)) {
55*667Shenry 					 yyerror("arg %d, modifying a constant",i);
56*667Shenry 					 return;
57*667Shenry 					}
58*667Shenry 			}
59*667Shenry 			break;
60*667Shenry 		}	/* end of the switch on fp_type */
61*667Shenry 		if (ap_type & AINDX) {
62*667Shenry 			if (ap_walk->a_areg2==0xF) {
63*667Shenry 				yyerror("arg %d, PC used as index",i);
64*667Shenry 				return;
65*667Shenry 			}
66*667Shenry 			switch(ap_type_mask){
67*667Shenry 			case AREG:	yyerror("arg %d, indexing the register file",i);
68*667Shenry 					return;
69*667Shenry 			case AIMM:	yyerror("arg %d, indexing a constant",i);
70*667Shenry 					return;
71*667Shenry 			case DECR:
72*667Shenry 			case INCR:	if (ap_walk->a_areg1==ap_walk->a_areg2) {
73*667Shenry 						yyerror("arg %d, indexing with modified register",i);
74*667Shenry 						return;
75*667Shenry 					}
76*667Shenry 					break;
77*667Shenry 			}	/* end of switch on ap_type_mask */
78*667Shenry 		} /* end of AINDX */
79*667Shenry 	   }
80*667Shenry 	} /* both passes here */
81592Sbill 	if (jxxflg < 0)
82592Sbill 		ijxout(op, ap, nact);
83592Sbill 	else putins(op, ap, nact);
84592Sbill }
85592Sbill 
86592Sbill extern	int d124;
87592Sbill 	int len124[] = 	{0,LEN1,LEN2,0,LEN4};
88592Sbill 	char mod124[] = {0,0x00,0x20,0,0x40};
89592Sbill 
90592Sbill putins(op, ap, n)
91592Sbill 	/*
92592Sbill 	 *	n had better be positive
93592Sbill 	 */
94592Sbill 	register struct arg *ap;
95592Sbill {
96592Sbill 	register struct exp 	*xp;
97592Sbill 	register int 		a;
98592Sbill 	int 			i,xtrab;
99592Sbill 
100592Sbill #ifdef DEBUG
101592Sbill 	fflush(stdout);
102592Sbill #endif
103592Sbill 	if (passno == 2)
104592Sbill 		goto PASS2;
105592Sbill 
106629Shenry 	dotp->e_xvalue += n+1;		/* 1 for the opcode, at least 1 per arg */
107629Shenry 	for (i=0; i<n; i++,ap++) {	/* some args take more than 1 byte */
108629Shenry 	    a = ap->a_atype;
109592Sbill 	    if (a & AINDX)
110629Shenry 		dotp->e_xvalue++;
111592Sbill 	    switch (a&~(AINDX|ASTAR)) {
112592Sbill 		case AEXP:
113629Shenry 			a = fetcharg(itab[op], i);
114592Sbill 			if (a == ACCB+TYPB)
115592Sbill 				break;
116592Sbill 			if (a==ACCB+TYPW){
117629Shenry 				dotp->e_xvalue++;
118592Sbill 				break;
119592Sbill 			}
120592Sbill 			/*
121592Sbill 			 *	Reduces to PC relative
122592Sbill 			 */
123629Shenry 			dotp->e_xvalue += ap->a_dispsize;
124592Sbill 			break;
125592Sbill 
126592Sbill 		case ADISP:
127629Shenry 			xp=ap->a_xp;
128629Shenry 			if ((xp->e_xtype&XTYPE)!=XABS || xp->e_xtype&XFORW){
129629Shenry 				dotp->e_xvalue += ap->a_dispsize;
130592Sbill 				break;
131592Sbill 			}
132629Shenry 			if (xp->e_xvalue==0 && !(a&ASTAR))
133592Sbill 				break;
134629Shenry 			dotp->e_xvalue++;
135629Shenry 			if ((xp->e_xvalue<MINBYTE) || (xp->e_xvalue>MAXBYTE))
136629Shenry 				dotp->e_xvalue++;
137629Shenry 			if ((xp->e_xvalue<MINWORD) || (xp->e_xvalue>MAXWORD))
138629Shenry 				dotp->e_xvalue += 2;
139592Sbill 			break;
140592Sbill 
141592Sbill 		case AIMM:
142629Shenry 			if (ap->a_atype&ASTAR) a=TYPL;
143592Sbill 			else {
144629Shenry 				a = fetcharg(itab[op], i);
145592Sbill 				if (a&ACCA)
146592Sbill 					a = TYPL;
147592Sbill 				else
148592Sbill 					a &= TYPMASK;
149629Shenry 				xp = ap->a_xp;
150629Shenry 				if (   ((xp->e_xtype&XTYPE)==XABS)
151629Shenry 				    && (!(xp->e_xtype&XFORW))
152629Shenry 				    && (xp->e_xvalue>=0)
153629Shenry 				    && (xp->e_xvalue<=63)
154629Shenry 				    && (xp->e_yvalue == 0)
155592Sbill 				    && (a != TYPD)
156592Sbill 				    && (a != TYPF)
157592Sbill 				)
158592Sbill 						break;
159592Sbill 			}
160592Sbill 			switch (a) {
161592Sbill 			case TYPD:
162592Sbill 			case TYPF:
163629Shenry 				if (   !(((xp->e_xtype&XTYPE)==XABS)
164629Shenry 				    && (!(xp->e_xtype&XFORW))
165592Sbill 				    && (slitflt(xp)))
166592Sbill 				){
167592Sbill 				/* it is NOT short */
168629Shenry 					dotp->e_xvalue += ((a==TYPF)?
169592Sbill 						4 : 8);
170592Sbill 				}
171592Sbill 				break;
172592Sbill 			case TYPQ:
173629Shenry 				dotp->e_xvalue += 8;break;
174592Sbill 			case TYPL:
175629Shenry 				dotp->e_xvalue += 4;break;
176592Sbill 			case TYPW:
177629Shenry 				dotp->e_xvalue += 2;break;
178592Sbill 			case TYPB:
179629Shenry 				dotp->e_xvalue += 1;break;
180592Sbill 			}	/*end of the switch on a*/
181592Sbill 	    }	/*end of the switch on the type*/
182592Sbill 	}	/*end of looping for all arguments*/
183592Sbill 	return;
184592Sbill 
185592Sbill PASS2:
186592Sbill 
187592Sbill #ifdef UNIX
188592Sbill 	outb(op); /* the opcode */
189592Sbill #endif UNIX
190592Sbill #ifdef VMS
191592Sbill 	*vms_obj_ptr++ = -1; *vms_obj_ptr++ = (char)op;
192629Shenry 	dotp->e_xvalue += 1;
193592Sbill #endif VMS
194592Sbill 
195592Sbill 	for (i=0; i<n; i++,ap++) {/* now for the arguments */
196629Shenry 		a=ap->a_atype;
197629Shenry 		xp=ap->a_xp;
198592Sbill 		xtrab=0;
199592Sbill 		if (a&AINDX) {
200592Sbill #ifdef UNIX
201629Shenry 			{ outb(0x40 | ap->a_areg2); }
202592Sbill #endif UNIX
203592Sbill #ifdef VMS
204592Sbill 			{ *vms_obj_ptr++ = -1;
205629Shenry 			  *vms_obj_ptr++ = (0x40 | ap->a_areg2);
206629Shenry 			  dotp->e_xvalue += 1; }
207592Sbill #endif VMS
208592Sbill 			a &= ~AINDX;
209592Sbill 		}
210592Sbill 		if (a&ASTAR) {
211629Shenry 			ap->a_areg1 |= 0x10;
212592Sbill 			a &= ~ASTAR;
213592Sbill 		}
214592Sbill 		switch (a) {
215592Sbill 		case AREG:		/* %r */
216629Shenry 			ap->a_areg1 |= 0x50;
217592Sbill 			break;
218592Sbill 		case ABASE:		/* (%r) */
219629Shenry 			ap->a_areg1 |= 0x60;
220592Sbill 			break;
221592Sbill 		case ADECR: 		/* -(%r) */
222629Shenry 			ap->a_areg1 |= 0x70;
223592Sbill 			break;
224665Shenry 		case AINCR:		/* (%r)+ */
225629Shenry 			ap->a_areg1 |= 0x80;
226592Sbill 			break;
227592Sbill 		case AEXP: /* expr */
228629Shenry 			a = fetcharg(itab[op], i);
229592Sbill 			if (a == ACCB+TYPB) {
230629Shenry 				ap->a_areg1 = a =
231629Shenry 					xp->e_xvalue - (dotp->e_xvalue + 1);
232592Sbill 				if (a<MINBYTE || a>MAXBYTE)
233592Sbill 					yyerror("Branch too far"); break;
234592Sbill 			}
235592Sbill 			if (a == ACCB+TYPW) {
236629Shenry 				ap->a_areg1 = a = xp->e_xvalue
237629Shenry 					-= dotp->e_xvalue + 2;
238629Shenry 				xp->e_xtype = XABS;
239592Sbill 				if (a<MINWORD || a>MAXWORD)
240592Sbill 					yyerror("Branch too far");
241629Shenry 				xp->e_xvalue = a>>8;
242592Sbill 				xtrab = LEN1;
243592Sbill 				break;
244592Sbill 			}
245592Sbill 			/* reduces to expr(pc) mode */
246629Shenry 			ap->a_areg1 |= (0xAF + mod124[ap->a_dispsize]);
247629Shenry 			xtrab = len124[ap->a_dispsize]+PCREL;
248592Sbill 			break;
249592Sbill 
250592Sbill 		case ADISP: /* expr(%r) */
251629Shenry 			ap->a_areg1 |= 0xA0;
252629Shenry 			if ((xp->e_xtype&XTYPE)!=XABS || xp->e_xtype&XFORW){
253629Shenry 				ap->a_areg1 += mod124[ap->a_dispsize];
254629Shenry 				xtrab=len124[ap->a_dispsize];
255592Sbill 				break;
256592Sbill 			}
257629Shenry 			if (xp->e_xvalue==0 && !(ap->a_areg1&0x10)) {
258629Shenry 				ap->a_areg1 ^= 0xC0;
259592Sbill 				break;
260592Sbill 			}
261592Sbill 			xtrab=LEN1;
262629Shenry 			if ((xp->e_xvalue<MINBYTE) || (xp->e_xvalue>MAXBYTE)){
263629Shenry 				ap->a_areg1 += 0x20;
264592Sbill 				xtrab=LEN2;
265592Sbill 			}
266629Shenry 			if ((xp->e_xvalue<MINWORD) || (xp->e_xvalue>MAXWORD)){
267629Shenry 				ap->a_areg1 += 0x20;
268592Sbill 				xtrab=LEN4;
269592Sbill 			}
270592Sbill 			break;
271592Sbill 
272592Sbill 		case AIMM:  /* $expr */
273629Shenry 			if (ap->a_atype&ASTAR)
274592Sbill 				a=TYPL;
275592Sbill 			else {
276629Shenry 				a = fetcharg(itab[op], i);
277592Sbill 				if (a&ACCA)
278592Sbill 					a=TYPL;
279592Sbill 				else
280592Sbill 					a &= TYPMASK;
281629Shenry 				if (    ( (xp->e_xtype&XTYPE) == XABS)
282629Shenry 				    && !(xp->e_xtype&XFORW)
283629Shenry 				    &&  (xp->e_xvalue >= 0)
284629Shenry 				    &&  (xp->e_xvalue <= 63)
285629Shenry 				    &&  (xp->e_yvalue == 0)
286592Sbill 				    &&  (a != TYPF)
287592Sbill 				    &&  (a != TYPD) ) {
288629Shenry 					ap->a_areg1 = xp->e_xvalue;
289592Sbill 					break;
290592Sbill 				}
291592Sbill 			}
292629Shenry 			ap->a_areg1 |= 0x8F;
293592Sbill 			switch (a) {
294592Sbill 			case TYPD:
295592Sbill 			case TYPF:
296629Shenry 				if (   ((xp->e_xtype&XTYPE)==XABS)
297629Shenry 				    && (!(xp->e_xtype&XFORW))
298592Sbill 				    && (slitflt(xp))
299592Sbill 				){
300629Shenry 					ap->a_areg1=extlitflt(xp);
301592Sbill 				} else {
302592Sbill 					xtrab = (a==TYPF) ? LEN4: LEN8;
303592Sbill 				}
304592Sbill 				break;
305592Sbill 			case TYPQ: xtrab = LEN8; break;
306592Sbill 			case TYPL: xtrab = LEN4; break;
307592Sbill 			case TYPW: xtrab = LEN2; break;
308592Sbill 			case TYPB: xtrab = LEN1; break;
309592Sbill 			}
310592Sbill 			break;
311592Sbill 
312592Sbill 		}	/*end of the switch on a*/
313592Sbill 		/*
314592Sbill 		 *	use the first byte to describe the argument
315592Sbill 		 */
316592Sbill #ifdef UNIX
317629Shenry 		outb(ap->a_areg1);
318592Sbill #endif UNIX
319592Sbill #ifdef VMS
320629Shenry 		*vms_obj_ptr++ = -1; *vms_obj_ptr++ = (char)(ap->a_areg1);
321629Shenry 		dotp->e_xvalue += 1;
322592Sbill 		if ((vms_obj_ptr-sobuf) > 400) {
323592Sbill 			write(objfil,sobuf,vms_obj_ptr-sobuf);
324592Sbill 			vms_obj_ptr=sobuf+1;
325592Sbill 		}
326592Sbill #endif VMS
327592Sbill 		if (xtrab)
328592Sbill 			/*
329592Sbill 			 *	Floating point numbers are written to a.out
330592Sbill 			 *	by outrel; they require that the least significant
331592Sbill 			 *	4 bytes of an 8 byte double precision number
332592Sbill 			 *	immediately follow the field xvalue, which
333592Sbill 			 *	they do.
334592Sbill 			 */
335629Shenry 			outrel(&xp->e_xvalue, xtrab, xp->e_xtype, xp->e_xname);
336592Sbill 	}	/*end of the for to pick up all arguments*/
337592Sbill }
338