1 /* Copyright (c) 1980 Regents of the University of California */ 2 static char sccsid[] = "@(#)ascode.c 4.1 08/13/80"; 3 #include <stdio.h> 4 #include <sys/types.h> 5 #include <a.out.h> 6 #include "as.h" 7 #include "assyms.h" 8 9 insout(op, ap, nact) 10 struct arg *ap; 11 { 12 int jxxflg; 13 14 op &= 0xFF; 15 jxxflg = nact; 16 if (nact < 0) 17 nact = -nact; 18 if (passno == 1) { 19 register struct arg *ap2; 20 register struct instab *ip; 21 int i,nexp; 22 ip = itab[op]; 23 nexp = ip->nargs; 24 if (nact < nexp) 25 yyerror("Too few arguments"); 26 if (nact > nexp) { 27 yyerror("Too many arguments"); 28 nact = nexp; 29 } 30 /* 31 * Check argument compatability with instruction template 32 */ 33 for (ap2 = ap+nact, i = nact; --i >= 0;) 34 argcompat(--ap2, ip->argtype[i], i+1); 35 } 36 if (jxxflg < 0) 37 ijxout(op, ap, nact); 38 else putins(op, ap, nact); 39 } 40 41 argcompat(act, exp, i) 42 struct arg *act; 43 int exp,i; 44 { 45 register at,atm; 46 47 at = act->atype; 48 atm = at & AMASK; 49 50 if ( (exp & ACCB) && (!((atm == AEXP) || (atm == AIMM))) ){ 51 yyerror("arg %d, branch displacement must be an expression",i); 52 return; 53 } 54 if ((exp & ACCA) && (atm == AREG)) { 55 yyerror("arg %d, addressing a register",i); 56 return; 57 } 58 if ((exp&ACCW) && (atm==AIMM) && !(at&ASTAR)) { 59 yyerror("arg %d, modifying a constant",i); 60 return; 61 } 62 if (at & AINDX) { 63 if (act->areg2==017) { 64 yyerror("arg %d, PC used as index",i); 65 return; 66 } 67 if (atm==AREG) { 68 yyerror("arg %d, indexing the register file",i); 69 return; 70 } 71 if (atm==AIMM) { 72 yyerror("arg %d, indexing a constant",i); 73 return; 74 } 75 if (((atm==ADECR) || (atm==AINCR)) && (act->areg1==act->areg2)) { 76 yyerror("arg %d, indexing with modified register",i); 77 return; 78 } 79 } 80 } 81 82 extern int d124; 83 int len124[] = {0,LEN1,LEN2,0,LEN4}; 84 char mod124[] = {0,0x00,0x20,0,0x40}; 85 86 putins(op, ap, n) 87 /* 88 * n had better be positive 89 */ 90 register struct arg *ap; 91 { 92 register struct exp *xp; 93 register int a; 94 int i,xtrab; 95 96 #ifdef DEBUG 97 fflush(stdout); 98 #endif 99 if (passno == 2) 100 goto PASS2; 101 102 dotp->xvalue += n+1; /* 1 for the opcode, at least 1 per arg */ 103 for (i=0; i<n; i++,ap++) {/* some args take more than 1 byte */ 104 xtrab = 0; 105 a=ap->atype; 106 if (a & AINDX) 107 dotp->xvalue++; 108 switch (a&~(AINDX|ASTAR)) { 109 case AEXP: 110 a = itab[op]->argtype[i]; 111 if (a == ACCB+TYPB) 112 break; 113 if (a==ACCB+TYPW){ 114 dotp->xvalue++; 115 break; 116 } 117 /* 118 * Reduces to PC relative 119 */ 120 xtrab++; 121 dotp->xvalue += ap->dispsize; 122 break; 123 124 case ADISP: 125 xp=ap->xp; 126 if ((xp->xtype&XTYPE)!=XABS || xp->xtype&XFORW){ 127 dotp->xvalue += ap->dispsize; 128 break; 129 } 130 if (xp->xvalue==0 && !(a&ASTAR)) 131 break; 132 dotp->xvalue++; 133 if ((xp->xvalue<MINBYTE) || (xp->xvalue>MAXBYTE)) 134 dotp->xvalue++; 135 if ((xp->xvalue<MINWORD) || (xp->xvalue>MAXWORD)) 136 dotp->xvalue += 2; 137 break; 138 139 case AIMM: 140 if (ap->atype&ASTAR) a=TYPL; 141 else { 142 a = itab[op]->argtype[i]; 143 if (a&ACCA) 144 a = TYPL; 145 else 146 a &= TYPMASK; 147 xp = ap->xp; 148 if ( ((xp->xtype&XTYPE)==XABS) 149 && (!(xp->xtype&XFORW)) 150 && (xp->xvalue>=0) 151 && (xp->xvalue<=63) 152 && (xp->yvalue == 0) 153 && (a != TYPD) 154 && (a != TYPF) 155 ) 156 break; 157 } 158 switch (a) { 159 case TYPD: 160 case TYPF: 161 if ( !(((xp->xtype&XTYPE)==XABS) 162 && (!(xp->xtype&XFORW)) 163 && (slitflt(xp))) 164 ){ 165 /* it is NOT short */ 166 dotp->xvalue += ((a==TYPF)? 167 4 : 8); 168 } 169 break; 170 case TYPQ: 171 dotp->xvalue += 8;break; 172 case TYPL: 173 dotp->xvalue += 4;break; 174 case TYPW: 175 dotp->xvalue += 2;break; 176 case TYPB: 177 dotp->xvalue += 1;break; 178 } /*end of the switch on a*/ 179 } /*end of the switch on the type*/ 180 } /*end of looping for all arguments*/ 181 return; 182 183 PASS2: 184 185 #ifdef UNIX 186 outb(op); /* the opcode */ 187 #endif UNIX 188 #ifdef VMS 189 *vms_obj_ptr++ = -1; *vms_obj_ptr++ = (char)op; 190 dotp->xvalue += 1; 191 #endif VMS 192 193 for (i=0; i<n; i++,ap++) {/* now for the arguments */ 194 a=ap->atype; 195 xp=ap->xp; 196 xtrab=0; 197 if (a&AINDX) { 198 #ifdef UNIX 199 { outb(0x40 | ap->areg2); } 200 #endif UNIX 201 #ifdef VMS 202 { *vms_obj_ptr++ = -1; 203 *vms_obj_ptr++ = (0x40 | ap->areg2); 204 dotp->xvalue += 1; } 205 #endif VMS 206 a &= ~AINDX; 207 } 208 if (a&ASTAR) { 209 ap->areg1 |= 0x10; 210 a &= ~ASTAR; 211 } 212 switch (a) { 213 case AREG: /* %r */ 214 ap->areg1 |= 0x50; 215 break; 216 case ABASE: /* (%r) */ 217 ap->areg1 |= 0x60; 218 break; 219 case ADECR: /* -(%r) */ 220 ap->areg1 |= 0x70; 221 break; 222 case AINCR: /* (%r) */ 223 ap->areg1 |= 0x80; 224 break; 225 case AEXP: /* expr */ 226 a = itab[op]->argtype[i]; 227 if (a == ACCB+TYPB) { 228 ap->areg1 = a = 229 xp->xvalue - (dotp->xvalue + 1); 230 if (a<MINBYTE || a>MAXBYTE) 231 yyerror("Branch too far"); break; 232 } 233 if (a == ACCB+TYPW) { 234 ap->areg1 = a = xp->xvalue 235 -= dotp->xvalue + 2; 236 xp->xtype = XABS; 237 if (a<MINWORD || a>MAXWORD) 238 yyerror("Branch too far"); 239 xp->xvalue = a>>8; 240 xtrab = LEN1; 241 break; 242 } 243 /* reduces to expr(pc) mode */ 244 ap->areg1 |= (0xAF + mod124[ap->dispsize]); 245 xtrab = len124[ap->dispsize]+PCREL; 246 break; 247 248 case ADISP: /* expr(%r) */ 249 ap->areg1 |= 0xA0; 250 if ((xp->xtype&XTYPE)!=XABS || xp->xtype&XFORW){ 251 ap->areg1 += mod124[ap->dispsize]; 252 xtrab=len124[ap->dispsize]; 253 break; 254 } 255 if (xp->xvalue==0 && !(ap->areg1&0x10)) { 256 ap->areg1 ^= 0xC0; 257 break; 258 } 259 xtrab=LEN1; 260 if ((xp->xvalue<MINBYTE) || (xp->xvalue>MAXBYTE)){ 261 ap->areg1 += 0x20; 262 xtrab=LEN2; 263 } 264 if ((xp->xvalue<MINWORD) || (xp->xvalue>MAXWORD)){ 265 ap->areg1 += 0x20; 266 xtrab=LEN4; 267 } 268 break; 269 270 case AIMM: /* $expr */ 271 if (ap->atype&ASTAR) 272 a=TYPL; 273 else { 274 a = itab[op]->argtype[i]; 275 if (a&ACCA) 276 a=TYPL; 277 else 278 a &= TYPMASK; 279 if ( ( (xp->xtype&XTYPE) == XABS) 280 && !(xp->xtype&XFORW) 281 && (xp->xvalue >= 0) 282 && (xp->xvalue <= 63) 283 && (xp->yvalue == 0) 284 && (a != TYPF) 285 && (a != TYPD) ) { 286 ap->areg1 = xp->xvalue; 287 break; 288 } 289 } 290 ap->areg1 |= 0x8F; 291 switch (a) { 292 case TYPD: 293 case TYPF: 294 if ( ((xp->xtype&XTYPE)==XABS) 295 && (!(xp->xtype&XFORW)) 296 && (slitflt(xp)) 297 ){ 298 ap->areg1=extlitflt(xp); 299 } else { 300 xtrab = (a==TYPF) ? LEN4: LEN8; 301 } 302 break; 303 case TYPQ: xtrab = LEN8; break; 304 case TYPL: xtrab = LEN4; break; 305 case TYPW: xtrab = LEN2; break; 306 case TYPB: xtrab = LEN1; break; 307 } 308 break; 309 310 } /*end of the switch on a*/ 311 /* 312 * use the first byte to describe the argument 313 */ 314 #ifdef UNIX 315 outb(ap->areg1); 316 #endif UNIX 317 #ifdef VMS 318 *vms_obj_ptr++ = -1; *vms_obj_ptr++ = (char)(ap->areg1); 319 dotp->xvalue += 1; 320 if ((vms_obj_ptr-sobuf) > 400) { 321 write(objfil,sobuf,vms_obj_ptr-sobuf); 322 vms_obj_ptr=sobuf+1; 323 } 324 #endif VMS 325 if (xtrab) 326 /* 327 * Floating point numbers are written to a.out 328 * by outrel; they require that the least significant 329 * 4 bytes of an 8 byte double precision number 330 * immediately follow the field xvalue, which 331 * they do. 332 */ 333 outrel(&xp->xvalue, xtrab, xp->xtype, xp->xname); 334 } /*end of the for to pick up all arguments*/ 335 } 336