|
|
1.1 ! root 1: static char *ID_swagen="@(#) swagen.c: 1.3 5/4/84"; ! 2: #include <stdio.h> ! 3: #include "systems.h" ! 4: #include "symbols.h" ! 5: #include "instab.h" ! 6: #include "parse.h" ! 7: #include "gendefs.h" ! 8: #include "expand.h" ! 9: #include "expand2.h" ! 10: ! 11: #define MULOP 0 ! 12: #define DIVOP 1 ! 13: #define MODOP 2 ! 14: ! 15: #define SIGNED 0 ! 16: #define UNSIGNED 1 ! 17: ! 18: extern upsymins ! 19: *lookup(); ! 20: extern short ! 21: workaround, /* no software workaround flag */ ! 22: opt; /* no optimize flag */ ! 23: extern unsigned short ! 24: line; /* current line number */ ! 25: ! 26: /* ! 27: * chip fix routines: ! 28: * The following three routines (mtoregcheck, intaft1check, and intaft2check) ! 29: * are chip fix routines for the Interrupt After TSTW bug. ! 30: * ! 31: * If an interupt is responded to after a certain sequence of instructions, ! 32: * (described below) the last instruction in the sequence may not set flags ! 33: * at all. ! 34: * ! 35: * Instruction Sequences which can cause problems: ! 36: * First Instruction: ! 37: * Type 1) Instruction which does a store to a register and whose ! 38: * last source operand comes from memory. This does not ! 39: * include any discontinuities, SWAPs, RESTORE, or instructions ! 40: * without destinations (ie. BIT, TST, CMP). ! 41: * Type 2) Instruction which does a store to a register and is a ! 42: * multiple cycle ALU operation (ie. multiply, divide, modulo, ! 43: * insert field, move negate). ! 44: * Second Instruction: ! 45: * Any instruction which is executed in 3 cycles. These are: ! 46: * TSTW %reg MOVW %reg,%reg MCOMW %reg %reg ! 47: * INCW %reg DECW %reg CLRW %reg ! 48: * The fix for thisproblem is to insert a NOP before the second instruction ! 49: * in the sequence. ! 50: * ! 51: */ ! 52: ! 53: /* This routine will return a 1 so that an indicator may be set if ! 54: * the first instruction in the dangerous sequence is assembled. ! 55: */ ! 56: mtoregcheck(src, dest) ! 57: register addrmode *src, *dest; ! 58: { ! 59: #ifdef CHIPFIX ! 60: if ((dest->admode == REGMD) && (src->admode == REGDFMD || ! 61: src->admode == DSPMD || src->admode == DSPDFMD || ! 62: src->admode == EXADMD || src->admode == ABSMD || ! 63: src->admode == EXADDFMD || src->admode == ABSDFMD) ! 64: && workaround ) ! 65: return(1); ! 66: else ! 67: return(0); ! 68: #else ! 69: return(0); ! 70: #endif ! 71: } /* mtoregcheck */ ! 72: ! 73: ! 74: /* This routine will generate a NOP if the indicator is set, and ! 75: * the operand is a register operand. ! 76: */ ! 77: intaft1check(opnd, mtoreg) ! 78: register addrmode *opnd; ! 79: short mtoreg; ! 80: { ! 81: #ifdef CHIPFIX ! 82: instr *newins; ! 83: if (mtoreg != 1) ! 84: return; ! 85: if ( (opnd->admode == REGMD) && workaround ) { ! 86: newins = (*lookup("NOP",N_INSTALL,MNEMON)).itp; ! 87: generate(newins->nbits, NOACTION, newins->opcode, NULLSYM); ! 88: } ! 89: #endif ! 90: } /* intaft1check */ ! 91: ! 92: ! 93: /* This routine will generate a NOP if the indicator is set, and ! 94: * both of the operands are register operands. ! 95: */ ! 96: intaft2check(opnd1, opnd2, mtoreg) ! 97: register addrmode *opnd1, *opnd2; ! 98: short mtoreg; ! 99: { ! 100: #ifdef CHIPFIX ! 101: instr *newins; ! 102: if (mtoreg != 1) ! 103: return; ! 104: if ((opnd1->admode == REGMD) && (opnd2->admode == REGMD && ! 105: workaround)) { ! 106: newins = (*lookup("NOP",N_INSTALL,MNEMON)).itp; ! 107: generate(newins->nbits, NOACTION, newins->opcode, NULLSYM); ! 108: } ! 109: #endif ! 110: } /* intaft2check */ ! 111: ! 112: ! 113: /* ! 114: * chip fix routine: Due to pipelining on the cpu chip ! 115: * it is possible for the chip to have the "next" instruction ! 116: * almost completely executed while it is waiting for the memory ! 117: * write of the "current" instr. to be completed, even executed ! 118: * to the point where the PC is incremented past the "next" instr. ! 119: * If an interrupt occurs in a situation like this then the PC ! 120: * will be restored to one past the "next" instr, thereby, in effect, ! 121: * skipping one instr. The fix for this is to place a NOP after ! 122: * every instr. that does a memory write, except for: ! 123: * CALL, call, SAVE, save, PUSHW, pushw, PUSHAW, pushaw ! 124: * These don't need the NOP padding. ! 125: */ ! 126: pcintcheck(insptr, dest) ! 127: register instr *insptr; ! 128: register addrmode *dest; ! 129: { ! 130: #ifdef CHIPFIX ! 131: instr *newins; ! 132: ! 133: if ( (dest->admode == DSPMD || dest->admode == DSPDFMD || ! 134: dest->admode == EXADMD || dest->admode == ABSMD || ! 135: dest->admode == EXADDFMD || dest->admode == ABSDFMD || ! 136: dest->admode == REGDFMD) && (workaround) ) { ! 137: ! 138: newins = (*lookup("NOP",N_INSTALL,MNEMON)).itp; ! 139: generate(newins->nbits,NOACTION,newins->opcode,NULLSYM); ! 140: } ! 141: #endif ! 142: } /* pcintcheck */ ! 143: ! 144: #if 0 ! 145: /* The following routine is ifdef'ed out because it is not ! 146: * needed in DBO Mask 2 chips. ! 147: */ ! 148: /* ! 149: * chip fix routine: if one of the following instructions: ! 150: * MUL[BHW]3, DIV[BHW]3, MOD[BHW]3 ! 151: * occurs and, during execution, the result from the first two ! 152: * operands is computed before the third (destination) operand ! 153: * has been latched and decoded then the CPU will hang. ! 154: * This problem is fixed with the following mapping: ! 155: * ! 156: * MULX3, DIVX3, MODX3 is mapped into ! 157: * ! 158: * pushYX arg1 ! 159: * if arg2 is %sp ! 160: * subw3 &4, %sp, marg3 ! 161: * else ! 162: * movX marg2, marg3 ! 163: * "offending instr"2 {Z}spoff(%sp), marg3 ! 164: * SUBW2 &4, %sp ! 165: * TSTX {Z}arg3 ! 166: * ! 167: * where: X = B, H, or W ! 168: * Y = z (zero extend) for bytes ! 169: * b (bit extend) for halfs ! 170: * Z = user specified expand byte ! 171: * marg[2|3] indicates arg[2|3] has been ! 172: * modified if it references the stack ! 173: * pointer. (The first instruction in ! 174: * the mapping is a push which changes ! 175: * the stack pointer.) ! 176: * spoff is -4L if X = W ! 177: * is -2L if X = H ! 178: * is -1L if X = B ! 179: */ ! 180: trimulcheck(insptr, arg1, arg2, arg3) ! 181: register instr *insptr; ! 182: register addrmode *arg1, *arg2, *arg3; ! 183: { ! 184: #ifdef CHIPFIX ! 185: instr *newins, *movins, *tstins; ! 186: short usrexp1, usrexp2, usrexp3, adjarg3, otype; ! 187: long spoffset; ! 188: ! 189: /* Save user specified expand bytes (if there are any) ! 190: * so that we can push arg1 on the stack using our own ! 191: * expand byte ! 192: */ ! 193: usrexp1 = arg1->newtype; ! 194: usrexp2 = arg2->newtype; ! 195: usrexp3 = arg3->newtype; ! 196: /* check if USER specified an expand byte in an IS25 instruction */ ! 197: if (insptr->tag & IS25) { ! 198: if (( usrexp1 != NOTYPE) || (usrexp2 != NOTYPE) || (usrexp3 != NOTYPE)) ! 199: yyerror("Expand byte invalid in IS25 instruction"); ! 200: } ! 201: arg1->newtype = NOTYPE; ! 202: ! 203: /* PUSHYX arg1 ! 204: * ! 205: * Generate push instruction. Also look up the correct forms ! 206: * of the MOV and TST instructions. ! 207: */ ! 208: otype = optype(insptr->tag,1); ! 209: switch (otype) { ! 210: case 0: newins = (*lookup("pushzb",N_INSTALL,MNEMON)).itp; /* BYTE */ ! 211: pushopgen(newins, arg1); ! 212: movins = (*lookup("MOVB",N_INSTALL,MNEMON)).itp; ! 213: tstins = (*lookup("TSTB",N_INSTALL,MNEMON)).itp; ! 214: spoffset = -1L; ! 215: break; ! 216: case 1: newins = (*lookup("pushbh",N_INSTALL,MNEMON)).itp; /* HALF */ ! 217: pushopgen(newins, arg1); ! 218: movins = (*lookup("MOVH",N_INSTALL,MNEMON)).itp; ! 219: tstins = (*lookup("TSTH",N_INSTALL,MNEMON)).itp; ! 220: spoffset = -2L; ! 221: break; ! 222: case 2: newins = (*lookup("pushw",N_INSTALL,MNEMON)).itp; /* WORD */ ! 223: generate (newins->nbits, NOACTION, newins->opcode, NULLSYM); ! 224: addrgen (newins, arg1, NOTYPE, 1); ! 225: movins = (*lookup("MOVW",N_INSTALL,MNEMON)).itp; ! 226: tstins = (*lookup("TSTW",N_INSTALL,MNEMON)).itp; ! 227: spoffset = -4L; ! 228: break; ! 229: } ! 230: ! 231: /* adjust arg3 if it references the stack pointer */ ! 232: adjarg3 = 0; ! 233: if (((arg3->admode == DSPMD) || (arg3->admode == DSPDFMD) ! 234: || (arg3->admode == REGDFMD)) && (arg3->adreg == SPREG)) { ! 235: adjarg3 = 1; ! 236: arg3->adexpr.expval -= 4L; ! 237: } ! 238: if ((arg2->admode == REGMD) && (arg2->adreg == SPREG)) { ! 239: /* SUBW3 &4,%sp,marg3 */ ! 240: movins = (*lookup("SUBW3",N_INSTALL,MNEMON)).itp; ! 241: generate(movins->nbits, NOACTION, movins->opcode, NULLSYM); ! 242: generate(8, NOACTION, 0x4L, NULLSYM); ! 243: generate(8, NOACTION, (long)((CREGMD<<4)|SPREG), NULLSYM); ! 244: addrgen(movins, arg3, NOTYPE, 3); ! 245: } ! 246: else { ! 247: /* adjust arg2 if it references the stack pointer */ ! 248: if (((arg2->admode == DSPMD) || (arg2->admode == DSPDFMD) ! 249: || (arg3->admode == REGDFMD)) && (arg2->adreg == SPREG)) ! 250: arg2->adexpr.expval -= 4L; ! 251: ! 252: /* MOVX marg2,marg3 */ ! 253: generate(movins->nbits, NOACTION, movins->opcode, NULLSYM); ! 254: if (insptr->name[0] == 'u') ! 255: generate(8, NOACTION, (long)((CEXPAND<<4)|UWORD), NULLSYM); ! 256: else if (usrexp2 == NOTYPE) ! 257: arg2->newtype = usrexp1; ! 258: addrgen(movins, arg2, NOTYPE, 1); ! 259: addrgen(movins, arg3, NOTYPE, 2); ! 260: } ! 261: pcintcheck(movins, arg3); ! 262: ! 263: /* <instr>X2 {expand}spoff(%sp),marg3 */ ! 264: switch ((int)insptr->opcode) { ! 265: case 0xe4: newins = (*lookup("MODW2",N_INSTALL,MNEMON)).itp; ! 266: break; ! 267: case 0xe6: newins = (*lookup("MODH2",N_INSTALL,MNEMON)).itp; ! 268: break; ! 269: case 0xe7: newins = (*lookup("MODB2",N_INSTALL,MNEMON)).itp; ! 270: break; ! 271: case 0xe8: newins = (*lookup("MULW2",N_INSTALL,MNEMON)).itp; ! 272: break; ! 273: case 0xea: newins = (*lookup("MULH2",N_INSTALL,MNEMON)).itp; ! 274: break; ! 275: case 0xeb: newins = (*lookup("MULB2",N_INSTALL,MNEMON)).itp; ! 276: break; ! 277: case 0xec: newins = (*lookup("DIVW2",N_INSTALL,MNEMON)).itp; ! 278: break; ! 279: case 0xee: newins = (*lookup("DIVH2",N_INSTALL,MNEMON)).itp; ! 280: break; ! 281: case 0xef: newins = (*lookup("DIVB2",N_INSTALL,MNEMON)).itp; ! 282: break; ! 283: } ! 284: generate(newins->nbits, NOACTION, newins->opcode, NULLSYM); ! 285: if (insptr->name[0] == 'u') ! 286: generate(8,NOACTION,(long)((CEXPAND<<4)|UWORD),NULLSYM); ! 287: else ! 288: if (usrexp1 != NOTYPE) ! 289: generate(8,NOACTION,(long)((CEXPAND<<4)|usrexp1),NULLSYM); ! 290: ! 291: generate(8, NOACTION, (long)((CBDSPMD<<4)|SPREG), NULLSYM); ! 292: generate(8, NOACTION, spoffset, NULLSYM); ! 293: arg3->newtype = usrexp2; ! 294: addrgen(newins, arg3, NOTYPE, 2); ! 295: pcintcheck(newins, arg3); ! 296: ! 297: /* SUBW2 &4,%sp */ ! 298: newins = (*lookup("SUBW2",N_INSTALL,MNEMON)).itp; ! 299: generate(newins->nbits, NOACTION, newins->opcode, NULLSYM); ! 300: generate(8, NOACTION, 0x4L, NULLSYM); ! 301: generate(8, NOACTION, (long)((CREGMD<<4)|SPREG), NULLSYM); ! 302: ! 303: /* TSTX arg3 ! 304: * This instruction is generated in order to restore the flag settings ! 305: * of the mul, div, or mod instruction. ! 306: * ! 307: * If arg3 was adjusted because of a stack reference it must now ! 308: * be readjusted. ! 309: */ ! 310: if (adjarg3 != 0) ! 311: arg3->adexpr.expval += 4L; ! 312: generate(tstins->nbits, NOACTION, tstins->opcode, NULLSYM); ! 313: if (insptr->name[0] == 'u') ! 314: arg3->newtype = UWORD; ! 315: else if (usrexp3 != NOTYPE) ! 316: arg3->newtype = usrexp3; ! 317: else if (usrexp2 != NOTYPE) ! 318: arg3->newtype = usrexp2; ! 319: else ! 320: arg3->newtype = usrexp1; ! 321: addrgen(tstins, arg3, NOTYPE, 1); ! 322: #endif ! 323: } /* trimulcheck */ ! 324: #endif ! 325: ! 326: /* ! 327: * chip fix routine: if the psw register is used as the source of ! 328: * an instruction, the flag values may not be set yet from the ! 329: * previous instruction due to a timing problem. If the instruction ! 330: * is preceded by a NOP then the bits have time to settle and all ! 331: * is well. ! 332: * This chip fix routine will only fix IS25 instructions, BELLMAC-32B ! 333: * instructions are left untouched. ! 334: */ ! 335: pswcheck( insptr, addr) ! 336: register instr *insptr; ! 337: register addrmode *addr; ! 338: { ! 339: instr *newins; ! 340: ! 341: if ( (addr->admode == REGMD) && (addr->adreg == PSWREG) ) { ! 342: newins = (*lookup("NOP",N_INSTALL,MNEMON)).itp; ! 343: generate(newins->nbits,NOACTION,newins->opcode,NULLSYM); ! 344: return(0); /* indicate that NOP was generated */ ! 345: } else { ! 346: return(1); /* NOP not needed */ ! 347: } ! 348: } ! 349: ! 350: #if M32RSTFIX ! 351: /* ! 352: * The following routine is a workaround for the ! 353: * RESTORE chip bug. ! 354: * ! 355: * The RESTORE instruction will be mapped into the ! 356: * following sequence of instructions. ! 357: * ! 358: * RESTORE %rX ===> MOVAW -Y(%fp), %sp ! 359: * POPW %r8 ! 360: * POPW %rZ ! 361: * . ! 362: * . ! 363: * POPW %rX ! 364: * POPW %fp ! 365: * ! 366: * where: ! 367: * Y is 4 * (3 - X) (ie. 12-4X ) ! 368: * Z is Y - 1 ! 369: * ! 370: * and if %rW is %fp then the sequence is the following: ! 371: * RESTORE %fp ===> MOVAW -24(%fp),%sp ! 372: * POPW %fp ! 373: */ ! 374: restorefix(num) ! 375: register addrmode *num; ! 376: { ! 377: register int numregs, rnum; ! 378: instr *newins; ! 379: static addrmode dispfp = {NOTYPE, DSPMD,FPREG,{ABS,NULLSYM,1L}}; ! 380: ! 381: if (num->admode == REGMD) ! 382: numregs = 9 - num->adreg; ! 383: if (num->admode == IMMD) ! 384: numregs = num->adexpr.expval; ! 385: newins = (*lookup("MOVAW",N_INSTALL,MNEMON)).itp; ! 386: generate(newins->nbits,NOACTION,newins->opcode,NULLSYM); ! 387: dispfp.adexpr.expval = -24 + (4 * numregs); ! 388: addrgen(newins,&dispfp,NOTYPE,1); ! 389: generate(8,NOACTION,(long)(CREGMD<<4|SPREG),NULLSYM); ! 390: /* generate MOVAW (12-4X)(%fp),%sp */ ! 391: newins = (*lookup("POPW",N_INSTALL,MNEMON)).itp; ! 392: for (rnum=8; numregs > 0; numregs--,rnum--) { ! 393: /* generate POPW with the register being 9-numreg */ ! 394: generate(newins->nbits,NOACTION,newins->opcode,NULLSYM); ! 395: generate(8,NOACTION,(long)(CREGMD<<4|rnum),NULLSYM); ! 396: } ! 397: generate(newins->nbits,NOACTION,newins->opcode,NULLSYM); ! 398: generate(8,NOACTION,(long)(CREGMD<<4|FPREG),NULLSYM); ! 399: } ! 400: #endif /* M32RSTFIX */ ! 401: ! 402: flags(flag) ! 403: char flag; ! 404: { ! 405: char errmsg[28]; ! 406: ! 407: switch(flag) { ! 408: ! 409: default: ! 410: sprintf(errmsg,"Illegal flag (%c) - ignored",flag); ! 411: werror(errmsg); ! 412: break; ! 413: } /* switch */ ! 414: } /* flags */ ! 415: ! 416: #if MLDVFIX ! 417: /* ! 418: * Number: er 1 ! 419: * ! 420: * Name: Flag Setting for Multiply/Divide ! 421: * ! 422: * Description: There are two situations where the CPU sets the N & V ! 423: * flags but not the Z flag, even though the result is zero. ! 424: * The source operands must be of opposite signs, with ! 425: * an unsigned destination. For multiply one source must be 0. ! 426: * For divide the absolute value of the numerator must be ! 427: * non-zero and greater than the absolute value of the denominator. ! 428: * ! 429: * Resolution: generate a warning diagnostic ! 430: * ! 431: */ ! 432: ! 433: mulchk3(insptr,addr1,addr2,addr3) ! 434: instr * ! 435: insptr; ! 436: addrmode * ! 437: addr1; ! 438: addrmode * ! 439: addr2; ! 440: addrmode * ! 441: addr3; ! 442: { ! 443: if (compare(insptr->name, "MULB3") == EQUAL || ! 444: compare(insptr->name, "MULH3") == EQUAL || ! 445: compare(insptr->name, "MULW3") == EQUAL || ! 446: compare(insptr->name, "DIVB3") == EQUAL || ! 447: compare(insptr->name, "DIVH3") == EQUAL || ! 448: compare(insptr->name, "DIVW3") == EQUAL || ! 449: compare(insptr->name, "MULB2") == EQUAL || ! 450: compare(insptr->name, "MULH2") == EQUAL || ! 451: compare(insptr->name, "MULW2") == EQUAL || ! 452: compare(insptr->name, "DIVB2") == EQUAL || ! 453: compare(insptr->name, "DIVH2") == EQUAL || ! 454: compare(insptr->name, "DIVW2") == EQUAL) ! 455: { ! 456: int ! 457: type1, type2, type3; ! 458: ! 459: switch (addr1->newtype) ! 460: { ! 461: case SBYTE: ! 462: case SHALF: ! 463: case SWORD: ! 464: type1 = SIGNED; ! 465: break; ! 466: case UBYTE: ! 467: case UHALF: ! 468: case UWORD: ! 469: type1 = UNSIGNED; ! 470: break; ! 471: case NOTYPE: ! 472: switch(optype(insptr->tag,1)) ! 473: { ! 474: case 0: /* byte */ ! 475: type1 = UNSIGNED; ! 476: break; ! 477: case 1: /* half */ ! 478: type1 = SIGNED; ! 479: break; ! 480: case 2: /* word */ ! 481: type1 = SIGNED; ! 482: break; ! 483: } ! 484: } ! 485: switch (addr2->newtype) ! 486: { ! 487: case SBYTE: ! 488: case SHALF: ! 489: case SWORD: ! 490: type2 = SIGNED; ! 491: break; ! 492: case UBYTE: ! 493: case UHALF: ! 494: case UWORD: ! 495: type2 = UNSIGNED; ! 496: break; ! 497: case NOTYPE: ! 498: type2 = type1; ! 499: } ! 500: switch (addr3->newtype) ! 501: { ! 502: case SBYTE: ! 503: case SHALF: ! 504: case SWORD: ! 505: type3 = SIGNED; ! 506: break; ! 507: case UBYTE: ! 508: case UHALF: ! 509: case UWORD: ! 510: type3 = UNSIGNED; ! 511: break; ! 512: case NOTYPE: ! 513: type3 = type2; ! 514: } ! 515: if ( (addr1->admode == IMMD) && (addr1->adexpr.expval < 0 ) ) ! 516: type1 = SIGNED; ! 517: if ( (addr2->admode == IMMD) && (addr2->adexpr.expval < 0 ) ) ! 518: type2 = SIGNED; ! 519: ! 520: if ( ( ( type1 == SIGNED ) || ( type2 == SIGNED ) ) && ! 521: ( type3 == UNSIGNED ) ) ! 522: ! 523: { ! 524: werror("Mixed signs with unsignd destination can cause erroneous flags"); ! 525: } ! 526: } ! 527: } /* mulchk3 */ ! 528: ! 529: #endif ! 530: ! 531: #if ER21FIX ! 532: ! 533: er21(insptr,addr1,addr2,addr3) ! 534: instr * ! 535: insptr; ! 536: addrmode * ! 537: addr1; ! 538: addrmode * ! 539: addr2; ! 540: addrmode * ! 541: addr3; ! 542: { ! 543: if (compare(insptr->name, "MODB3") == EQUAL || ! 544: compare(insptr->name, "MODH3") == EQUAL || ! 545: compare(insptr->name, "MODW3") == EQUAL ) ! 546: { ! 547: int ! 548: type1, type2, type3; ! 549: ! 550: switch (addr1->newtype) ! 551: { ! 552: case SBYTE: ! 553: case SHALF: ! 554: case SWORD: ! 555: type1 = SIGNED; ! 556: break; ! 557: case UBYTE: ! 558: case UHALF: ! 559: case UWORD: ! 560: type1 = UNSIGNED; ! 561: break; ! 562: case NOTYPE: ! 563: switch(optype(insptr->tag,1)) ! 564: { ! 565: case 0: /* byte */ ! 566: type1 = UNSIGNED; ! 567: break; ! 568: case 1: /* half */ ! 569: type1 = SIGNED; ! 570: break; ! 571: case 2: /* word */ ! 572: type1 = SIGNED; ! 573: break; ! 574: } ! 575: } ! 576: switch (addr2->newtype) ! 577: { ! 578: case SBYTE: ! 579: case SHALF: ! 580: case SWORD: ! 581: type2 = SIGNED; ! 582: break; ! 583: case UBYTE: ! 584: case UHALF: ! 585: case UWORD: ! 586: type2 = UNSIGNED; ! 587: break; ! 588: case NOTYPE: ! 589: type2 = type1; ! 590: } ! 591: switch (addr3->newtype) ! 592: { ! 593: case SBYTE: ! 594: case SHALF: ! 595: case SWORD: ! 596: type3 = SIGNED; ! 597: break; ! 598: case UBYTE: ! 599: case UHALF: ! 600: case UWORD: ! 601: type3 = UNSIGNED; ! 602: break; ! 603: case NOTYPE: ! 604: type3 = type2; ! 605: } ! 606: if ( (addr1->admode == IMMD) && (addr1->adexpr.expval < 0 ) ) ! 607: type1 = SIGNED; ! 608: if ( (addr2->admode == IMMD) && (addr2->adexpr.expval < 0 ) ) ! 609: type2 = SIGNED; ! 610: ! 611: if ( ( type2 == SIGNED ) && ( type3 == UNSIGNED ) ) ! 612: { ! 613: werror ! 614: ("Mixed signs with unsignd destination can cause erroneous flags"); ! 615: } ! 616: } ! 617: } /* er21 */ ! 618: ! 619: #endif ! 620: ! 621: #if ER16FIX ! 622: ! 623: decrstk(i) ! 624: int ! 625: i; ! 626: { /* decrstk */ ! 627: instr * ! 628: tmpins; ! 629: ! 630: tmpins = (*lookup("SUBW2",N_INSTALL,MNEMON)).itp; ! 631: generate(8, NOACTION, tmpins->opcode, NULLSYM); ! 632: generate(8, NOACTION, i, NULLSYM); ! 633: generate(8, NOACTION, (long)((CREGMD<<4)|SPREG), NULLSYM); ! 634: } /* decrstk */ ! 635: ! 636: incrstk(i) ! 637: int ! 638: i; ! 639: { /* incrstk */ ! 640: instr * ! 641: tmpins; ! 642: ! 643: tmpins = (*lookup("ADDW2",N_INSTALL,MNEMON)).itp; ! 644: generate(8, NOACTION, tmpins->opcode, NULLSYM); ! 645: generate(8, NOACTION, i, NULLSYM); ! 646: generate(8, NOACTION, (long)((CREGMD<<4)|SPREG), NULLSYM); ! 647: } /* incrstk */ ! 648: ! 649: copyadd(addr1,addr2) ! 650: addrmode * ! 651: addr1; ! 652: addrmode * ! 653: addr2; ! 654: { /* copyadd */ ! 655: addr2->newtype = addr1->newtype; ! 656: addr2->admode = addr1->admode; ! 657: addr2->adreg = addr1->adreg; ! 658: addr2->adexpr.exptype = addr1->adexpr.exptype; ! 659: addr2->adexpr.symptr = addr1->adexpr.symptr; ! 660: addr2->adexpr.expval = addr1->adexpr.expval; ! 661: addr2->adexpr.fdexpval2 = addr1->adexpr.fdexpval2; ! 662: addr2->expspec = addr1->expspec; ! 663: } /* copyadd */ ! 664: ! 665: gen2(op,addr1,addr2) ! 666: char * ! 667: op; ! 668: addrmode * ! 669: addr1; ! 670: addrmode * ! 671: addr2; ! 672: { /* gen2 */ ! 673: instr * ! 674: tmpins; ! 675: ! 676: tmpins = (*lookup(op,N_INSTALL,MNEMON)).itp; ! 677: generate (tmpins->nbits, NOACTION, tmpins->opcode, NULLSYM); ! 678: addrgen(tmpins,addr1,NOTYPE,1); ! 679: addrgen(tmpins,addr2,NOTYPE,2); ! 680: } /* gen2 */ ! 681: ! 682: er16fix(insptr, arg1, arg2, arg3) ! 683: instr * ! 684: insptr; ! 685: addrmode * ! 686: arg1; ! 687: addrmode * ! 688: arg2; ! 689: addrmode * ! 690: arg3; ! 691: { /* er16fix */ ! 692: addrmode ! 693: c_tmp1; ! 694: addrmode * ! 695: c_arg1 = &c_tmp1; ! 696: addrmode ! 697: c_tmp2; ! 698: addrmode * ! 699: c_arg2 = &c_tmp2; ! 700: addrmode ! 701: c_tmp3; ! 702: addrmode * ! 703: c_arg3 = &c_tmp3; ! 704: instr * ! 705: tmpins; ! 706: ! 707: if ( ! ( (compare(insptr->name, "MULH3") == EQUAL ) || ! 708: (compare(insptr->name, "MULB3") == EQUAL ) || ! 709: (compare(insptr->name, "MULW3") == EQUAL ) || ! 710: (compare(insptr->name, "DIVH3") == EQUAL ) || ! 711: (compare(insptr->name, "DIVB3") == EQUAL ) || ! 712: (compare(insptr->name, "DIVW3") == EQUAL ) || ! 713: (compare(insptr->name, "MODH3") == EQUAL ) || ! 714: (compare(insptr->name, "MODB3") == EQUAL ) || ! 715: (compare(insptr->name, "MODW3") == EQUAL ) || ! 716: (compare(insptr->name, "mulw3") == EQUAL ) || ! 717: (compare(insptr->name, "umulw3") == EQUAL ) || ! 718: (compare(insptr->name, "divw3") == EQUAL ) || ! 719: (compare(insptr->name, "udivw3") == EQUAL ) || ! 720: (compare(insptr->name, "modw3") == EQUAL ) || ! 721: (compare(insptr->name, "umodw3") == EQUAL ) ) ) ! 722: return(0); ! 723: ! 724: if( ! ( (er16chk(arg1,arg3)) || (er16chk(arg2,arg3)) ) ) ! 725: return(0); ! 726: if( ! workaround ) ! 727: return(0); ! 728: ! 729: if ( compare(insptr->name, "mulw3") == EQUAL) ! 730: insptr = (*lookup("MULW3",N_INSTALL,MNEMON)).itp; ! 731: if (compare(insptr->name, "umulw3") == EQUAL ) ! 732: { ! 733: insptr = (*lookup("MULW3",N_INSTALL,MNEMON)).itp; ! 734: arg1->newtype = UWORD; ! 735: } ! 736: ! 737: if ( compare(insptr->name, "divw3") == EQUAL) ! 738: insptr = (*lookup("DIVW3",N_INSTALL,MNEMON)).itp; ! 739: if (compare(insptr->name, "udivw3") == EQUAL ) ! 740: { ! 741: insptr = (*lookup("DIVW3",N_INSTALL,MNEMON)).itp; ! 742: arg1->newtype = UWORD; ! 743: } ! 744: ! 745: if ( compare(insptr->name, "modw3") == EQUAL) ! 746: insptr = (*lookup("MODW3",N_INSTALL,MNEMON)).itp; ! 747: if (compare(insptr->name, "umodw3") == EQUAL ) ! 748: { ! 749: insptr = (*lookup("MODW3",N_INSTALL,MNEMON)).itp; ! 750: arg1->newtype = UWORD; ! 751: } ! 752: ! 753: incrstk(12); ! 754: ! 755: if (arg1->newtype == NOTYPE) ! 756: switch(optype(insptr->tag,1)) ! 757: { ! 758: case 0: /* byte */ ! 759: arg1->newtype = UBYTE; ! 760: break; ! 761: case 1: /* half */ ! 762: arg1->newtype = SHALF; ! 763: break; ! 764: case 2: /* word */ ! 765: arg1->newtype = SWORD; ! 766: break; ! 767: } ! 768: if (arg2->newtype == NOTYPE) ! 769: arg2->newtype = arg1->newtype; ! 770: if (arg3->newtype == NOTYPE) ! 771: arg3->newtype = arg2->newtype; ! 772: ! 773: copyadd(arg1,c_arg1); ! 774: copyadd(arg2,c_arg2); ! 775: copyadd(arg3,c_arg3); ! 776: ! 777: if ( ( (c_arg1->admode == DSPMD ) || ! 778: (c_arg1->admode == DSPDFMD) || ! 779: (c_arg1->admode == REGDFMD) ) && ! 780: ( c_arg1->adreg == SPREG ) ) ! 781: c_arg1->adexpr.expval -= 12; ! 782: if ( (c_arg1->admode == REGMD) && (c_arg1->adreg == SPREG) ) ! 783: { ! 784: /* SUBW3 &12,%sp,c_arg1 */ ! 785: c_arg1->admode = DSPMD; ! 786: c_arg1->adexpr.exptype = ABS; ! 787: c_arg1->adexpr.symptr = NULLSYM; ! 788: c_arg1->adexpr.expval = -12; ! 789: ! 790: tmpins = (*lookup("SUBW3",N_INSTALL,MNEMON)).itp; ! 791: generate(tmpins->nbits, NOACTION, tmpins->opcode, NULLSYM); ! 792: generate(8, NOACTION, 0x12L, NULLSYM); ! 793: generate(8, NOACTION, (long)((CREGMD<<4)|SPREG), NULLSYM); ! 794: addrgen(tmpins, c_arg1, NOTYPE, 3); ! 795: } ! 796: ! 797: if ( ( (c_arg2->admode == DSPMD ) || ! 798: (c_arg2->admode == DSPDFMD) || ! 799: (c_arg2->admode == REGDFMD) ) && ! 800: ( c_arg2->adreg == SPREG ) ) ! 801: c_arg2->adexpr.expval -= 12; ! 802: if ( (c_arg2->admode == REGMD) && (c_arg2->adreg == SPREG) ) ! 803: { ! 804: /* SUBW3 &12,%sp,c_arg2 */ ! 805: c_arg2->admode = DSPMD; ! 806: c_arg2->adexpr.exptype = ABS; ! 807: c_arg2->adexpr.symptr = NULLSYM; ! 808: c_arg2->adexpr.expval = -8; ! 809: ! 810: ! 811: tmpins = (*lookup("SUBW3",N_INSTALL,MNEMON)).itp; ! 812: generate(tmpins->nbits, NOACTION, tmpins->opcode, NULLSYM); ! 813: generate(8, NOACTION, 0x12L, NULLSYM); ! 814: generate(8, NOACTION, (long)((CREGMD<<4)|SPREG), NULLSYM); ! 815: addrgen(tmpins, c_arg2, NOTYPE, 3); ! 816: } ! 817: ! 818: c_arg3->admode = DSPMD; ! 819: c_arg3->adreg = SPREG; ! 820: c_arg3->adexpr.exptype = ABS; ! 821: c_arg3->adexpr.symptr = NULLSYM; ! 822: c_arg3->adexpr.expval = -4; ! 823: ! 824: generate(8,NOACTION,insptr->opcode,NULLSYM); ! 825: addrgen(insptr,c_arg1,NOTYPE,1); ! 826: addrgen(insptr,c_arg2,NOTYPE,2); ! 827: addrgen(insptr,c_arg3,NOTYPE,3); ! 828: ! 829: if ( ( (arg3->admode == DSPMD ) || ! 830: (arg3->admode == DSPDFMD) || ! 831: (arg3->admode == REGDFMD) ) && ! 832: ( arg3->adreg == SPREG ) ) ! 833: arg3->adexpr.expval -= 12; ! 834: ! 835: gen2("MOVW",c_arg3,arg3); ! 836: ! 837: decrstk(12); ! 838: ! 839: c_arg3->adexpr.expval = 0; ! 840: generate(8,NOACTION,insptr->opcode,NULLSYM); ! 841: addrgen(insptr,arg1,NOTYPE,1); ! 842: addrgen(insptr,arg2,NOTYPE,2); ! 843: addrgen(insptr,c_arg3,NOTYPE,3); ! 844: ! 845: return(1); ! 846: ! 847: } /* er16fix */ ! 848: ! 849: ! 850: er16chk(addr1,addr2) ! 851: addrmode ! 852: *addr1; ! 853: addrmode ! 854: *addr2; ! 855: { /* er16chk */ ! 856: switch(addr2->admode) ! 857: { /* switch(addr2->admode) */ ! 858: case REGDFMD: /* register deferred mode */ ! 859: switch(addr1->admode) ! 860: { ! 861: case DSPMD: /* displacement mode */ ! 862: if ( ( addr1->adreg == addr2->adreg ) && ! 863: ( abs(addr1->adexpr.expval - 0) >= 4 ) ) ! 864: return(NO); ! 865: break; ! 866: case REGMD: /* register mode */ ! 867: return(NO); ! 868: } ! 869: break; ! 870: case DSPMD: /* displacement mode */ ! 871: switch(addr1->admode) ! 872: { ! 873: case DSPMD: /* displacement mode */ ! 874: if ( ( addr1->adreg == addr2->adreg ) && ! 875: ( abs(addr1->adexpr.expval - addr2->adexpr.expval) >=4 ) ) ! 876: return(NO); ! 877: break; ! 878: case REGMD: /* register mode */ ! 879: return(NO); ! 880: } ! 881: break; ! 882: case DSPDFMD: /* displacement deferred mode */ ! 883: switch(addr1->admode) ! 884: { ! 885: case REGMD: /* register mode */ ! 886: return(NO); ! 887: } ! 888: break; ! 889: case EXADMD: /* external address mode */ ! 890: switch(addr1->admode) ! 891: { ! 892: case REGMD: /* register mode */ ! 893: return(NO); ! 894: } ! 895: break; ! 896: case ABSMD: /* absolute address mode */ ! 897: switch(addr1->admode) ! 898: { ! 899: case ABSMD: /* absolute address mode */ ! 900: if ( abs(addr1->adexpr.expval - addr2->adexpr.expval) >= 4 ) ! 901: return(NO); ! 902: break; ! 903: case REGMD: /* register mode */ ! 904: return(NO); ! 905: } ! 906: break; ! 907: case EXADDFMD: /* external address deferred mode (PC relative deferred) */ ! 908: switch(addr1->admode) ! 909: { ! 910: case REGMD: /* register mode */ ! 911: return(NO); ! 912: } ! 913: break; ! 914: case ABSDFMD: /* absolute address deferred mode */ ! 915: switch(addr1->admode) ! 916: { ! 917: case REGMD: /* register mode */ ! 918: return(NO); ! 919: } ! 920: break; ! 921: case IMMD: /* immediate mode */ ! 922: return(NO); ! 923: case REGMD: /* register mode */ ! 924: return(NO); ! 925: } /* switch(addr2->admode) */ ! 926: return(YES); ! 927: } /* er16chk */ ! 928: ! 929: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.