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