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