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