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