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