Commit | Line | Data |
---|---|---|
cb3898cb | 1 | /* Copyright (c) 1980 Regents of the University of California */ |
593d71c1 | 2 | static char sccsid[] = "@(#)ascode.c 4.3 %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 | } | |
593d71c1 RH |
52 | if (exp & ACCA){ |
53 | if (atm == AREG) { | |
54 | yyerror("arg %d, addressing a register",i); | |
55 | return; | |
56 | } | |
57 | if ( (atm == AIMM) && !(at & ASTAR) ){ | |
58 | yyerror("arg %d, addressing an immediate operand",i); | |
59 | return; | |
60 | } | |
cb3898cb BJ |
61 | } |
62 | if ((exp&ACCW) && (atm==AIMM) && !(at&ASTAR)) { | |
63 | yyerror("arg %d, modifying a constant",i); | |
64 | return; | |
65 | } | |
66 | if (at & AINDX) { | |
451260e7 | 67 | if (act->a_areg2==017) { |
cb3898cb BJ |
68 | yyerror("arg %d, PC used as index",i); |
69 | return; | |
70 | } | |
71 | if (atm==AREG) { | |
72 | yyerror("arg %d, indexing the register file",i); | |
73 | return; | |
74 | } | |
75 | if (atm==AIMM) { | |
76 | yyerror("arg %d, indexing a constant",i); | |
77 | return; | |
78 | } | |
451260e7 | 79 | if (((atm==ADECR) || (atm==AINCR)) && (act->a_areg1==act->a_areg2)) { |
cb3898cb BJ |
80 | yyerror("arg %d, indexing with modified register",i); |
81 | return; | |
82 | } | |
83 | } | |
84 | } | |
85 | ||
86 | extern int d124; | |
87 | int len124[] = {0,LEN1,LEN2,0,LEN4}; | |
88 | char mod124[] = {0,0x00,0x20,0,0x40}; | |
89 | ||
90 | putins(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 | ||
185 | PASS2: | |
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 | } |