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