Add copyright
[unix-history] / usr / src / old / as.vax / ascode.c
CommitLineData
5b3c350a 1/*
f70ab843 2 * Copyright (c) 1982 Regents of the University of California
5b3c350a 3 */
f70ab843 4#ifndef lint
f6af3f2c 5static char sccsid[] = "@(#)ascode.c 4.12 %G%";
f70ab843 6#endif not lint
5b3c350a 7
f70ab843
RH
8#include <stdio.h>
9#include "as.h"
10#include "assyms.h"
5b3c350a 11
f70ab843
RH
12insout(opcode, ap, nact)
13 struct Opcode opcode;
14 struct arg *ap;
15 int nact;
cb3898cb 16{
f70ab843
RH
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
cb3898cb
BJ
24 jxxflg = nact;
25 if (nact < 0)
26 nact = -nact;
27 if (passno == 1) {
f70ab843
RH
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 }
a264a1b2
RH
37 /*
38 * Check argument compatability with instruction template
39 */
40 for (ap_walk = ap, i = 1; i <= nact; ap_walk++, i++){
5b3c350a 41 ap_type = ap_walk->a_atype;
a264a1b2 42 ap_type_mask = ap_type & AMASK;
10973e2e 43 /*
f70ab843 44 * The switch value is >> by TYPLG so that the switch
10973e2e
RH
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.
f70ab843 49 * switch on the type of fp
10973e2e 50 */
f70ab843
RH
51 switch( ((fetcharg(ip, i-1)) & ACCESSMASK) >> TYPLG){
52 case ACCI >> TYPLG:
53 case ACCR >> TYPLG:
10973e2e 54 break;
f70ab843 55 case ACCB >> TYPLG:
a264a1b2
RH
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;
f70ab843 61 case ACCA >> TYPLG:
a264a1b2
RH
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;
f70ab843
RH
71 case ACCM >> TYPLG:
72 case ACCW >> TYPLG:
a264a1b2
RH
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;
5b3c350a
RH
91 case ADECR:
92 case AINCR: if (ap_walk->a_areg1==ap_walk->a_areg2) {
a264a1b2
RH
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 */
cb3898cb 101 if (jxxflg < 0)
f70ab843
RH
102 ijxout(opcode, ap, nact);
103 else
104 putins(opcode, ap, nact);
cb3898cb
BJ
105}
106
cb3898cb 107extern int d124;
cb3898cb 108
f70ab843
RH
109putins(opcode, ap, n)
110 struct Opcode opcode;
cb3898cb 111 register struct arg *ap;
f70ab843 112 int n; /* Must be positive */
cb3898cb 113{
f70ab843
RH
114 reg struct exp *xp;
115 reg int argtype;
116 int i;
117 int reloc_how;
118 int value;
cb3898cb
BJ
119
120#ifdef DEBUG
121 fflush(stdout);
122#endif
123 if (passno == 2)
124 goto PASS2;
125
f70ab843
RH
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
451260e7 140 for (i=0; i<n; i++,ap++) { /* some args take more than 1 byte */
1e967e62
RH
141 argtype = ap->a_atype;
142 if (argtype & AINDX)
451260e7 143 dotp->e_xvalue++;
10973e2e
RH
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 */
1e967e62 149 switch (argtype&~(AINDX|ASTAR)) {
10973e2e
RH
150 case AREG:
151 case ABASE:
152 case ADECR:
153 case AINCR:
154 break;
cb3898cb 155 case AEXP:
f70ab843
RH
156 argtype = fetcharg(ITABFETCH(opcode), i);
157 if (argtype == A_BB)
cb3898cb 158 break;
f70ab843 159 if (argtype == A_BW){
451260e7 160 dotp->e_xvalue++;
cb3898cb
BJ
161 break;
162 }
163 /*
164 * Reduces to PC relative
165 */
451260e7 166 dotp->e_xvalue += ap->a_dispsize;
cb3898cb
BJ
167 break;
168
169 case ADISP:
451260e7
RH
170 xp=ap->a_xp;
171 if ((xp->e_xtype&XTYPE)!=XABS || xp->e_xtype&XFORW){
172 dotp->e_xvalue += ap->a_dispsize;
cb3898cb
BJ
173 break;
174 }
1e967e62 175 if (xp->e_xvalue==0 && !(argtype&ASTAR))
cb3898cb 176 break;
f70ab843
RH
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;
cb3898cb
BJ
184 break;
185
186 case AIMM:
f70ab843
RH
187 if (ap->a_atype&ASTAR) {
188 argtype=TYPL;
189 } else {
190 argtype = fetcharg(ITABFETCH(opcode), i);
1e967e62
RH
191 if (argtype&ACCA)
192 argtype = TYPL;
cb3898cb 193 else
1e967e62 194 argtype &= TYPMASK;
451260e7 195 xp = ap->a_xp;
f70ab843
RH
196 if (immconstant(ap->a_xp, argtype, &value))
197 break;
cb3898cb 198 }
f70ab843 199 dotp->e_xvalue += ty_nbyte[argtype];
cb3898cb
BJ
200 } /*end of the switch on the type*/
201 } /*end of looping for all arguments*/
202 return;
203
204PASS2:
f70ab843
RH
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);
cb3898cb
BJ
223
224 for (i=0; i<n; i++,ap++) {/* now for the arguments */
1e967e62 225 argtype=ap->a_atype;
451260e7 226 xp=ap->a_xp;
5b3c350a 227 reloc_how = TYPNONE;
1e967e62 228 if (argtype&AINDX) {
f70ab843 229 { Outb(0x40 | ap->a_areg2); }
1e967e62 230 argtype &= ~AINDX;
cb3898cb 231 }
1e967e62 232 if (argtype&ASTAR) {
451260e7 233 ap->a_areg1 |= 0x10;
1e967e62 234 argtype &= ~ASTAR;
cb3898cb 235 }
1e967e62 236 switch (argtype) {
cb3898cb 237 case AREG: /* %r */
451260e7 238 ap->a_areg1 |= 0x50;
cb3898cb
BJ
239 break;
240 case ABASE: /* (%r) */
451260e7 241 ap->a_areg1 |= 0x60;
cb3898cb
BJ
242 break;
243 case ADECR: /* -(%r) */
451260e7 244 ap->a_areg1 |= 0x70;
cb3898cb 245 break;
593d71c1 246 case AINCR: /* (%r)+ */
451260e7 247 ap->a_areg1 |= 0x80;
cb3898cb
BJ
248 break;
249 case AEXP: /* expr */
f70ab843
RH
250 argtype = fetcharg(ITABFETCH(opcode), i);
251 if (argtype == A_BB) {
1e967e62 252 ap->a_areg1 = argtype =
451260e7 253 xp->e_xvalue - (dotp->e_xvalue + 1);
f6af3f2c 254 if ((xp->e_xtype & XTYPE) == XUNDEF)
f70ab843 255 yywarning("%s: destination label is external",
ec43bca4 256 FETCHNAME(ITABFETCH(opcode)));
f70ab843 257 if (!ISBYTE(argtype))
7cc2ec23 258 yyerror("%s: Branch too far(%db): try -J flag",
ec43bca4 259 FETCHNAME(ITABFETCH(opcode)),
f70ab843
RH
260 argtype);
261 break;
cb3898cb 262 }
f70ab843 263 if (argtype == A_BW) {
1e967e62 264 ap->a_areg1 = argtype = xp->e_xvalue
451260e7 265 -= dotp->e_xvalue + 2;
f6af3f2c 266 if ((xp->e_xtype & XTYPE) == XUNDEF)
f70ab843 267 yywarning("%s: destination label is external",
ec43bca4 268 FETCHNAME(ITABFETCH(opcode)));
451260e7 269 xp->e_xtype = XABS;
f70ab843 270 if (!ISWORD(argtype))
7cc2ec23 271 yyerror("%s: Branch too far(%db): try -J flag",
ec43bca4 272 FETCHNAME(ITABFETCH(opcode)),
f70ab843 273 argtype);
1e967e62 274 xp->e_xvalue = argtype>>8;
5b3c350a 275 reloc_how = TYPB;
cb3898cb
BJ
276 break;
277 }
278 /* reduces to expr(pc) mode */
451260e7 279 ap->a_areg1 |= (0xAF + mod124[ap->a_dispsize]);
5b3c350a 280 reloc_how = type_124[ap->a_dispsize] + RELOC_PCREL;
cb3898cb
BJ
281 break;
282
283 case ADISP: /* expr(%r) */
451260e7
RH
284 ap->a_areg1 |= 0xA0;
285 if ((xp->e_xtype&XTYPE)!=XABS || xp->e_xtype&XFORW){
286 ap->a_areg1 += mod124[ap->a_dispsize];
5b3c350a 287 reloc_how = type_124[ap->a_dispsize];
cb3898cb
BJ
288 break;
289 }
451260e7
RH
290 if (xp->e_xvalue==0 && !(ap->a_areg1&0x10)) {
291 ap->a_areg1 ^= 0xC0;
cb3898cb
BJ
292 break;
293 }
5b3c350a 294 reloc_how = TYPB;
f70ab843
RH
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;
cb3898cb
BJ
303 break;
304
305 case AIMM: /* $expr */
f70ab843 306 if (ap->a_atype&ASTAR) {
1e967e62 307 argtype=TYPL;
f70ab843
RH
308 } else {
309 argtype = fetcharg(ITABFETCH(opcode), i);
1e967e62 310 if (argtype&ACCA)
f70ab843 311 argtype = TYPL;
cb3898cb 312 else
1e967e62 313 argtype &= TYPMASK;
f70ab843
RH
314 if (immconstant(xp, argtype, &value)){
315 reloc_how = TYPNONE;
316 ap->a_areg1 = value;
cb3898cb
BJ
317 break;
318 }
319 }
451260e7 320 ap->a_areg1 |= 0x8F;
1e967e62 321 reloc_how = argtype;
cb3898cb
BJ
322 break;
323
1e967e62 324 } /*end of the switch on argtype*/
cb3898cb
BJ
325 /*
326 * use the first byte to describe the argument
327 */
f70ab843 328 Outb(ap->a_areg1);
5b3c350a
RH
329 if (reloc_how != TYPNONE)
330 outrel(xp, reloc_how);
cb3898cb
BJ
331 } /*end of the for to pick up all arguments*/
332}
f70ab843
RH
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}