|
|
1.1 ! root 1: /* Copyright (c) 1980 Regents of the University of California */ ! 2: static char sccsid[] = "@(#)ascode.c 4.7 11/5/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, 1); ! 374: } /*end of the for to pick up all arguments*/ ! 375: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.