Fixing so that can compile with FLEXNAMES turned off
[unix-history] / usr / src / old / as.vax / ascode.c
CommitLineData
cb3898cb 1/* Copyright (c) 1980 Regents of the University of California */
1e967e62 2static char sccsid[] = "@(#)ascode.c 4.6 %G%";
cb3898cb 3#include <stdio.h>
cb3898cb
BJ
4#include "as.h"
5#include "assyms.h"
6
5b3c350a
RH
7/*
8 * Loader reference types (plust PCREL) to bytes and lg bytes
9 */
10/* LEN1 LEN1+PC LEN2 LEN2+PC LEN4 LEN4+PC LEN8 LEN8+PC*/
11int reflen[] = /* {LEN*+PCREL} ==> number of bytes */
12{0, 0, 1, 1, 2, 2, 4, 4, 8, 8};
13int lgreflen[] = /* {LEN*+PCREL} ==> lg number of bytes */
14{-1, -1, 0, 0, 1, 1, 2, 2, 3, 3};
15
16/*
17 * Sizes to Loader reference types and type flags
18 */
19/*0 1 2 3 4 5 6 7 8*/
20int len124[] = /* {1,2,4,8} ==> {LEN1, LEN2, LEN4, LEN8} */
21{0, LEN1, LEN2, 0, LEN4, 0, 0, 0, LEN8};
22char mod124[] = /* {1,2,4,8} ==> {bits to construct operands */
23{0, 0x00, 0x20, 0, 0x40, 0, 0, 0, 0};
24int type_124[] = /* {1,2,4,8} ==> {TYPB, TYPW, TYPL, TYPQ} */
25{0, TYPB, TYPW, 0, TYPL, 0, 0, 0, TYPQ};
26
27/*
28 * type flags to Loader reference and byte lengths
29 */
30/*TYPB TYPW TYPL TYPQ TYPF TYPD*/
31int ty_NORELOC[] = /* {TYPB..TYPD} ==> {1 if relocation not OK */
32{0, 0, 0, 1, 1, 1};
33int ty_LEN[] = /* {TYPB..TYPD} ==> {LEN1..LEN8} */
34{LEN1, LEN2, LEN4, LEN8, LEN4, LEN8};
35int ty_nbyte[] = /* {TYPB..TYPD} ==> {1,2,4,8} */
36{1, 2, 4, 8, 4, 8};
37int ty_nlg[] = /* {TYPB..TYPD} ==> lg{1,2,4,8} */
38{0, 1, 2, 3, 2, 3};
39
cb3898cb
BJ
40insout(op, ap, nact)
41 struct arg *ap;
42{
a264a1b2
RH
43 int jxxflg;
44 register struct instab *ip; /* the instruction */
45 register struct arg *ap_walk; /* actual param walk */
46 register int i;
47 register int ap_type; /* actual param type */
48 register int ap_type_mask; /* masked actual param */
cb3898cb
BJ
49 op &= 0xFF;
50 jxxflg = nact;
51 if (nact < 0)
52 nact = -nact;
53 if (passno == 1) {
a264a1b2
RH
54 ip = itab[op];
55 if (nact < ip->i_nargs)
56 yyerror("Too few arguments");
57 if (nact > ip->i_nargs) {
58 yyerror("Too many arguments");
59 nact = ip->i_nargs;
60 }
61 /*
62 * Check argument compatability with instruction template
63 */
64 for (ap_walk = ap, i = 1; i <= nact; ap_walk++, i++){
5b3c350a 65 ap_type = ap_walk->a_atype;
a264a1b2 66 ap_type_mask = ap_type & AMASK;
5b3c350a 67 switch( (fetcharg(ip, i-1)) & ACCESSMASK){ /* type of fp */
a264a1b2
RH
68 case ACCB:
69 if ( !((ap_type_mask == AEXP) || (ap_type_mask == AIMM)) ){
70 yyerror("arg %d, branch displacement must be an expression",i);
71 return;
72 }
73 break;
74 case ACCA:
75 switch(ap_type_mask){
76 case AREG: yyerror("arg %d, addressing a register",i);
77 return;
78 case AIMM: if ( !(ap_type & ASTAR) ){
79 yyerror("arg %d, addressing an immediate operand",i);
80 return;
81 }
82 }
83 break;
84 case ACCM:
85 case ACCW:
86 switch(ap_type_mask){
87 case AIMM: if (!(ap_type&ASTAR)) {
88 yyerror("arg %d, modifying a constant",i);
89 return;
90 }
91 }
92 break;
93 } /* end of the switch on fp_type */
94 if (ap_type & AINDX) {
95 if (ap_walk->a_areg2==0xF) {
96 yyerror("arg %d, PC used as index",i);
97 return;
98 }
99 switch(ap_type_mask){
100 case AREG: yyerror("arg %d, indexing the register file",i);
101 return;
102 case AIMM: yyerror("arg %d, indexing a constant",i);
103 return;
5b3c350a
RH
104 case ADECR:
105 case AINCR: if (ap_walk->a_areg1==ap_walk->a_areg2) {
a264a1b2
RH
106 yyerror("arg %d, indexing with modified register",i);
107 return;
108 }
109 break;
110 } /* end of switch on ap_type_mask */
111 } /* end of AINDX */
112 }
113 } /* both passes here */
cb3898cb
BJ
114 if (jxxflg < 0)
115 ijxout(op, ap, nact);
116 else putins(op, ap, nact);
117}
118
cb3898cb 119extern int d124;
cb3898cb
BJ
120
121putins(op, ap, n)
122 /*
123 * n had better be positive
124 */
125 register struct arg *ap;
126{
127 register struct exp *xp;
1e967e62 128 register int argtype;
5b3c350a
RH
129 int i;
130 int reloc_how;
cb3898cb
BJ
131
132#ifdef DEBUG
133 fflush(stdout);
134#endif
135 if (passno == 2)
136 goto PASS2;
137
451260e7
RH
138 dotp->e_xvalue += n+1; /* 1 for the opcode, at least 1 per arg */
139 for (i=0; i<n; i++,ap++) { /* some args take more than 1 byte */
1e967e62
RH
140 argtype = ap->a_atype;
141 if (argtype & AINDX)
451260e7 142 dotp->e_xvalue++;
1e967e62 143 switch (argtype&~(AINDX|ASTAR)) {
cb3898cb 144 case AEXP:
1e967e62
RH
145 argtype = fetcharg(itab[op], i);
146 if (argtype == ACCB+TYPB)
cb3898cb 147 break;
1e967e62 148 if (argtype==ACCB+TYPW){
451260e7 149 dotp->e_xvalue++;
cb3898cb
BJ
150 break;
151 }
152 /*
153 * Reduces to PC relative
154 */
451260e7 155 dotp->e_xvalue += ap->a_dispsize;
cb3898cb
BJ
156 break;
157
158 case ADISP:
451260e7
RH
159 xp=ap->a_xp;
160 if ((xp->e_xtype&XTYPE)!=XABS || xp->e_xtype&XFORW){
161 dotp->e_xvalue += ap->a_dispsize;
cb3898cb
BJ
162 break;
163 }
1e967e62 164 if (xp->e_xvalue==0 && !(argtype&ASTAR))
cb3898cb 165 break;
451260e7
RH
166 dotp->e_xvalue++;
167 if ((xp->e_xvalue<MINBYTE) || (xp->e_xvalue>MAXBYTE))
168 dotp->e_xvalue++;
169 if ((xp->e_xvalue<MINWORD) || (xp->e_xvalue>MAXWORD))
170 dotp->e_xvalue += 2;
cb3898cb
BJ
171 break;
172
173 case AIMM:
1e967e62 174 if (ap->a_atype&ASTAR) argtype=TYPL;
cb3898cb 175 else {
1e967e62
RH
176 argtype = fetcharg(itab[op], i);
177 if (argtype&ACCA)
178 argtype = TYPL;
cb3898cb 179 else
1e967e62 180 argtype &= TYPMASK;
451260e7
RH
181 xp = ap->a_xp;
182 if ( ((xp->e_xtype&XTYPE)==XABS)
183 && (!(xp->e_xtype&XFORW))
184 && (xp->e_xvalue>=0)
185 && (xp->e_xvalue<=63)
186 && (xp->e_yvalue == 0)
1e967e62
RH
187 && (argtype != TYPD)
188 && (argtype != TYPF)
cb3898cb
BJ
189 )
190 break;
191 }
1e967e62 192 switch (argtype) {
cb3898cb
BJ
193 case TYPD:
194 case TYPF:
451260e7
RH
195 if ( !(((xp->e_xtype&XTYPE)==XABS)
196 && (!(xp->e_xtype&XFORW))
cb3898cb
BJ
197 && (slitflt(xp)))
198 ){
199 /* it is NOT short */
1e967e62 200 dotp->e_xvalue += ((argtype==TYPF)?
cb3898cb
BJ
201 4 : 8);
202 }
203 break;
204 case TYPQ:
451260e7 205 dotp->e_xvalue += 8;break;
cb3898cb 206 case TYPL:
451260e7 207 dotp->e_xvalue += 4;break;
cb3898cb 208 case TYPW:
451260e7 209 dotp->e_xvalue += 2;break;
cb3898cb 210 case TYPB:
451260e7 211 dotp->e_xvalue += 1;break;
1e967e62 212 } /*end of the switch on argtype*/
cb3898cb
BJ
213 } /*end of the switch on the type*/
214 } /*end of looping for all arguments*/
215 return;
216
217PASS2:
218
219#ifdef UNIX
220 outb(op); /* the opcode */
221#endif UNIX
222#ifdef VMS
223 *vms_obj_ptr++ = -1; *vms_obj_ptr++ = (char)op;
451260e7 224 dotp->e_xvalue += 1;
cb3898cb
BJ
225#endif VMS
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) {
cb3898cb 232#ifdef UNIX
451260e7 233 { outb(0x40 | ap->a_areg2); }
cb3898cb
BJ
234#endif UNIX
235#ifdef VMS
236 { *vms_obj_ptr++ = -1;
451260e7
RH
237 *vms_obj_ptr++ = (0x40 | ap->a_areg2);
238 dotp->e_xvalue += 1; }
cb3898cb 239#endif VMS
1e967e62 240 argtype &= ~AINDX;
cb3898cb 241 }
1e967e62 242 if (argtype&ASTAR) {
451260e7 243 ap->a_areg1 |= 0x10;
1e967e62 244 argtype &= ~ASTAR;
cb3898cb 245 }
1e967e62 246 switch (argtype) {
cb3898cb 247 case AREG: /* %r */
451260e7 248 ap->a_areg1 |= 0x50;
cb3898cb
BJ
249 break;
250 case ABASE: /* (%r) */
451260e7 251 ap->a_areg1 |= 0x60;
cb3898cb
BJ
252 break;
253 case ADECR: /* -(%r) */
451260e7 254 ap->a_areg1 |= 0x70;
cb3898cb 255 break;
593d71c1 256 case AINCR: /* (%r)+ */
451260e7 257 ap->a_areg1 |= 0x80;
cb3898cb
BJ
258 break;
259 case AEXP: /* expr */
1e967e62
RH
260 argtype = fetcharg(itab[op], i);
261 if (argtype == ACCB+TYPB) {
262 ap->a_areg1 = argtype =
451260e7 263 xp->e_xvalue - (dotp->e_xvalue + 1);
1e967e62 264 if (argtype<MINBYTE || argtype>MAXBYTE)
cb3898cb
BJ
265 yyerror("Branch too far"); break;
266 }
1e967e62
RH
267 if (argtype == ACCB+TYPW) {
268 ap->a_areg1 = argtype = xp->e_xvalue
451260e7
RH
269 -= dotp->e_xvalue + 2;
270 xp->e_xtype = XABS;
1e967e62 271 if (argtype<MINWORD || argtype>MAXWORD)
cb3898cb 272 yyerror("Branch too far");
1e967e62 273 xp->e_xvalue = argtype>>8;
5b3c350a 274 reloc_how = TYPB;
cb3898cb
BJ
275 break;
276 }
277 /* reduces to expr(pc) mode */
451260e7 278 ap->a_areg1 |= (0xAF + mod124[ap->a_dispsize]);
5b3c350a 279 reloc_how = type_124[ap->a_dispsize] + RELOC_PCREL;
cb3898cb
BJ
280 break;
281
282 case ADISP: /* expr(%r) */
451260e7
RH
283 ap->a_areg1 |= 0xA0;
284 if ((xp->e_xtype&XTYPE)!=XABS || xp->e_xtype&XFORW){
285 ap->a_areg1 += mod124[ap->a_dispsize];
5b3c350a 286 reloc_how = type_124[ap->a_dispsize];
cb3898cb
BJ
287 break;
288 }
451260e7
RH
289 if (xp->e_xvalue==0 && !(ap->a_areg1&0x10)) {
290 ap->a_areg1 ^= 0xC0;
cb3898cb
BJ
291 break;
292 }
5b3c350a 293 reloc_how = TYPB;
451260e7
RH
294 if ((xp->e_xvalue<MINBYTE) || (xp->e_xvalue>MAXBYTE)){
295 ap->a_areg1 += 0x20;
5b3c350a 296 reloc_how = TYPW;
cb3898cb 297 }
451260e7
RH
298 if ((xp->e_xvalue<MINWORD) || (xp->e_xvalue>MAXWORD)){
299 ap->a_areg1 += 0x20;
5b3c350a 300 reloc_how = TYPL;
cb3898cb
BJ
301 }
302 break;
303
304 case AIMM: /* $expr */
451260e7 305 if (ap->a_atype&ASTAR)
1e967e62 306 argtype=TYPL;
cb3898cb 307 else {
1e967e62
RH
308 argtype = fetcharg(itab[op], i);
309 if (argtype&ACCA)
310 argtype=TYPL;
cb3898cb 311 else
1e967e62 312 argtype &= TYPMASK;
451260e7
RH
313 if ( ( (xp->e_xtype&XTYPE) == XABS)
314 && !(xp->e_xtype&XFORW)
315 && (xp->e_xvalue >= 0)
316 && (xp->e_xvalue <= 63)
317 && (xp->e_yvalue == 0)
1e967e62
RH
318 && (argtype != TYPF)
319 && (argtype != TYPD) ) {
451260e7 320 ap->a_areg1 = xp->e_xvalue;
cb3898cb
BJ
321 break;
322 }
323 }
451260e7 324 ap->a_areg1 |= 0x8F;
1e967e62 325 reloc_how = argtype;
5b3c350a 326 if (reloc_how == TYPD || reloc_how == TYPF){
451260e7
RH
327 if ( ((xp->e_xtype&XTYPE)==XABS)
328 && (!(xp->e_xtype&XFORW))
cb3898cb
BJ
329 && (slitflt(xp))
330 ){
5b3c350a 331 reloc_how = TYPNONE;
451260e7 332 ap->a_areg1=extlitflt(xp);
cb3898cb 333 }
cb3898cb
BJ
334 }
335 break;
336
1e967e62 337 } /*end of the switch on argtype*/
cb3898cb
BJ
338 /*
339 * use the first byte to describe the argument
340 */
341#ifdef UNIX
451260e7 342 outb(ap->a_areg1);
cb3898cb
BJ
343#endif UNIX
344#ifdef VMS
451260e7
RH
345 *vms_obj_ptr++ = -1; *vms_obj_ptr++ = (char)(ap->a_areg1);
346 dotp->e_xvalue += 1;
cb3898cb
BJ
347 if ((vms_obj_ptr-sobuf) > 400) {
348 write(objfil,sobuf,vms_obj_ptr-sobuf);
349 vms_obj_ptr=sobuf+1;
350 }
351#endif VMS
5b3c350a
RH
352 if (reloc_how != TYPNONE)
353 outrel(xp, reloc_how);
cb3898cb
BJ
354 } /*end of the for to pick up all arguments*/
355}