1 /*
2 * Copyright (c) 1982 Regents of the University of California
3 */
4 #ifndef lint
5 static char sccsid[] = "@(#)ascode.c 4.11 6/30/83";
6 #endif not lint
7
8 #include <stdio.h>
9 #include "as.h"
10 #include "assyms.h"
11
insout(opcode,ap,nact)12 insout(opcode, ap, nact)
13 u_char opcode;
14 struct arg *ap;
15 int nact;
16 {
17 int jxxflg;
18 reg struct instab *ip; /* the instruction */
19 reg struct arg *ap_walk; /* actual param walk */
20 reg int i;
21 reg int ap_type; /* actual param type */
22 reg int ap_type_mask; /* masked actual param */
23 reg int argtype;
24
25 jxxflg = nact;
26 if (nact < 0)
27 nact = -nact;
28 if (passno == 1) {
29 ip = ITABFETCH(opcode & 0xFF);
30 if (nact < ip->i_nargs)
31 yyerror("Too few arguments");
32 if (nact > ip->i_nargs) {
33 yyerror("Too many arguments");
34 nact = ip->i_nargs;
35 }
36 /*
37 * Check argument compatability with instruction template
38 */
39 for (ap_walk = ap, i = 1; i <= nact; ap_walk++, i++){
40 ap_type = ap_walk->a_atype;
41 ap_type_mask = ap_type & AMASK;
42 /*
43 * The switch value is >> by TYPLG so that the switch
44 * code is dense, not implemented as a sequence
45 * of branches but implemented as a casel.
46 * In addition, cases ACCI and ACCR are added to force
47 * dense switch code.
48 * switch on the type of fp
49 */
50 argtype = fetcharg(ip, i-1);
51 switch( (argtype & ACCESSMASK) >> TYPLG){
52 case ACCI >> TYPLG:
53 break;
54 case ACCR >> TYPLG:
55 if ((argtype == A_RQ) &&
56 (ap_type_mask == AREG) &&
57 (ap_walk->a_areg1 & 0x01)) {
58 yyerror("arg %d, register must be even",i);
59 return;
60 }
61 if (ap_type_mask == ADECR)
62 {
63 yyerror("arg %d, a source arg cant be auto decrement",i);
64 return;
65 }
66 if (argtype == A_RD)
67 {
68 if (ap_type_mask == AIMM)
69 if ( !(ap_type&ASTAR))
70 {
71 yyerror("arg %d, cant be immediate data",i);
72 return;
73 }
74 if ((argtype == A_RD) &&
75 ((ap_type_mask == AINCR) ||
76 (ap_type_mask == ADECR)))
77 {
78 yyerror("arg %d, cant be auto increment/decrement",i);
79 return;
80 }
81 if ((argtype == A_RD) &&
82 (ap_type_mask == AREG) &&
83 (ap_walk->a_areg1 & 0x01)) {
84 yyerror("arg %d, register must be even",i);
85 return;
86 }
87 }
88 break;
89 case ACCB >> TYPLG:
90 if ( ap_type_mask != AEXP)
91 {
92 yyerror("arg %d, branch displacement must be an expression",i);
93 return;
94 }
95 break;
96 case ACCA >> TYPLG:
97 switch(ap_type_mask){
98 case AREG: yyerror("arg %d, addressing a register",i);
99 return;
100 case AIMM: if ( !(ap_type & ASTAR) ){
101 yyerror("arg %d, addressing an immediate operand",i);
102 return;
103 }
104 }
105 break;
106 case ACCM >> TYPLG:
107 case ACCW >> TYPLG:
108 if ((argtype == A_WQ) &&
109 (ap_type_mask == AREG) &&
110 (ap_walk->a_areg1 & 0x01)) {
111 yyerror("arg %d, register must be even",i);
112 return;
113 }
114 switch(ap_type_mask){
115 case AIMM: if (!(ap_type&ASTAR)) {
116 yyerror("arg %d, modifying a constant",i);
117 return;
118 }
119 case AINCR:
120 yyerror("arg %d, a destination arg cant be auto increment",i);
121 return;
122 }
123 break;
124 } /* end of the switch on fp_type */
125 if (ap_type & AINDX) {
126 if (ap_walk->a_areg2==0xF) {
127 yyerror("arg %d, PC used as index",i);
128 return;
129 }
130 if (ap_walk->a_areg2==0xE) {
131 yyerror("arg %d, SP used as index",i);
132 return;
133 }
134 switch(ap_type_mask){
135 case AREG: yyerror("arg %d, indexing the register file",i);
136 return;
137 case AIMM: yyerror("arg %d, indexing a constant",i);
138 return;
139 case ADECR:
140 case AINCR: if (ap_walk->a_areg1==ap_walk->a_areg2) {
141 yyerror("arg %d, indexing with modified register",i);
142 return;
143 }
144 break;
145 } /* end of switch on ap_type_mask */
146 } /* end of AINDX */
147 }
148 } /* both passes here */
149 if (jxxflg < 0)
150 ijxout(opcode, ap, nact);
151 else
152 putins(opcode, ap, nact);
153 }
154
155 extern int d124;
156
putins(opcode,ap,n)157 putins(opcode, ap, n)
158 u_char opcode;
159 register struct arg *ap;
160 int n; /* Must be positive */
161 {
162 reg struct exp *xp;
163 reg int argtype;
164 int i;
165 int reloc_how;
166
167 #ifdef DEBUG
168 fflush(stdout);
169 #endif
170 if (passno == 2)
171 goto PASS2;
172
173 dotp->e_xvalue += n+1; /* at least one byte per arg */
174
175 for (i=0; i<n; i++,ap++) { /* some args take more than 1 byte */
176 argtype = ap->a_atype;
177 if (argtype & AINDX)
178 dotp->e_xvalue++;
179 /*
180 * This switch has been fixed by enumerating the no action
181 * alternatives (those that have 1 one byte of code)
182 * so that a casel instruction is emitted.
183 */
184 switch (argtype&~(AINDX|ASTAR)) {
185 case AREG:
186 case ABASE:
187 case ADECR:
188 case AINCR:
189 break;
190 case AEXP:
191 argtype = fetcharg(ITABFETCH(opcode), i);
192 if (argtype == A_BB)
193 break;
194 if (argtype == A_BW){
195 dotp->e_xvalue++;
196 break;
197 }
198 /*
199 * Reduces to PC relative
200 */
201 dotp->e_xvalue += ap->a_dispsize;
202 break;
203
204 case ADISP:
205 xp=ap->a_xp;
206 if ((xp->e_xtype&XTYPE)!=XABS || xp->e_xtype&XFORW){
207 dotp->e_xvalue += ap->a_dispsize;
208 break;
209 }
210 if (xp->e_xvalue==0 && !(argtype&ASTAR))
211 break;
212 dotp->e_xvalue ++;
213 if (ISBYTE(xp->e_xvalue))
214 break;
215 dotp->e_xvalue ++;
216 if (ISWORD(xp->e_xvalue))
217 break;
218 dotp->e_xvalue += 2;
219 break;
220
221 case AIMM:
222 if (ap->a_atype&ASTAR) {
223 argtype=TYPL;
224 } else {
225 argtype = fetcharg(ITABFETCH(opcode), i);
226 if (argtype&ACCA)
227 argtype = TYPL;
228 else
229 argtype &= TYPMASK;
230 xp = ap->a_xp;
231 if ( ((xp->e_xtype&XTYPE)==XABS)
232 && (!(xp->e_xtype&XFORW))
233 && (argtype != TYPD)
234 && (argtype != TYPF))
235 {
236 if ((xp->e_xvalue>=0)
237 && (xp->e_xvalue<=63))
238 break;
239 if (ISBYTE(xp->e_xvalue))
240 argtype = TYPB;
241 else
242 if (ISWORD(xp->e_xvalue))
243 argtype = TYPW;
244 else
245 argtype = TYPL;
246 }
247 else
248 argtype = TYPL;
249 }
250 switch (argtype) {
251 case TYPD:
252 case TYPF:
253 if (!(slitflt(xp)))
254 return;
255 case TYPQ:
256 case TYPL:
257 case TYPW:
258 case TYPB:
259 dotp->e_xvalue += ty_nbyte[argtype];
260 break;
261 } /*end of the switch on argtype*/
262 } /*end of the switch on the type*/
263 } /*end of looping for all arguments*/
264 return;
265
266 PASS2:
267 /*
268 * Output the opcode
269 */
270 Outb(opcode);
271 if ((passno == 2) && liston)
272 {
273 byte_out (opcode);
274 *layoutpos++ = ' ';
275 }
276
277 for (i=0; i<n; i++,ap++) {/* now for the arguments */
278 argtype=ap->a_atype;
279 xp=ap->a_xp;
280 reloc_how = TYPNONE;
281 if (argtype&AINDX) {
282 { Outb(0x40 | ap->a_areg2);
283 if ((passno == 2) && liston)
284 byte_out (0x40 | ap->a_areg2); }
285 argtype &= ~AINDX;
286 }
287 if (argtype&ASTAR) {
288 ap->a_areg1 |= 0x10;
289 argtype &= ~ASTAR;
290 }
291 switch (argtype) {
292 case AREG: /* %r */
293 ap->a_areg1 |= 0x50;
294 break;
295 case ABASE: /* (%r) */
296 ap->a_areg1 |= 0x60;
297 break;
298 case ADECR: /* -(%r) */
299 ap->a_areg1 |= 0x70;
300 break;
301 case AINCR: /* (%r)+ */
302 ap->a_areg1 |= 0x80;
303 break;
304 case AEXP: /* expr */
305 argtype = fetcharg(ITABFETCH(opcode), i);
306 if (argtype == A_BB) {
307 ap->a_areg1 = argtype =
308 xp->e_xvalue - (dotp->e_xvalue + 1);
309 if (xp->e_xtype & XXTRN)
310 yywarning("%s: destination label is external",
311 FETCHNAME(ITABFETCH(opcode)));
312 if (!ISBYTE(argtype) && !jxxxJUMP)
313 yyerror("%s: Branch too far(%db): try -J flag",
314 FETCHNAME(ITABFETCH(opcode)),
315 argtype);
316 break;
317 }
318 if (argtype == A_BW) {
319 ap->a_areg1 = argtype = xp->e_xvalue
320 -= dotp->e_xvalue + 2;
321 if (xp->e_xtype & XXTRN)
322 yywarning("%s: destination label is external",
323 FETCHNAME(ITABFETCH(opcode)));
324 xp->e_xtype = XABS;
325 if (!ISWORD(argtype) && !jxxxJUMP)
326 yyerror("%s: Branch too far(%db): try -J flag",
327 FETCHNAME(ITABFETCH(opcode)),
328 argtype);
329 reloc_how = TYPB;
330 ap->a_areg1 = argtype>>8;
331 xp->e_xvalue = argtype;
332 break;
333 }
334 /* reduces to expr(pc) mode */
335 ap->a_areg1 |= (0xAF + mod124[ap->a_dispsize]);
336 reloc_how = type_124[ap->a_dispsize] + RELOC_PCREL;
337 break;
338
339 case ADISP: /* expr(%r) */
340 ap->a_areg1 |= 0xA0;
341 if ((xp->e_xtype&XTYPE)!=XABS || xp->e_xtype&XFORW){
342 ap->a_areg1 += mod124[ap->a_dispsize];
343 reloc_how = type_124[ap->a_dispsize];
344 break;
345 }
346 if (xp->e_xvalue==0 && !(ap->a_areg1&0x10)) {
347 ap->a_areg1 ^= 0xC0;
348 break;
349 }
350 reloc_how = TYPB;
351 if (ISBYTE(xp->e_xvalue))
352 break;
353 ap->a_areg1 += 0x20;
354 reloc_how = TYPW;
355 if (ISWORD(xp->e_xvalue))
356 break;
357 ap->a_areg1 += 0x20;
358 reloc_how = TYPL;
359 break;
360
361 case AIMM: /* $expr */
362 if (ap->a_atype&ASTAR) {
363 argtype=TYPL;
364 ap->a_areg1 |= 0x8F;
365 } else {
366 argtype = fetcharg(ITABFETCH(opcode), i);
367 if (argtype&ACCA)
368 argtype = TYPL;
369 else
370 argtype &= TYPMASK;
371 if ( ( (xp->e_xtype&XTYPE) == XABS)
372 && !(xp->e_xtype&XFORW)
373 && (argtype != TYPF)
374 && (argtype != TYPD)
375 )
376 {
377 if ((xp->e_xvalue <= 63)
378 && (xp->e_xvalue >= 0))
379 {
380 ap->a_areg1 = xp->e_xvalue;
381 break;
382 }
383 else
384 if (ISBYTE (xp->e_xvalue))
385 {
386 ap->a_areg1 = 0x88;
387 argtype = TYPB;
388 }
389 else
390 if (ISWORD (xp->e_xvalue))
391 {
392 ap->a_areg1 = 0x89;
393 argtype = TYPW;
394 }
395 else
396 {
397 ap->a_areg1 = 0x8F;
398 argtype = TYPL;
399 }
400 }
401 else
402 {
403 ap->a_areg1 = 0x8F;
404 argtype = TYPL;
405 }
406 }
407 reloc_how = argtype;
408 if (reloc_how == TYPD || reloc_how == TYPF){
409 if ( ((xp->e_xtype&XTYPE)==XABS)
410 && (!(xp->e_xtype&XFORW))
411 && (slitflt(xp))
412 ){
413 reloc_how = TYPNONE;
414 ap->a_areg1=extlitflt(xp);
415 }
416 }
417 break;
418
419 } /*end of the switch on argtype*/
420 /*
421 * use the first byte to describe the argument
422 */
423 Outb(ap->a_areg1);
424 if ((passno == 2) && liston)
425 byte_out (ap->a_areg1);
426 if (reloc_how != TYPNONE)
427 outrel(xp, reloc_how);
428 if ((passno == 2) && liston)
429 *layoutpos++ = ' ';
430 } /*end of the for to pick up all arguments*/
431 }
432