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