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