xref: /csrg-svn/old/as.vax/ascode.c (revision 673)
1592Sbill /* Copyright (c) 1980 Regents of the University of California */
2*673Shenry static	char sccsid[] = "@(#)ascode.c 4.5 08/20/80";
3592Sbill #include <stdio.h>
4592Sbill #include "as.h"
5592Sbill #include "assyms.h"
6592Sbill 
7*673Shenry /*
8*673Shenry  *	Loader reference types  (plust PCREL) to bytes and lg bytes
9*673Shenry  */
10*673Shenry /*		LEN1	LEN1+PC	LEN2	LEN2+PC	LEN4	LEN4+PC	LEN8	LEN8+PC*/
11*673Shenry int	reflen[] = 	/* {LEN*+PCREL} ==> number of bytes */
12*673Shenry {0,	0,	1,	1,	2,	2,	4,	4,	8,	8};
13*673Shenry int	lgreflen[] =	/* {LEN*+PCREL} ==> lg number of bytes */
14*673Shenry {-1,	-1,	0,	0,	1,	1,	2,	2,	3,	3};
15*673Shenry 
16*673Shenry /*
17*673Shenry  *	Sizes to Loader reference types and type flags
18*673Shenry  */
19*673Shenry /*0	1	2	3	4	5	6	7	8*/
20*673Shenry int	len124[] = 	/* {1,2,4,8} ==> {LEN1, LEN2, LEN4, LEN8} */
21*673Shenry {0,	LEN1,	LEN2,	0,	LEN4,	0,	0,	0,	LEN8};
22*673Shenry char	mod124[] = 	/* {1,2,4,8} ==> {bits to construct operands */
23*673Shenry {0,	0x00,	0x20,	0,	0x40,	0,	0,	0,	0};
24*673Shenry int	type_124[] =	/* {1,2,4,8} ==> {TYPB, TYPW, TYPL, TYPQ} */
25*673Shenry {0,	 TYPB,	TYPW,	 0,	 TYPL,	 0,	 0,	 0,	 TYPQ};
26*673Shenry 
27*673Shenry /*
28*673Shenry  *	type flags to Loader reference and byte lengths
29*673Shenry  */
30*673Shenry /*TYPB	TYPW	TYPL	TYPQ	TYPF	TYPD*/
31*673Shenry int	ty_NORELOC[] =	/* {TYPB..TYPD} ==> {1 if relocation not OK */
32*673Shenry {0,	0,	0,	1,	1,	1};
33*673Shenry int	ty_LEN[] =	/* {TYPB..TYPD} ==> {LEN1..LEN8} */
34*673Shenry {LEN1,	LEN2,	LEN4,	LEN8,	LEN4,	LEN8};
35*673Shenry int	ty_nbyte[] =	/* {TYPB..TYPD} ==> {1,2,4,8} */
36*673Shenry {1,	2,	4,	8,	4,	8};
37*673Shenry int	ty_nlg[] =	/* {TYPB..TYPD} ==> lg{1,2,4,8} */
38*673Shenry {0,	1,	2,	3,	2,	3};
39*673Shenry 
40592Sbill insout(op, ap, nact)
41592Sbill 	struct arg *ap;
42592Sbill {
43667Shenry 	int		jxxflg;
44667Shenry 	register	struct	instab	*ip;		/* the instruction */
45667Shenry 	register	struct	arg	*ap_walk;	/* actual param walk */
46667Shenry 	register	int	i;
47667Shenry 	register	int	ap_type;		/* actual param type */
48667Shenry 	register	int	ap_type_mask;		/* masked actual param */
49592Sbill 	op &= 0xFF;
50592Sbill 	jxxflg = nact;
51592Sbill 	if (nact < 0)
52592Sbill 		nact = -nact;
53592Sbill 	if (passno == 1) {
54667Shenry 	    ip = itab[op];
55667Shenry 	    if (nact < ip->i_nargs)
56667Shenry 		yyerror("Too few arguments");
57667Shenry 	    if (nact > ip->i_nargs) {
58667Shenry 		yyerror("Too many arguments");
59667Shenry 		nact = ip->i_nargs;
60667Shenry 	    }
61667Shenry 	    /*
62667Shenry 	     *	Check argument compatability with instruction template
63667Shenry 	     */
64667Shenry 	    for (ap_walk = ap, i = 1; i <= nact; ap_walk++, i++){
65*673Shenry 		ap_type = ap_walk->a_atype;
66667Shenry 		ap_type_mask = ap_type & AMASK;
67*673Shenry 		switch( (fetcharg(ip, i-1)) & ACCESSMASK){	/* type of fp */
68667Shenry 		case ACCB:
69667Shenry 			if ( !((ap_type_mask == AEXP) || (ap_type_mask == AIMM)) ){
70667Shenry 				yyerror("arg %d, branch displacement must be an expression",i);
71667Shenry 				return;
72667Shenry 			}
73667Shenry 			break;
74667Shenry 		case ACCA:
75667Shenry 			switch(ap_type_mask){
76667Shenry 			case AREG:	yyerror("arg %d, addressing a register",i);
77667Shenry 					return;
78667Shenry 			case AIMM:	if ( !(ap_type & ASTAR) ){
79667Shenry 					 yyerror("arg %d, addressing an immediate operand",i);
80667Shenry 					 return;
81667Shenry 					}
82667Shenry 			}
83667Shenry 			break;
84667Shenry 		case ACCM:
85667Shenry 		case ACCW:
86667Shenry 			switch(ap_type_mask){
87667Shenry 			case AIMM:	if (!(ap_type&ASTAR)) {
88667Shenry 					 yyerror("arg %d, modifying a constant",i);
89667Shenry 					 return;
90667Shenry 					}
91667Shenry 			}
92667Shenry 			break;
93667Shenry 		}	/* end of the switch on fp_type */
94667Shenry 		if (ap_type & AINDX) {
95667Shenry 			if (ap_walk->a_areg2==0xF) {
96667Shenry 				yyerror("arg %d, PC used as index",i);
97667Shenry 				return;
98667Shenry 			}
99667Shenry 			switch(ap_type_mask){
100667Shenry 			case AREG:	yyerror("arg %d, indexing the register file",i);
101667Shenry 					return;
102667Shenry 			case AIMM:	yyerror("arg %d, indexing a constant",i);
103667Shenry 					return;
104*673Shenry 			case ADECR:
105*673Shenry 			case AINCR:	if (ap_walk->a_areg1==ap_walk->a_areg2) {
106667Shenry 						yyerror("arg %d, indexing with modified register",i);
107667Shenry 						return;
108667Shenry 					}
109667Shenry 					break;
110667Shenry 			}	/* end of switch on ap_type_mask */
111667Shenry 		} /* end of AINDX */
112667Shenry 	   }
113667Shenry 	} /* both passes here */
114592Sbill 	if (jxxflg < 0)
115592Sbill 		ijxout(op, ap, nact);
116592Sbill 	else putins(op, ap, nact);
117592Sbill }
118592Sbill 
119592Sbill extern	int d124;
120592Sbill 
121592Sbill putins(op, ap, n)
122592Sbill 	/*
123592Sbill 	 *	n had better be positive
124592Sbill 	 */
125592Sbill 	register struct arg *ap;
126592Sbill {
127592Sbill 	register struct exp 	*xp;
128592Sbill 	register int 		a;
129*673Shenry 	int 			i;
130*673Shenry 	int			reloc_how;
131592Sbill 
132592Sbill #ifdef DEBUG
133592Sbill 	fflush(stdout);
134592Sbill #endif
135592Sbill 	if (passno == 2)
136592Sbill 		goto PASS2;
137592Sbill 
138629Shenry 	dotp->e_xvalue += n+1;		/* 1 for the opcode, at least 1 per arg */
139629Shenry 	for (i=0; i<n; i++,ap++) {	/* some args take more than 1 byte */
140629Shenry 	    a = ap->a_atype;
141592Sbill 	    if (a & AINDX)
142629Shenry 		dotp->e_xvalue++;
143592Sbill 	    switch (a&~(AINDX|ASTAR)) {
144592Sbill 		case AEXP:
145629Shenry 			a = fetcharg(itab[op], i);
146592Sbill 			if (a == ACCB+TYPB)
147592Sbill 				break;
148592Sbill 			if (a==ACCB+TYPW){
149629Shenry 				dotp->e_xvalue++;
150592Sbill 				break;
151592Sbill 			}
152592Sbill 			/*
153592Sbill 			 *	Reduces to PC relative
154592Sbill 			 */
155629Shenry 			dotp->e_xvalue += ap->a_dispsize;
156592Sbill 			break;
157592Sbill 
158592Sbill 		case ADISP:
159629Shenry 			xp=ap->a_xp;
160629Shenry 			if ((xp->e_xtype&XTYPE)!=XABS || xp->e_xtype&XFORW){
161629Shenry 				dotp->e_xvalue += ap->a_dispsize;
162592Sbill 				break;
163592Sbill 			}
164629Shenry 			if (xp->e_xvalue==0 && !(a&ASTAR))
165592Sbill 				break;
166629Shenry 			dotp->e_xvalue++;
167629Shenry 			if ((xp->e_xvalue<MINBYTE) || (xp->e_xvalue>MAXBYTE))
168629Shenry 				dotp->e_xvalue++;
169629Shenry 			if ((xp->e_xvalue<MINWORD) || (xp->e_xvalue>MAXWORD))
170629Shenry 				dotp->e_xvalue += 2;
171592Sbill 			break;
172592Sbill 
173592Sbill 		case AIMM:
174629Shenry 			if (ap->a_atype&ASTAR) a=TYPL;
175592Sbill 			else {
176629Shenry 				a = fetcharg(itab[op], i);
177592Sbill 				if (a&ACCA)
178592Sbill 					a = TYPL;
179592Sbill 				else
180592Sbill 					a &= TYPMASK;
181629Shenry 				xp = ap->a_xp;
182629Shenry 				if (   ((xp->e_xtype&XTYPE)==XABS)
183629Shenry 				    && (!(xp->e_xtype&XFORW))
184629Shenry 				    && (xp->e_xvalue>=0)
185629Shenry 				    && (xp->e_xvalue<=63)
186629Shenry 				    && (xp->e_yvalue == 0)
187592Sbill 				    && (a != TYPD)
188592Sbill 				    && (a != TYPF)
189592Sbill 				)
190592Sbill 						break;
191592Sbill 			}
192592Sbill 			switch (a) {
193592Sbill 			case TYPD:
194592Sbill 			case TYPF:
195629Shenry 				if (   !(((xp->e_xtype&XTYPE)==XABS)
196629Shenry 				    && (!(xp->e_xtype&XFORW))
197592Sbill 				    && (slitflt(xp)))
198592Sbill 				){
199592Sbill 				/* it is NOT short */
200629Shenry 					dotp->e_xvalue += ((a==TYPF)?
201592Sbill 						4 : 8);
202592Sbill 				}
203592Sbill 				break;
204592Sbill 			case TYPQ:
205629Shenry 				dotp->e_xvalue += 8;break;
206592Sbill 			case TYPL:
207629Shenry 				dotp->e_xvalue += 4;break;
208592Sbill 			case TYPW:
209629Shenry 				dotp->e_xvalue += 2;break;
210592Sbill 			case TYPB:
211629Shenry 				dotp->e_xvalue += 1;break;
212592Sbill 			}	/*end of the switch on a*/
213592Sbill 	    }	/*end of the switch on the type*/
214592Sbill 	}	/*end of looping for all arguments*/
215592Sbill 	return;
216592Sbill 
217592Sbill PASS2:
218592Sbill 
219592Sbill #ifdef UNIX
220592Sbill 	outb(op); /* the opcode */
221592Sbill #endif UNIX
222592Sbill #ifdef VMS
223592Sbill 	*vms_obj_ptr++ = -1; *vms_obj_ptr++ = (char)op;
224629Shenry 	dotp->e_xvalue += 1;
225592Sbill #endif VMS
226592Sbill 
227592Sbill 	for (i=0; i<n; i++,ap++) {/* now for the arguments */
228629Shenry 		a=ap->a_atype;
229629Shenry 		xp=ap->a_xp;
230*673Shenry 		reloc_how = TYPNONE;
231592Sbill 		if (a&AINDX) {
232592Sbill #ifdef UNIX
233629Shenry 			{ outb(0x40 | ap->a_areg2); }
234592Sbill #endif UNIX
235592Sbill #ifdef VMS
236592Sbill 			{ *vms_obj_ptr++ = -1;
237629Shenry 			  *vms_obj_ptr++ = (0x40 | ap->a_areg2);
238629Shenry 			  dotp->e_xvalue += 1; }
239592Sbill #endif VMS
240592Sbill 			a &= ~AINDX;
241592Sbill 		}
242592Sbill 		if (a&ASTAR) {
243629Shenry 			ap->a_areg1 |= 0x10;
244592Sbill 			a &= ~ASTAR;
245592Sbill 		}
246592Sbill 		switch (a) {
247592Sbill 		case AREG:		/* %r */
248629Shenry 			ap->a_areg1 |= 0x50;
249592Sbill 			break;
250592Sbill 		case ABASE:		/* (%r) */
251629Shenry 			ap->a_areg1 |= 0x60;
252592Sbill 			break;
253592Sbill 		case ADECR: 		/* -(%r) */
254629Shenry 			ap->a_areg1 |= 0x70;
255592Sbill 			break;
256665Shenry 		case AINCR:		/* (%r)+ */
257629Shenry 			ap->a_areg1 |= 0x80;
258592Sbill 			break;
259592Sbill 		case AEXP: /* expr */
260629Shenry 			a = fetcharg(itab[op], i);
261592Sbill 			if (a == ACCB+TYPB) {
262629Shenry 				ap->a_areg1 = a =
263629Shenry 					xp->e_xvalue - (dotp->e_xvalue + 1);
264592Sbill 				if (a<MINBYTE || a>MAXBYTE)
265592Sbill 					yyerror("Branch too far"); break;
266592Sbill 			}
267592Sbill 			if (a == ACCB+TYPW) {
268629Shenry 				ap->a_areg1 = a = xp->e_xvalue
269629Shenry 					-= dotp->e_xvalue + 2;
270629Shenry 				xp->e_xtype = XABS;
271592Sbill 				if (a<MINWORD || a>MAXWORD)
272592Sbill 					yyerror("Branch too far");
273629Shenry 				xp->e_xvalue = a>>8;
274*673Shenry 				reloc_how = TYPB;
275592Sbill 				break;
276592Sbill 			}
277592Sbill 			/* reduces to expr(pc) mode */
278629Shenry 			ap->a_areg1 |= (0xAF + mod124[ap->a_dispsize]);
279*673Shenry 			reloc_how = type_124[ap->a_dispsize] + RELOC_PCREL;
280592Sbill 			break;
281592Sbill 
282592Sbill 		case ADISP: /* expr(%r) */
283629Shenry 			ap->a_areg1 |= 0xA0;
284629Shenry 			if ((xp->e_xtype&XTYPE)!=XABS || xp->e_xtype&XFORW){
285629Shenry 				ap->a_areg1 += mod124[ap->a_dispsize];
286*673Shenry 				reloc_how = type_124[ap->a_dispsize];
287592Sbill 				break;
288592Sbill 			}
289629Shenry 			if (xp->e_xvalue==0 && !(ap->a_areg1&0x10)) {
290629Shenry 				ap->a_areg1 ^= 0xC0;
291592Sbill 				break;
292592Sbill 			}
293*673Shenry 			reloc_how = TYPB;
294629Shenry 			if ((xp->e_xvalue<MINBYTE) || (xp->e_xvalue>MAXBYTE)){
295629Shenry 				ap->a_areg1 += 0x20;
296*673Shenry 				reloc_how = TYPW;
297592Sbill 			}
298629Shenry 			if ((xp->e_xvalue<MINWORD) || (xp->e_xvalue>MAXWORD)){
299629Shenry 				ap->a_areg1 += 0x20;
300*673Shenry 				reloc_how = TYPL;
301592Sbill 			}
302592Sbill 			break;
303592Sbill 
304592Sbill 		case AIMM:  /* $expr */
305629Shenry 			if (ap->a_atype&ASTAR)
306592Sbill 				a=TYPL;
307592Sbill 			else {
308629Shenry 				a = fetcharg(itab[op], i);
309592Sbill 				if (a&ACCA)
310592Sbill 					a=TYPL;
311592Sbill 				else
312592Sbill 					a &= TYPMASK;
313629Shenry 				if (    ( (xp->e_xtype&XTYPE) == XABS)
314629Shenry 				    && !(xp->e_xtype&XFORW)
315629Shenry 				    &&  (xp->e_xvalue >= 0)
316629Shenry 				    &&  (xp->e_xvalue <= 63)
317629Shenry 				    &&  (xp->e_yvalue == 0)
318592Sbill 				    &&  (a != TYPF)
319592Sbill 				    &&  (a != TYPD) ) {
320629Shenry 					ap->a_areg1 = xp->e_xvalue;
321592Sbill 					break;
322592Sbill 				}
323592Sbill 			}
324629Shenry 			ap->a_areg1 |= 0x8F;
325*673Shenry 			reloc_how = a;
326*673Shenry 			if (reloc_how == TYPD || reloc_how == TYPF){
327629Shenry 				if (   ((xp->e_xtype&XTYPE)==XABS)
328629Shenry 				    && (!(xp->e_xtype&XFORW))
329592Sbill 				    && (slitflt(xp))
330592Sbill 				){
331*673Shenry 					reloc_how = TYPNONE;
332629Shenry 					ap->a_areg1=extlitflt(xp);
333592Sbill 				}
334592Sbill 			}
335592Sbill 			break;
336592Sbill 
337592Sbill 		}	/*end of the switch on a*/
338592Sbill 		/*
339592Sbill 		 *	use the first byte to describe the argument
340592Sbill 		 */
341592Sbill #ifdef UNIX
342629Shenry 		outb(ap->a_areg1);
343592Sbill #endif UNIX
344592Sbill #ifdef VMS
345629Shenry 		*vms_obj_ptr++ = -1; *vms_obj_ptr++ = (char)(ap->a_areg1);
346629Shenry 		dotp->e_xvalue += 1;
347592Sbill 		if ((vms_obj_ptr-sobuf) > 400) {
348592Sbill 			write(objfil,sobuf,vms_obj_ptr-sobuf);
349592Sbill 			vms_obj_ptr=sobuf+1;
350592Sbill 		}
351592Sbill #endif VMS
352*673Shenry 		if (reloc_how != TYPNONE)
353*673Shenry 			outrel(xp, reloc_how);
354592Sbill 	}	/*end of the for to pick up all arguments*/
355592Sbill }
356