1 /* Copyright (c) 1980 Regents of the University of California */ 2 static char sccsid[] = "@(#)ascode.c 4.6 09/08/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 switch( (fetcharg(ip, i-1)) & ACCESSMASK){ /* type of fp */ 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; 104 case ADECR: 105 case AINCR: if (ap_walk->a_areg1==ap_walk->a_areg2) { 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 */ 114 if (jxxflg < 0) 115 ijxout(op, ap, nact); 116 else putins(op, ap, nact); 117 } 118 119 extern int d124; 120 121 putins(op, ap, n) 122 /* 123 * n had better be positive 124 */ 125 register struct arg *ap; 126 { 127 register struct exp *xp; 128 register int argtype; 129 int i; 130 int reloc_how; 131 132 #ifdef DEBUG 133 fflush(stdout); 134 #endif 135 if (passno == 2) 136 goto PASS2; 137 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 */ 140 argtype = ap->a_atype; 141 if (argtype & AINDX) 142 dotp->e_xvalue++; 143 switch (argtype&~(AINDX|ASTAR)) { 144 case AEXP: 145 argtype = fetcharg(itab[op], i); 146 if (argtype == ACCB+TYPB) 147 break; 148 if (argtype==ACCB+TYPW){ 149 dotp->e_xvalue++; 150 break; 151 } 152 /* 153 * Reduces to PC relative 154 */ 155 dotp->e_xvalue += ap->a_dispsize; 156 break; 157 158 case ADISP: 159 xp=ap->a_xp; 160 if ((xp->e_xtype&XTYPE)!=XABS || xp->e_xtype&XFORW){ 161 dotp->e_xvalue += ap->a_dispsize; 162 break; 163 } 164 if (xp->e_xvalue==0 && !(argtype&ASTAR)) 165 break; 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; 171 break; 172 173 case AIMM: 174 if (ap->a_atype&ASTAR) argtype=TYPL; 175 else { 176 argtype = fetcharg(itab[op], i); 177 if (argtype&ACCA) 178 argtype = TYPL; 179 else 180 argtype &= TYPMASK; 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) 187 && (argtype != TYPD) 188 && (argtype != TYPF) 189 ) 190 break; 191 } 192 switch (argtype) { 193 case TYPD: 194 case TYPF: 195 if ( !(((xp->e_xtype&XTYPE)==XABS) 196 && (!(xp->e_xtype&XFORW)) 197 && (slitflt(xp))) 198 ){ 199 /* it is NOT short */ 200 dotp->e_xvalue += ((argtype==TYPF)? 201 4 : 8); 202 } 203 break; 204 case TYPQ: 205 dotp->e_xvalue += 8;break; 206 case TYPL: 207 dotp->e_xvalue += 4;break; 208 case TYPW: 209 dotp->e_xvalue += 2;break; 210 case TYPB: 211 dotp->e_xvalue += 1;break; 212 } /*end of the switch on argtype*/ 213 } /*end of the switch on the type*/ 214 } /*end of looping for all arguments*/ 215 return; 216 217 PASS2: 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; 224 dotp->e_xvalue += 1; 225 #endif VMS 226 227 for (i=0; i<n; i++,ap++) {/* now for the arguments */ 228 argtype=ap->a_atype; 229 xp=ap->a_xp; 230 reloc_how = TYPNONE; 231 if (argtype&AINDX) { 232 #ifdef UNIX 233 { outb(0x40 | ap->a_areg2); } 234 #endif UNIX 235 #ifdef VMS 236 { *vms_obj_ptr++ = -1; 237 *vms_obj_ptr++ = (0x40 | ap->a_areg2); 238 dotp->e_xvalue += 1; } 239 #endif VMS 240 argtype &= ~AINDX; 241 } 242 if (argtype&ASTAR) { 243 ap->a_areg1 |= 0x10; 244 argtype &= ~ASTAR; 245 } 246 switch (argtype) { 247 case AREG: /* %r */ 248 ap->a_areg1 |= 0x50; 249 break; 250 case ABASE: /* (%r) */ 251 ap->a_areg1 |= 0x60; 252 break; 253 case ADECR: /* -(%r) */ 254 ap->a_areg1 |= 0x70; 255 break; 256 case AINCR: /* (%r)+ */ 257 ap->a_areg1 |= 0x80; 258 break; 259 case AEXP: /* expr */ 260 argtype = fetcharg(itab[op], i); 261 if (argtype == ACCB+TYPB) { 262 ap->a_areg1 = argtype = 263 xp->e_xvalue - (dotp->e_xvalue + 1); 264 if (argtype<MINBYTE || argtype>MAXBYTE) 265 yyerror("Branch too far"); break; 266 } 267 if (argtype == ACCB+TYPW) { 268 ap->a_areg1 = argtype = xp->e_xvalue 269 -= dotp->e_xvalue + 2; 270 xp->e_xtype = XABS; 271 if (argtype<MINWORD || argtype>MAXWORD) 272 yyerror("Branch too far"); 273 xp->e_xvalue = argtype>>8; 274 reloc_how = TYPB; 275 break; 276 } 277 /* reduces to expr(pc) mode */ 278 ap->a_areg1 |= (0xAF + mod124[ap->a_dispsize]); 279 reloc_how = type_124[ap->a_dispsize] + RELOC_PCREL; 280 break; 281 282 case ADISP: /* expr(%r) */ 283 ap->a_areg1 |= 0xA0; 284 if ((xp->e_xtype&XTYPE)!=XABS || xp->e_xtype&XFORW){ 285 ap->a_areg1 += mod124[ap->a_dispsize]; 286 reloc_how = type_124[ap->a_dispsize]; 287 break; 288 } 289 if (xp->e_xvalue==0 && !(ap->a_areg1&0x10)) { 290 ap->a_areg1 ^= 0xC0; 291 break; 292 } 293 reloc_how = TYPB; 294 if ((xp->e_xvalue<MINBYTE) || (xp->e_xvalue>MAXBYTE)){ 295 ap->a_areg1 += 0x20; 296 reloc_how = TYPW; 297 } 298 if ((xp->e_xvalue<MINWORD) || (xp->e_xvalue>MAXWORD)){ 299 ap->a_areg1 += 0x20; 300 reloc_how = TYPL; 301 } 302 break; 303 304 case AIMM: /* $expr */ 305 if (ap->a_atype&ASTAR) 306 argtype=TYPL; 307 else { 308 argtype = fetcharg(itab[op], i); 309 if (argtype&ACCA) 310 argtype=TYPL; 311 else 312 argtype &= TYPMASK; 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) 318 && (argtype != TYPF) 319 && (argtype != TYPD) ) { 320 ap->a_areg1 = xp->e_xvalue; 321 break; 322 } 323 } 324 ap->a_areg1 |= 0x8F; 325 reloc_how = argtype; 326 if (reloc_how == TYPD || reloc_how == TYPF){ 327 if ( ((xp->e_xtype&XTYPE)==XABS) 328 && (!(xp->e_xtype&XFORW)) 329 && (slitflt(xp)) 330 ){ 331 reloc_how = TYPNONE; 332 ap->a_areg1=extlitflt(xp); 333 } 334 } 335 break; 336 337 } /*end of the switch on argtype*/ 338 /* 339 * use the first byte to describe the argument 340 */ 341 #ifdef UNIX 342 outb(ap->a_areg1); 343 #endif UNIX 344 #ifdef VMS 345 *vms_obj_ptr++ = -1; *vms_obj_ptr++ = (char)(ap->a_areg1); 346 dotp->e_xvalue += 1; 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 352 if (reloc_how != TYPNONE) 353 outrel(xp, reloc_how); 354 } /*end of the for to pick up all arguments*/ 355 } 356