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