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