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