xref: /original-bsd/old/as.vax/ascode.c (revision fbed46ce)
1 /*
2  *	Copyright (c) 1982 Regents of the University of California
3  */
4 #ifndef lint
5 static char sccsid[] = "@(#)ascode.c 4.8 02/14/82";
6 #endif not lint
7 
8 #include <stdio.h>
9 #include "as.h"
10 #include "assyms.h"
11 
12 insout(opcode, ap, nact)
13 	struct	Opcode	opcode;
14 	struct	arg	*ap;
15 	int	nact;
16 {
17 	int	jxxflg;
18 	reg	struct	instab	*ip;		/* the instruction */
19 	reg	struct	arg	*ap_walk;	/* actual param walk */
20 	reg	int	i;
21 	reg	int	ap_type;		/* actual param type */
22 	reg	int	ap_type_mask;		/* masked actual param */
23 
24 	jxxflg = nact;
25 	if (nact < 0)
26 		nact = -nact;
27 	if (passno == 1) {
28 		if (!(ITABCHECK(opcode)))
29 			panic("Botched reference into itab");
30 		ip = ITABFETCH(opcode);
31 		if (nact < ip->i_nargs)
32 			yyerror("Too few arguments");
33 		if (nact > ip->i_nargs) {
34 			yyerror("Too many arguments");
35 			nact = ip->i_nargs;
36 		}
37 	    /*
38 	     *	Check argument compatability with instruction template
39 	     */
40 	    for (ap_walk = ap, i = 1; i <= nact; ap_walk++, i++){
41 		ap_type = ap_walk->a_atype;
42 		ap_type_mask = ap_type & AMASK;
43 		/*
44 		 *	The switch value is >> by TYPLG so that the switch
45 		 *	code is dense, not implemented as a sequence
46 		 *	of branches but implemented as a casel.
47 		 *	In addition, cases ACCI and ACCR are added to force
48 		 *	dense switch code.
49 		 *	switch on the type of fp
50 		 */
51 		switch( ((fetcharg(ip, i-1)) & ACCESSMASK) >> TYPLG){
52 		case ACCI >> TYPLG:
53 		case ACCR >> TYPLG:
54 			break;
55 		case ACCB >> TYPLG:
56 			if ( !((ap_type_mask == AEXP) || (ap_type_mask == AIMM)) ){
57 				yyerror("arg %d, branch displacement must be an expression",i);
58 				return;
59 			}
60 			break;
61 		case ACCA >> TYPLG:
62 			switch(ap_type_mask){
63 			case AREG:	yyerror("arg %d, addressing a register",i);
64 					return;
65 			case AIMM:	if ( !(ap_type & ASTAR) ){
66 					 yyerror("arg %d, addressing an immediate operand",i);
67 					 return;
68 					}
69 			}
70 			break;
71 		case ACCM >> TYPLG:
72 		case ACCW >> TYPLG:
73 			switch(ap_type_mask){
74 			case AIMM:	if (!(ap_type&ASTAR)) {
75 					 yyerror("arg %d, modifying a constant",i);
76 					 return;
77 					}
78 			}
79 			break;
80 		}	/* end of the switch on fp_type */
81 		if (ap_type & AINDX) {
82 			if (ap_walk->a_areg2==0xF) {
83 				yyerror("arg %d, PC used as index",i);
84 				return;
85 			}
86 			switch(ap_type_mask){
87 			case AREG:	yyerror("arg %d, indexing the register file",i);
88 					return;
89 			case AIMM:	yyerror("arg %d, indexing a constant",i);
90 					return;
91 			case ADECR:
92 			case AINCR:	if (ap_walk->a_areg1==ap_walk->a_areg2) {
93 						yyerror("arg %d, indexing with modified register",i);
94 						return;
95 					}
96 					break;
97 			}	/* end of switch on ap_type_mask */
98 		} /* end of AINDX */
99 	   }
100 	} /* both passes here */
101 	if (jxxflg < 0)
102 		ijxout(opcode, ap, nact);
103 	else
104 		putins(opcode, ap, nact);
105 }
106 
107 extern	int d124;
108 
109 putins(opcode, ap, n)
110 	struct	Opcode	opcode;
111 	register struct arg *ap;
112 	int	n;			/* Must be positive */
113 {
114 	reg	struct exp 	*xp;
115 	reg	int 	argtype;
116 		int 	i;
117 		int	reloc_how;
118 		int	value;
119 
120 #ifdef DEBUG
121 	fflush(stdout);
122 #endif
123 	if (passno == 2)
124 		goto PASS2;
125 
126 	dotp->e_xvalue += n;		/* at least one byte per arg */
127 	switch(opcode.Op_eopcode){
128 	case NEW:
129 	case CORE:
130 		dotp->e_xvalue += 1;	/* 1 byte opcode */
131 		break;
132 	case ESCD:
133 	case ESCF:
134 		dotp->e_xvalue += 2;	/* 2 byte opcode */
135 		break;
136 	default:
137 		panic("Bad escape opcode");
138 	}
139 
140 	for (i=0; i<n; i++,ap++) {	/* some args take more than 1 byte */
141 	    argtype = ap->a_atype;
142 	    if (argtype & AINDX)
143 		dotp->e_xvalue++;
144 	    /*
145 	     *	This switch has been fixed by enumerating the no action
146 	     *	alternatives (those that have 1 one byte of code)
147 	     *	so that a casel instruction is emitted.
148 	     */
149 	    switch (argtype&~(AINDX|ASTAR)) {
150 		case AREG:
151 		case ABASE:
152 		case ADECR:
153 		case AINCR:
154 			break;
155 		case AEXP:
156 			argtype = fetcharg(ITABFETCH(opcode), i);
157 			if (argtype == A_BB)
158 				break;
159 			if (argtype == A_BW){
160 				dotp->e_xvalue++;
161 				break;
162 			}
163 			/*
164 			 *	Reduces to PC relative
165 			 */
166 			dotp->e_xvalue += ap->a_dispsize;
167 			break;
168 
169 		case ADISP:
170 			xp=ap->a_xp;
171 			if ((xp->e_xtype&XTYPE)!=XABS || xp->e_xtype&XFORW){
172 				dotp->e_xvalue += ap->a_dispsize;
173 				break;
174 			}
175 			if (xp->e_xvalue==0 && !(argtype&ASTAR))
176 				break;
177 			dotp->e_xvalue += 1;
178 			if (ISBYTE(xp->e_xvalue))
179 				break;
180 			dotp->e_xvalue += 1;
181 			if (ISWORD(xp->e_xvalue))
182 				break;
183 			dotp->e_xvalue += 2;
184 			break;
185 
186 		case AIMM:
187 			if (ap->a_atype&ASTAR) {
188 				argtype=TYPL;
189 			} else {
190 				argtype = fetcharg(ITABFETCH(opcode), i);
191 				if (argtype&ACCA)
192 					argtype = TYPL;
193 				else
194 					argtype &= TYPMASK;
195 				xp = ap->a_xp;
196 				if (immconstant(ap->a_xp, argtype, &value))
197 					break;
198 			}
199 			dotp->e_xvalue += ty_nbyte[argtype];
200 	    }	/*end of the switch on the type*/
201 	}	/*end of looping for all arguments*/
202 	return;
203 
204 PASS2:
205 	/*
206 	 *	Output the opcode
207 	 */
208 	switch(opcode.Op_eopcode){
209 	case NEW:
210 		nnewopcodes++;
211 		break;
212 	case ESCD:
213 	case ESCF:
214 		nGHopcodes++;
215 		Outb(opcode.Op_eopcode);
216 		break;
217 	case CORE:
218 		break;
219 	default:
220 		panic("Bad escape opcode");
221 	}
222 	Outb(opcode.Op_popcode);
223 
224 	for (i=0; i<n; i++,ap++) {/* now for the arguments */
225 		argtype=ap->a_atype;
226 		xp=ap->a_xp;
227 		reloc_how = TYPNONE;
228 		if (argtype&AINDX) {
229 			{ Outb(0x40 | ap->a_areg2); }
230 			argtype &= ~AINDX;
231 		}
232 		if (argtype&ASTAR) {
233 			ap->a_areg1 |= 0x10;
234 			argtype &= ~ASTAR;
235 		}
236 		switch (argtype) {
237 		case AREG:		/* %r */
238 			ap->a_areg1 |= 0x50;
239 			break;
240 		case ABASE:		/* (%r) */
241 			ap->a_areg1 |= 0x60;
242 			break;
243 		case ADECR: 		/* -(%r) */
244 			ap->a_areg1 |= 0x70;
245 			break;
246 		case AINCR:		/* (%r)+ */
247 			ap->a_areg1 |= 0x80;
248 			break;
249 		case AEXP: /* expr */
250 			argtype = fetcharg(ITABFETCH(opcode), i);
251 			if (argtype == A_BB) {
252 				ap->a_areg1 = argtype =
253 					xp->e_xvalue - (dotp->e_xvalue + 1);
254 				if (xp->e_xtype & XXTRN)
255 					yywarning("%s: destination label is external",
256 						ITABFETCH(opcode)->s_name);
257 				if (!ISBYTE(argtype))
258 					yyerror("%s: Branch too far: %d",
259 						ITABFETCH(opcode)->s_name,
260 						argtype);
261 				break;
262 			}
263 			if (argtype == A_BW) {
264 				ap->a_areg1 = argtype = xp->e_xvalue
265 					-= dotp->e_xvalue + 2;
266 				if (xp->e_xtype & XXTRN)
267 					yywarning("%s: destination label is external",
268 						ITABFETCH(opcode)->s_name);
269 				xp->e_xtype = XABS;
270 				if (!ISWORD(argtype))
271 					yyerror("%s: Branch too far: %d",
272 						ITABFETCH(opcode)->s_name,
273 						argtype);
274 				xp->e_xvalue = argtype>>8;
275 				reloc_how = TYPB;
276 				break;
277 			}
278 			/* reduces to expr(pc) mode */
279 			ap->a_areg1 |= (0xAF + mod124[ap->a_dispsize]);
280 			reloc_how = type_124[ap->a_dispsize] + RELOC_PCREL;
281 			break;
282 
283 		case ADISP: /* expr(%r) */
284 			ap->a_areg1 |= 0xA0;
285 			if ((xp->e_xtype&XTYPE)!=XABS || xp->e_xtype&XFORW){
286 				ap->a_areg1 += mod124[ap->a_dispsize];
287 				reloc_how = type_124[ap->a_dispsize];
288 				break;
289 			}
290 			if (xp->e_xvalue==0 && !(ap->a_areg1&0x10)) {
291 				ap->a_areg1 ^= 0xC0;
292 				break;
293 			}
294 			reloc_how = TYPB;
295 			if (ISBYTE(xp->e_xvalue))
296 				break;
297 			ap->a_areg1 += 0x20;
298 			reloc_how = TYPW;
299 			if (ISWORD(xp->e_xvalue))
300 				break;
301 			ap->a_areg1 += 0x20;
302 			reloc_how = TYPL;
303 			break;
304 
305 		case AIMM:  /* $expr */
306 			if (ap->a_atype&ASTAR) {
307 				argtype=TYPL;
308 			} else {
309 				argtype = fetcharg(ITABFETCH(opcode), i);
310 				if (argtype&ACCA)
311 					argtype = TYPL;
312 				else
313 					argtype &= TYPMASK;
314 				if (immconstant(xp, argtype, &value)){
315 					reloc_how = TYPNONE;
316 					ap->a_areg1 = value;
317 					break;
318 				}
319 			}
320 			ap->a_areg1 |= 0x8F;
321 			reloc_how = argtype;
322 			break;
323 
324 		}	/*end of the switch on argtype*/
325 		/*
326 		 *	use the first byte to describe the argument
327 		 */
328 		Outb(ap->a_areg1);
329 #ifdef VMS
330 		if ((vms_obj_ptr-sobuf) > 400) {
331 			write(objfil,sobuf,vms_obj_ptr-sobuf);
332 			vms_obj_ptr=sobuf+1;
333 		}
334 #endif VMS
335 		if (reloc_how != TYPNONE)
336 			outrel(xp, reloc_how);
337 	}	/*end of the for to pick up all arguments*/
338 }
339 /*
340  *	Is xp an immediate constant?
341  *	argtype: how the instruction will interpret the bytes
342  *	xp->e_number.num_tag ("numtype"): the kind of number given
343  *
344  *	Use the following table:
345  *	float: TYPF, TYPD, TYPG, TYPH
346  *	quad: TYPQ, TYPO
347  *	int: TYPG, TYPW, TYPL
348  *
349  *				numtype
350  *	argtype		float	quad	int
351  *
352  *	float		slitflt	slitflt	slitflt
353  *	quad		0	0	0
354  *	int		0..63	0	0..63
355  *
356  *	Where the table entry implies the predicate to return.
357  */
358 #define	IMMFLT	1		/* these flags are not used by anybody (yet) */
359 #define	IMMINT	2
360 
361 int immconstant(xp, argtype, valuep)
362 	reg	struct	exp	*xp;
363 		int	argtype;
364 		int	*valuep;
365 {
366 	reg	int	back = 0;
367 		int	numtype;
368 	reg	int	fits;
369 
370 	if ((xp->e_xtype & XTYPE) != XABS)
371 		return(0);
372 	if ((xp->e_xtype & XFORW) != 0)
373 		return(0);
374 	numtype = xp->e_number.num_tag;
375 
376 	fits = 1;
377 	if (passno == 2) switch(argtype){
378 	case TYPB:
379 		switch(numtype){
380 		default:	fits = 0; break;
381 		case TYPB:	fits = 1; break;
382 		case TYPW:
383 		case TYPL:
384 			fits = ISBYTE(xp->e_xvalue) || ISUBYTE(xp->e_xvalue);
385 			break;
386 		}
387 		break;
388 	case TYPW:
389 		switch(numtype){
390 		default:	fits = 0; break;
391 		case TYPB:
392 		case TYPW:	fits = 1; break;
393 		case TYPL:
394 			fits = ISWORD(xp->e_xvalue) || ISUWORD(xp->e_xvalue);
395 			break;
396 		}
397 		break;
398 	case TYPF:
399 		if (numtype == TYPD){	/* same format for first 32 bits */
400 			fits = 1;
401 			break;
402 		}
403 		/*FALLTHROUGH*/
404 	default:
405 		fits = ty_nbyte[argtype] >= ty_nbyte[numtype];
406 	}
407 	if (!fits){
408 	  yywarning("Immediate constant type %s mismatches instruction type %s",
409 		ty_string[numtype],
410 		ty_string[argtype]);
411 	}
412 
413 	switch(argtype){
414 	case TYPF:
415 	case TYPG:
416 	case TYPD:
417 	case TYPH:
418 		back = slitflt(xp->e_number, argtype, valuep);
419 		break;
420 	case TYPO:
421 	case TYPQ:
422 		back = 0;
423 		break;
424 	case TYPB:
425 	case TYPW:
426 	case TYPL:
427 		switch(numtype){
428 		case TYPO:
429 		case TYPQ:
430 			back = 0;
431 			break;
432 		default:
433 			*valuep = xp->e_xvalue;
434 			back = ISLIT(xp->e_xvalue);
435 			break;
436 		}
437 		break;
438 	}
439 	return(back);
440 }
441