|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1982 Regents of the University of California ! 3: */ ! 4: #ifndef lint ! 5: static char sccsid[] = "@(#)ascode.c 4.11 6/30/83"; ! 6: #endif not lint ! 7: ! 8: #include <stdio.h> ! 9: #include "as.h" ! 10: #include "assyms.h" ! 11: ! 12: insout(opcode, ap, nact) ! 13: struct Opcode opcode; ! 14: struct arg *ap; ! 15: int nact; ! 16: { ! 17: int jxxflg; ! 18: reg struct instab *ip; /* the instruction */ ! 19: reg struct arg *ap_walk; /* actual param walk */ ! 20: reg int i; ! 21: reg int ap_type; /* actual param type */ ! 22: reg int ap_type_mask; /* masked actual param */ ! 23: ! 24: jxxflg = nact; ! 25: if (nact < 0) ! 26: nact = -nact; ! 27: if (passno == 1) { ! 28: if (!(ITABCHECK(opcode))) ! 29: panic("Botched reference into itab"); ! 30: ip = ITABFETCH(opcode); ! 31: if (nact < ip->i_nargs) ! 32: yyerror("Too few arguments"); ! 33: if (nact > ip->i_nargs) { ! 34: yyerror("Too many arguments"); ! 35: nact = ip->i_nargs; ! 36: } ! 37: /* ! 38: * Check argument compatability with instruction template ! 39: */ ! 40: for (ap_walk = ap, i = 1; i <= nact; ap_walk++, i++){ ! 41: ap_type = ap_walk->a_atype; ! 42: ap_type_mask = ap_type & AMASK; ! 43: /* ! 44: * The switch value is >> by TYPLG so that the switch ! 45: * code is dense, not implemented as a sequence ! 46: * of branches but implemented as a casel. ! 47: * In addition, cases ACCI and ACCR are added to force ! 48: * dense switch code. ! 49: * switch on the type of fp ! 50: */ ! 51: switch( ((fetcharg(ip, i-1)) & ACCESSMASK) >> TYPLG){ ! 52: case ACCI >> TYPLG: ! 53: case ACCR >> TYPLG: ! 54: break; ! 55: case ACCB >> TYPLG: ! 56: if ( !((ap_type_mask == AEXP) || (ap_type_mask == AIMM)) ){ ! 57: yyerror("arg %d, branch displacement must be an expression",i); ! 58: return; ! 59: } ! 60: break; ! 61: case ACCA >> TYPLG: ! 62: switch(ap_type_mask){ ! 63: case AREG: yyerror("arg %d, addressing a register",i); ! 64: return; ! 65: case AIMM: if ( !(ap_type & ASTAR) ){ ! 66: yyerror("arg %d, addressing an immediate operand",i); ! 67: return; ! 68: } ! 69: } ! 70: break; ! 71: case ACCM >> TYPLG: ! 72: case ACCW >> TYPLG: ! 73: switch(ap_type_mask){ ! 74: case AIMM: if (!(ap_type&ASTAR)) { ! 75: yyerror("arg %d, modifying a constant",i); ! 76: return; ! 77: } ! 78: } ! 79: break; ! 80: } /* end of the switch on fp_type */ ! 81: if (ap_type & AINDX) { ! 82: if (ap_walk->a_areg2==0xF) { ! 83: yyerror("arg %d, PC used as index",i); ! 84: return; ! 85: } ! 86: switch(ap_type_mask){ ! 87: case AREG: yyerror("arg %d, indexing the register file",i); ! 88: return; ! 89: case AIMM: yyerror("arg %d, indexing a constant",i); ! 90: return; ! 91: case ADECR: ! 92: case AINCR: if (ap_walk->a_areg1==ap_walk->a_areg2) { ! 93: yyerror("arg %d, indexing with modified register",i); ! 94: return; ! 95: } ! 96: break; ! 97: } /* end of switch on ap_type_mask */ ! 98: } /* end of AINDX */ ! 99: } ! 100: } /* both passes here */ ! 101: if (jxxflg < 0) ! 102: ijxout(opcode, ap, nact); ! 103: else ! 104: putins(opcode, ap, nact); ! 105: } ! 106: ! 107: extern int d124; ! 108: ! 109: putins(opcode, ap, n) ! 110: struct Opcode opcode; ! 111: register struct arg *ap; ! 112: int n; /* Must be positive */ ! 113: { ! 114: reg struct exp *xp; ! 115: reg int argtype; ! 116: int i; ! 117: int reloc_how; ! 118: int value; ! 119: ! 120: #ifdef DEBUG ! 121: fflush(stdout); ! 122: #endif ! 123: if (passno == 2) ! 124: goto PASS2; ! 125: ! 126: dotp->e_xvalue += n; /* at least one byte per arg */ ! 127: switch(opcode.Op_eopcode){ ! 128: case NEW: ! 129: case CORE: ! 130: dotp->e_xvalue += 1; /* 1 byte opcode */ ! 131: break; ! 132: case ESCD: ! 133: case ESCF: ! 134: dotp->e_xvalue += 2; /* 2 byte opcode */ ! 135: break; ! 136: default: ! 137: panic("Bad escape opcode"); ! 138: } ! 139: ! 140: for (i=0; i<n; i++,ap++) { /* some args take more than 1 byte */ ! 141: argtype = ap->a_atype; ! 142: if (argtype & AINDX) ! 143: dotp->e_xvalue++; ! 144: /* ! 145: * This switch has been fixed by enumerating the no action ! 146: * alternatives (those that have 1 one byte of code) ! 147: * so that a casel instruction is emitted. ! 148: */ ! 149: switch (argtype&~(AINDX|ASTAR)) { ! 150: case AREG: ! 151: case ABASE: ! 152: case ADECR: ! 153: case AINCR: ! 154: break; ! 155: case AEXP: ! 156: argtype = fetcharg(ITABFETCH(opcode), i); ! 157: if (argtype == A_BB) ! 158: break; ! 159: if (argtype == A_BW){ ! 160: dotp->e_xvalue++; ! 161: break; ! 162: } ! 163: /* ! 164: * Reduces to PC relative ! 165: */ ! 166: dotp->e_xvalue += ap->a_dispsize; ! 167: break; ! 168: ! 169: case ADISP: ! 170: xp=ap->a_xp; ! 171: if ((xp->e_xtype&XTYPE)!=XABS || xp->e_xtype&XFORW){ ! 172: dotp->e_xvalue += ap->a_dispsize; ! 173: break; ! 174: } ! 175: if (xp->e_xvalue==0 && !(argtype&ASTAR)) ! 176: break; ! 177: dotp->e_xvalue += 1; ! 178: if (ISBYTE(xp->e_xvalue)) ! 179: break; ! 180: dotp->e_xvalue += 1; ! 181: if (ISWORD(xp->e_xvalue)) ! 182: break; ! 183: dotp->e_xvalue += 2; ! 184: break; ! 185: ! 186: case AIMM: ! 187: if (ap->a_atype&ASTAR) { ! 188: argtype=TYPL; ! 189: } else { ! 190: argtype = fetcharg(ITABFETCH(opcode), i); ! 191: if (argtype&ACCA) ! 192: argtype = TYPL; ! 193: else ! 194: argtype &= TYPMASK; ! 195: xp = ap->a_xp; ! 196: if (immconstant(ap->a_xp, argtype, &value)) ! 197: break; ! 198: } ! 199: dotp->e_xvalue += ty_nbyte[argtype]; ! 200: } /*end of the switch on the type*/ ! 201: } /*end of looping for all arguments*/ ! 202: return; ! 203: ! 204: PASS2: ! 205: /* ! 206: * Output the opcode ! 207: */ ! 208: switch(opcode.Op_eopcode){ ! 209: case NEW: ! 210: nnewopcodes++; ! 211: break; ! 212: case ESCD: ! 213: case ESCF: ! 214: nGHopcodes++; ! 215: Outb(opcode.Op_eopcode); ! 216: break; ! 217: case CORE: ! 218: break; ! 219: default: ! 220: panic("Bad escape opcode"); ! 221: } ! 222: Outb(opcode.Op_popcode); ! 223: ! 224: for (i=0; i<n; i++,ap++) {/* now for the arguments */ ! 225: argtype=ap->a_atype; ! 226: xp=ap->a_xp; ! 227: reloc_how = TYPNONE; ! 228: if (argtype&AINDX) { ! 229: { Outb(0x40 | ap->a_areg2); } ! 230: argtype &= ~AINDX; ! 231: } ! 232: if (argtype&ASTAR) { ! 233: ap->a_areg1 |= 0x10; ! 234: argtype &= ~ASTAR; ! 235: } ! 236: switch (argtype) { ! 237: case AREG: /* %r */ ! 238: ap->a_areg1 |= 0x50; ! 239: break; ! 240: case ABASE: /* (%r) */ ! 241: ap->a_areg1 |= 0x60; ! 242: break; ! 243: case ADECR: /* -(%r) */ ! 244: ap->a_areg1 |= 0x70; ! 245: break; ! 246: case AINCR: /* (%r)+ */ ! 247: ap->a_areg1 |= 0x80; ! 248: break; ! 249: case AEXP: /* expr */ ! 250: argtype = fetcharg(ITABFETCH(opcode), i); ! 251: if (argtype == A_BB) { ! 252: ap->a_areg1 = argtype = ! 253: xp->e_xvalue - (dotp->e_xvalue + 1); ! 254: if (xp->e_xtype & XXTRN) ! 255: yywarning("%s: destination label is external", ! 256: FETCHNAME(ITABFETCH(opcode))); ! 257: if (!ISBYTE(argtype)) ! 258: yyerror("%s: Branch too far(%db): try -J flag", ! 259: FETCHNAME(ITABFETCH(opcode)), ! 260: argtype); ! 261: break; ! 262: } ! 263: if (argtype == A_BW) { ! 264: ap->a_areg1 = argtype = xp->e_xvalue ! 265: -= dotp->e_xvalue + 2; ! 266: if (xp->e_xtype & XXTRN) ! 267: yywarning("%s: destination label is external", ! 268: FETCHNAME(ITABFETCH(opcode))); ! 269: xp->e_xtype = XABS; ! 270: if (!ISWORD(argtype)) ! 271: yyerror("%s: Branch too far(%db): try -J flag", ! 272: FETCHNAME(ITABFETCH(opcode)), ! 273: argtype); ! 274: xp->e_xvalue = argtype>>8; ! 275: reloc_how = TYPB; ! 276: break; ! 277: } ! 278: /* reduces to expr(pc) mode */ ! 279: ap->a_areg1 |= (0xAF + mod124[ap->a_dispsize]); ! 280: reloc_how = type_124[ap->a_dispsize] + RELOC_PCREL; ! 281: break; ! 282: ! 283: case ADISP: /* expr(%r) */ ! 284: ap->a_areg1 |= 0xA0; ! 285: if ((xp->e_xtype&XTYPE)!=XABS || xp->e_xtype&XFORW){ ! 286: ap->a_areg1 += mod124[ap->a_dispsize]; ! 287: reloc_how = type_124[ap->a_dispsize]; ! 288: break; ! 289: } ! 290: if (xp->e_xvalue==0 && !(ap->a_areg1&0x10)) { ! 291: ap->a_areg1 ^= 0xC0; ! 292: break; ! 293: } ! 294: reloc_how = TYPB; ! 295: if (ISBYTE(xp->e_xvalue)) ! 296: break; ! 297: ap->a_areg1 += 0x20; ! 298: reloc_how = TYPW; ! 299: if (ISWORD(xp->e_xvalue)) ! 300: break; ! 301: ap->a_areg1 += 0x20; ! 302: reloc_how = TYPL; ! 303: break; ! 304: ! 305: case AIMM: /* $expr */ ! 306: if (ap->a_atype&ASTAR) { ! 307: argtype=TYPL; ! 308: } else { ! 309: argtype = fetcharg(ITABFETCH(opcode), i); ! 310: if (argtype&ACCA) ! 311: argtype = TYPL; ! 312: else ! 313: argtype &= TYPMASK; ! 314: if (immconstant(xp, argtype, &value)){ ! 315: reloc_how = TYPNONE; ! 316: ap->a_areg1 = value; ! 317: break; ! 318: } ! 319: } ! 320: ap->a_areg1 |= 0x8F; ! 321: reloc_how = argtype; ! 322: break; ! 323: ! 324: } /*end of the switch on argtype*/ ! 325: /* ! 326: * use the first byte to describe the argument ! 327: */ ! 328: Outb(ap->a_areg1); ! 329: if (reloc_how != TYPNONE) ! 330: outrel(xp, reloc_how); ! 331: } /*end of the for to pick up all arguments*/ ! 332: } ! 333: /* ! 334: * Is xp an immediate constant? ! 335: * argtype: how the instruction will interpret the bytes ! 336: * xp->e_number.num_tag ("numtype"): the kind of number given ! 337: * ! 338: * Use the following table: ! 339: * float: TYPF, TYPD, TYPG, TYPH ! 340: * quad: TYPQ, TYPO ! 341: * int: TYPG, TYPW, TYPL ! 342: * ! 343: * numtype ! 344: * argtype float quad int ! 345: * ! 346: * float slitflt slitflt slitflt ! 347: * quad 0 0 0 ! 348: * int 0..63 0 0..63 ! 349: * ! 350: * Where the table entry implies the predicate to return. ! 351: */ ! 352: #define IMMFLT 1 /* these flags are not used by anybody (yet) */ ! 353: #define IMMINT 2 ! 354: ! 355: int immconstant(xp, argtype, valuep) ! 356: reg struct exp *xp; ! 357: int argtype; ! 358: int *valuep; ! 359: { ! 360: reg int back = 0; ! 361: int numtype; ! 362: reg int fits; ! 363: ! 364: if ((xp->e_xtype & XTYPE) != XABS) ! 365: return(0); ! 366: if ((xp->e_xtype & XFORW) != 0) ! 367: return(0); ! 368: numtype = xp->e_number.num_tag; ! 369: ! 370: fits = 1; ! 371: if (passno == 2) switch(argtype){ ! 372: case TYPB: ! 373: switch(numtype){ ! 374: default: fits = 0; break; ! 375: case TYPB: fits = 1; break; ! 376: case TYPW: ! 377: case TYPL: ! 378: fits = ISBYTE(xp->e_xvalue) || ISUBYTE(xp->e_xvalue); ! 379: break; ! 380: } ! 381: break; ! 382: case TYPW: ! 383: switch(numtype){ ! 384: default: fits = 0; break; ! 385: case TYPB: ! 386: case TYPW: fits = 1; break; ! 387: case TYPL: ! 388: fits = ISWORD(xp->e_xvalue) || ISUWORD(xp->e_xvalue); ! 389: break; ! 390: } ! 391: break; ! 392: case TYPF: ! 393: if (numtype == TYPD){ /* same format for first 32 bits */ ! 394: fits = 1; ! 395: break; ! 396: } ! 397: /*FALLTHROUGH*/ ! 398: default: ! 399: fits = ty_nbyte[argtype] >= ty_nbyte[numtype]; ! 400: } ! 401: if (!fits){ ! 402: yywarning("Immediate constant type %s mismatches instruction type %s", ! 403: ty_string[numtype], ! 404: ty_string[argtype]); ! 405: } ! 406: ! 407: switch(argtype){ ! 408: case TYPF: ! 409: case TYPG: ! 410: case TYPD: ! 411: case TYPH: ! 412: back = slitflt(xp->e_number, argtype, valuep); ! 413: break; ! 414: case TYPO: ! 415: case TYPQ: ! 416: back = 0; ! 417: break; ! 418: case TYPB: ! 419: case TYPW: ! 420: case TYPL: ! 421: switch(numtype){ ! 422: case TYPO: ! 423: case TYPQ: ! 424: back = 0; ! 425: break; ! 426: default: ! 427: *valuep = xp->e_xvalue; ! 428: back = ISLIT(xp->e_xvalue); ! 429: break; ! 430: } ! 431: break; ! 432: } ! 433: return(back); ! 434: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.