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