X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Fmcs51%2Fgen.c;h=649c643e5ea6f50e6b464777b546b4369137ce52;hb=67da89445478477cbda97171c16f8cc2666ce240;hp=1034905e7b6ae8fd436525a3adce4d8a3a1acfd8;hpb=f8b4af7c3b2882b086b0b4ab2454191a46647756;p=fw%2Fsdcc diff --git a/src/mcs51/gen.c b/src/mcs51/gen.c index 1034905e..649c643e 100644 --- a/src/mcs51/gen.c +++ b/src/mcs51/gen.c @@ -73,6 +73,7 @@ static struct short debugLine; short nRegsSaved; set *sendSet; + iCode *current_iCode; } _G; @@ -139,6 +140,8 @@ emitcode (char *inst, const char *fmt,...) (lineHead = newLineNode (lb))); lineCurr->isInline = _G.inLine; lineCurr->isDebug = _G.debugLine; + lineCurr->ic = _G.current_iCode; + lineCurr->isComment = (*lbp==';'); va_end (ap); } @@ -279,6 +282,74 @@ pointerCode (sym_link * etype) } + +/*-----------------------------------------------------------------*/ +/* leftRightUseAcc - returns size of accumulator use by operands */ +/*-----------------------------------------------------------------*/ +static int +leftRightUseAcc(iCode *ic) +{ + operand *op; + int size; + int accuseSize = 0; + int accuse = 0; + + if (!ic) + { + werror (E_INTERNAL_ERROR, __FILE__, __LINE__, + "null iCode pointer"); + return 0; + } + + if (ic->op == IFX) + { + op = IC_COND (ic); + if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse) + { + accuse = 1; + size = getSize (OP_SYMBOL (op)->type); + if (size>accuseSize) + accuseSize = size; + } + } + else if (ic->op == JUMPTABLE) + { + op = IC_JTCOND (ic); + if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse) + { + accuse = 1; + size = getSize (OP_SYMBOL (op)->type); + if (size>accuseSize) + accuseSize = size; + } + } + else + { + op = IC_LEFT (ic); + if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse) + { + accuse = 1; + size = getSize (OP_SYMBOL (op)->type); + if (size>accuseSize) + accuseSize = size; + } + op = IC_RIGHT (ic); + if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse) + { + accuse = 1; + size = getSize (OP_SYMBOL (op)->type); + if (size>accuseSize) + accuseSize = size; + } + } + + if (accuseSize) + return accuseSize; + else + return accuse; +} + + /*-----------------------------------------------------------------*/ /* aopForSym - for a true symbol */ /*-----------------------------------------------------------------*/ @@ -313,7 +384,7 @@ aopForSym (iCode * ic, symbol * sym, bool result) if (sym->onStack) { - if (_G.accInUse) + if (_G.accInUse || leftRightUseAcc (ic)) emitcode ("push", "acc"); emitcode ("mov", "a,_bp"); @@ -324,7 +395,7 @@ aopForSym (iCode * ic, symbol * sym, bool result) emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name); - if (_G.accInUse) + if (_G.accInUse || leftRightUseAcc (ic)) emitcode ("pop", "acc"); } else @@ -349,6 +420,9 @@ aopForSym (iCode * ic, symbol * sym, bool result) /* if it is in direct space */ if (IN_DIRSPACE (space)) { + //printf("aopForSym, using AOP_DIR for %s (%x)\n", sym->name, sym); + //printTypeChainRaw(sym->type, NULL); + //printf("space = %s\n", space ? space->sname : "NULL"); sym->aop = aop = newAsmop (AOP_DIR); aop->aopu.aop_dir = sym->rname; aop->size = getSize (sym->type); @@ -634,13 +708,21 @@ aopOp (operand * op, iCode * ic, bool result) return; } - /* else spill location */ - if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) { - /* force a new aop if sizes differ */ - sym->usl.spillLoc->aop = NULL; - } - sym->aop = op->aop = aop = - aopForSym (ic, sym->usl.spillLoc, result); + if (sym->usl.spillLoc) + { + if (getSize(sym->type) != getSize(sym->usl.spillLoc->type)) + { + /* force a new aop if sizes differ */ + sym->usl.spillLoc->aop = NULL; + } + sym->aop = op->aop = aop = + aopForSym (ic, sym->usl.spillLoc, result); + aop->size = getSize (sym->type); + return; + } + + /* else must be a dummy iTemp */ + sym->aop = op->aop = aop = newAsmop (AOP_DUMMY); aop->size = getSize (sym->type); return; } @@ -704,7 +786,7 @@ freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop) case AOP_STK: { int sz = aop->size; - int stk = aop->aopu.aop_stk + aop->size; + int stk = aop->aopu.aop_stk + aop->size - 1; bitVectUnSetBit (ic->rUsed, R0_IDX); bitVectUnSetBit (ic->rUsed, R1_IDX); @@ -731,17 +813,17 @@ freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop) } op->aop = aop; freeAsmop (op, NULL, ic, TRUE); - if (_G.r0Pushed) - { - emitcode ("pop", "ar0"); - _G.r0Pushed--; - } - if (_G.r1Pushed) { emitcode ("pop", "ar1"); _G.r1Pushed--; } + + if (_G.r0Pushed) + { + emitcode ("pop", "ar0"); + _G.r0Pushed--; + } } } @@ -797,6 +879,8 @@ aopGetUsesAcc (asmop *aop, int offset) if (strcmp (aop->aopu.aop_str[offset], "a") == 0) return TRUE; return FALSE; + case AOP_DUMMY: + return FALSE; default: /* Error case --- will have been caught already */ wassert(0); @@ -804,7 +888,6 @@ aopGetUsesAcc (asmop *aop, int offset) } } - /*-----------------------------------------------------------------*/ /* aopGet - for fetching value of the aop */ /*-----------------------------------------------------------------*/ @@ -823,7 +906,9 @@ aopGet (asmop * aop, int offset, bool bit16, bool dname) /* depending on type */ switch (aop->type) { - + case AOP_DUMMY: + return zero; + case AOP_R0: case AOP_R1: /* if we need to increment it */ @@ -962,6 +1047,10 @@ aopPut (asmop * aop, const char *s, int offset, bool bvolatile) /* depending on where it is ofcourse */ switch (aop->type) { + case AOP_DUMMY: + MOVA (s); /* read s in case it was volatile */ + break; + case AOP_DIR: if (offset) sprintf (d, "(%s + %d)", @@ -1205,46 +1294,6 @@ reAdjustPreg (asmop * aop) (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \ x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) ))) -/*-----------------------------------------------------------------*/ -/* genNotFloat - generates not for float operations */ -/*-----------------------------------------------------------------*/ -static void -genNotFloat (operand * op, operand * res) -{ - int size, offset; - char *l; - symbol *tlbl; - - D(emitcode ("; genNotFloat","")); - - /* we will put 127 in the first byte of - the result */ - aopPut (AOP (res), "#127", 0, isOperandVolatile (op, FALSE)); - size = AOP_SIZE (op) - 1; - offset = 1; - - l = aopGet (op->aop, offset++, FALSE, FALSE); - MOVA (l); - - while (size--) - { - emitcode ("orl", "a,%s", - aopGet (op->aop, - offset++, FALSE, FALSE)); - } - - tlbl = newiTempLabel (NULL); - aopPut (res->aop, one, 1, isOperandVolatile (op, FALSE)); - emitcode ("jz", "%05d$", (tlbl->key + 100)); - aopPut (res->aop, zero, 1, isOperandVolatile (op, FALSE)); - emitcode ("", "%05d$:", (tlbl->key + 100)); - - size = res->aop->size - 2; - offset = 2; - /* put zeros in the rest */ - while (size--) - aopPut (res->aop, zero, offset++, isOperandVolatile (op, FALSE)); -} /*-----------------------------------------------------------------*/ /* opIsGptr: returns non-zero if the passed operand is */ @@ -1343,7 +1392,6 @@ static void genNot (iCode * ic) { symbol *tlbl; - sym_link *optype = operandType (IC_LEFT (ic)); D(emitcode ("; genNot","")); @@ -1360,13 +1408,6 @@ genNot (iCode * ic) goto release; } - /* if type float then do float */ - if (IS_FLOAT (optype)) - { - genNotFloat (IC_LEFT (ic), IC_RESULT (ic)); - goto release; - } - toBoolean (IC_LEFT (ic)); tlbl = newiTempLabel (NULL); @@ -1398,20 +1439,35 @@ genCpl (iCode * ic) aopOp (IC_RESULT (ic), ic, TRUE); /* special case if in bit space */ - if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) { - if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) { - emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir); - emitcode ("cpl", "c"); - emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir); + if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) + { + if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) + { + emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir); + emitcode ("cpl", "c"); + emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir); + goto release; + } + + tlbl=newiTempLabel(NULL); + if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC || + AOP_TYPE (IC_LEFT (ic)) == AOP_REG || + IS_AOP_PREG (IC_LEFT (ic))) + { + emitcode ("cjne", "%s,#0x01,%05d$", + aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE), + tlbl->key + 100); + } + else + { + char *l = aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE); + MOVA (l); + emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100); + } + emitcode ("", "%05d$:", tlbl->key + 100); + outBitC (IC_RESULT(ic)); goto release; } - tlbl=newiTempLabel(NULL); - emitcode ("cjne", "%s,#0x01,%05d$", - aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE), tlbl->key+100); - emitcode ("", "%05d$:", tlbl->key+100); - outBitC (IC_RESULT(ic)); - goto release; - } size = AOP_SIZE (IC_RESULT (ic)); while (size--) @@ -2019,16 +2075,16 @@ genCall (iCode * ic) (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) && !IFFUNC_ISISR (dtype)) { - swapBanks = TRUE; - } - + swapBanks = TRUE; + } + /* if caller saves & we have not saved then */ if (!ic->regsSaved) saveRegisters (ic); if (swapBanks) { - emitcode ("mov", "psw,#0x%02x", + emitcode ("mov", "psw,#0x%02x", ((FUNC_REGBANK(dtype)) << 3) & 0xff); } @@ -2039,14 +2095,14 @@ genCall (iCode * ic) if (swapBanks) { - emitcode ("mov", "psw,#0x%02x", + emitcode ("mov", "psw,#0x%02x", ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff); } /* if we need assign a result value */ if ((IS_ITEMP (IC_RESULT (ic)) && (OP_SYMBOL (IC_RESULT (ic))->nRegs || - OP_SYMBOL (IC_RESULT (ic))->accuse || + OP_SYMBOL (IC_RESULT (ic))->accuse || OP_SYMBOL (IC_RESULT (ic))->spildir)) || IS_TRUE_SYMOP (IC_RESULT (ic))) { @@ -2268,10 +2324,6 @@ genFunction (iCode * ic) return; } - /* if critical function then turn interrupts off */ - if (IFFUNC_ISCRITICAL (ftype)) - emitcode ("clr", "ea"); - /* here we need to generate the equates for the register bank if required */ if (FUNC_REGBANK (ftype) != rbank) @@ -2548,7 +2600,17 @@ genFunction (iCode * ic) emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff)); emitcode ("mov", "_spx,a"); } - + + /* if critical function then turn interrupts off */ + if (IFFUNC_ISCRITICAL (ftype)) + { + symbol *tlbl = newiTempLabel (NULL); + emitcode ("setb", "c"); + emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */ + emitcode ("clr", "c"); + emitcode ("", "%05d$:", (tlbl->key + 100)); + emitcode ("push", "psw"); /* save old ea via c in psw */ + } } /*-----------------------------------------------------------------*/ @@ -2564,6 +2626,12 @@ genEndFunction (iCode * ic) emitcode(";", "naked function: no epilogue."); return; } + + if (IFFUNC_ISCRITICAL (sym->type)) + { + emitcode ("pop", "psw"); /* restore ea via c in psw */ + emitcode ("mov", "ea,c"); + } if (IFFUNC_ISREENT (sym->type) || options.stackAuto) { @@ -2688,9 +2756,6 @@ genEndFunction (iCode * ic) if (!inExcludeList ("acc")) emitcode ("pop", "acc"); - if (IFFUNC_ISCRITICAL (sym->type)) - emitcode ("setb", "ea"); - /* if debug then send end of function */ if (options.debug && currFunc) { @@ -2709,9 +2774,6 @@ genEndFunction (iCode * ic) } else { - if (IFFUNC_ISCRITICAL (sym->type)) - emitcode ("setb", "ea"); - if (IFFUNC_CALLEESAVES(sym->type)) { int i; @@ -3130,8 +3192,10 @@ static void genPlus (iCode * ic) { int size, offset = 0; - char *add; + int skip_bytes = 0; + char *add = "add"; asmop *leftOp, *rightOp; + operand * op; /* special cases :- */ @@ -3193,33 +3257,92 @@ genPlus (iCode * ic) goto release; size = getDataSize (IC_RESULT (ic)); - leftOp = AOP(IC_LEFT(ic)); rightOp = AOP(IC_RIGHT(ic)); - add = "add"; + op=IC_LEFT(ic); + + /* if this is an add for an array access + at a 256 byte boundary */ + if ( 2 == size + && AOP_TYPE (op) == AOP_IMMD + && IS_SYMOP (op) + && IS_SPEC (OP_SYM_ETYPE (op)) + && SPEC_ABSA (OP_SYM_ETYPE (op)) + && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0 + ) + { + D(emitcode ("; genPlus aligned array","")); + aopPut (AOP (IC_RESULT (ic)), + aopGet (rightOp, 0, FALSE, FALSE), + 0, + isOperandVolatile (IC_RESULT (ic), FALSE)); - while (size--) - { - if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset)) + if( 1 == getDataSize (IC_RIGHT (ic)) ) { - emitcode("mov", "b,a"); - MOVA (aopGet (leftOp, offset, FALSE, TRUE)); - emitcode("xch", "a,b"); - MOVA (aopGet (rightOp, offset, FALSE, TRUE)); - emitcode (add, "a,b"); + aopPut (AOP (IC_RESULT (ic)), + aopGet (leftOp, 1, FALSE, FALSE), + 1, + isOperandVolatile (IC_RESULT (ic), FALSE)); } - else if (aopGetUsesAcc (leftOp, offset)) - { - MOVA (aopGet (leftOp, offset, FALSE, TRUE)); - emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE)); + else + { + MOVA (aopGet (AOP (IC_LEFT (ic)), 1, FALSE, FALSE)); + emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE)); + aopPut (AOP (IC_RESULT (ic)), "a", 1, isOperandVolatile (IC_RESULT (ic), FALSE)); } + goto release; + } + + /* if the lower bytes of a literal are zero skip the addition */ + if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT ) + { + while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) && + (skip_bytes+1 < size)) + { + skip_bytes++; + } + if (skip_bytes) + D(emitcode ("; genPlus shortcut","")); + } + + while (size--) + { + if( offset >= skip_bytes ) + { + if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset)) + { + emitcode("mov", "b,a"); + MOVA (aopGet (leftOp, offset, FALSE, TRUE)); + emitcode("xch", "a,b"); + MOVA (aopGet (rightOp, offset, FALSE, TRUE)); + emitcode (add, "a,b"); + } + else if (aopGetUsesAcc (leftOp, offset)) + { + MOVA (aopGet (leftOp, offset, FALSE, TRUE)); + emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE)); + } + else + { + MOVA (aopGet (rightOp, offset, FALSE, TRUE)); + emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE)); + } + aopPut (AOP (IC_RESULT (ic)), "a", offset, isOperandVolatile (IC_RESULT (ic), FALSE)); + add = "addc"; /* further adds must propagate carry */ + } else - { - MOVA (aopGet (rightOp, offset, FALSE, TRUE)); - emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE)); + { + if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) || + isOperandVolatile (IC_RESULT (ic), FALSE)) + { + /* just move */ + aopPut (AOP (IC_RESULT (ic)), + aopGet (leftOp, offset, FALSE, FALSE), + offset, + isOperandVolatile (IC_RESULT (ic), FALSE)); + } } - aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE)); - add = "addc"; /* further adds must propagate carry */ + offset++; } adjustArithmeticResult (ic); @@ -3547,13 +3670,21 @@ genMultOneByte (operand * left, if (SPEC_USIGN(opetype) // ignore the sign of left and right, what else can we do? - || (SPEC_USIGN(operandType(left)) && + || (SPEC_USIGN(operandType(left)) && SPEC_USIGN(operandType(right)))) { // just an unsigned 8*8=8/16 multiply //emitcode (";","unsigned"); // TODO: check for accumulator clash between left & right aops? - emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE)); - MOVA (aopGet (AOP (left), 0, FALSE, FALSE)); + + if( AOP_TYPE(right)==AOP_LIT ){ + // moving to accumulator first helps peepholes + MOVA (aopGet (AOP (left), 0, FALSE, FALSE)); + emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE)); + } else { + emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE)); + MOVA (aopGet (AOP (left), 0, FALSE, FALSE)); + } + emitcode ("mul", "ab"); aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE)); if (size==2) { @@ -3599,7 +3730,7 @@ genMultOneByte (operand * left, emitcode ("", "%05d$:", lbl->key+100); } emitcode ("mul", "ab"); - + lbl=newiTempLabel(NULL); emitcode ("jnb", "F0,%05d$", lbl->key+100); // only ONE op was negative, we have to do a 8/16-bit two's complement @@ -3651,7 +3782,7 @@ genMult (iCode * ic) #if 0 // one of them can be a sloc shared with the result if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1) #else - if (getSize(operandType(left)) == 1 && + if (getSize(operandType(left)) == 1 && getSize(operandType(right)) == 1) #endif { @@ -3665,9 +3796,9 @@ genMult (iCode * ic) assert (0); release: - freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); - freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); freeAsmop (result, NULL, ic, TRUE); + freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); + freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); } /*-----------------------------------------------------------------*/ @@ -3819,8 +3950,8 @@ genDiv (iCode * ic) /* should have been converted to function call */ assert (0); release: - freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); + freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); freeAsmop (result, NULL, ic, TRUE); } @@ -3964,8 +4095,8 @@ genMod (iCode * ic) assert (0); release: - freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); + freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); freeAsmop (result, NULL, ic, TRUE); } @@ -4109,8 +4240,8 @@ genCmp (operand * left, operand * right, } release: - freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); + freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) { outBitC (result); @@ -4201,12 +4332,14 @@ gencjneshort (operand * left, operand * right, symbol * lbl) if the right is in a pointer register and left is not */ if ((AOP_TYPE (left) == AOP_LIT) || + (AOP_TYPE (left) == AOP_IMMD) || (IS_AOP_PREG (right) && !IS_AOP_PREG (left))) { operand *t = right; right = left; left = t; } + if (AOP_TYPE (right) == AOP_LIT) lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit); @@ -4230,6 +4363,7 @@ gencjneshort (operand * left, operand * right, symbol * lbl) else if (AOP_TYPE (right) == AOP_REG || AOP_TYPE (right) == AOP_DIR || AOP_TYPE (right) == AOP_LIT || + AOP_TYPE (right) == AOP_IMMD || (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) || (IS_AOP_PREG (left) && !IS_AOP_PREG (right))) { @@ -4440,8 +4574,8 @@ genCmpEq (iCode * ic, iCode * ifx) } release: - freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); + freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); freeAsmop (result, NULL, ic, TRUE); } @@ -4540,8 +4674,8 @@ genAndOp (iCode * ic) outBitAcc (result); } - freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); + freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); freeAsmop (result, NULL, ic, TRUE); } @@ -4582,8 +4716,8 @@ genOrOp (iCode * ic) outBitAcc (result); } - freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); + freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); freeAsmop (result, NULL, ic, TRUE); } @@ -4829,6 +4963,8 @@ genAnd (iCode * ic, iCode * ifx) { if (ifx) jmpTrueOrFalse (ifx, tlbl); + else + emitcode ("", "%05d$:", tlbl->key + 100); goto release; } } @@ -4919,6 +5055,8 @@ genAnd (iCode * ic, iCode * ifx) } else if (ifx) jmpTrueOrFalse (ifx, tlbl); + else + emitcode ("", "%05d$:", tlbl->key + 100); } else { @@ -4961,8 +5099,8 @@ genAnd (iCode * ic, iCode * ifx) } release: - freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); + freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); freeAsmop (result, NULL, ic, TRUE); } @@ -5205,6 +5343,8 @@ genOr (iCode * ic, iCode * ifx) } else if (ifx) jmpTrueOrFalse (ifx, tlbl); + else + emitcode ("", "%05d$:", tlbl->key + 100); } else for (; (size--); offset++) @@ -5237,8 +5377,8 @@ genOr (iCode * ic, iCode * ifx) } release: - freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); + freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); freeAsmop (result, NULL, ic, TRUE); } @@ -5498,8 +5638,8 @@ genXor (iCode * ic, iCode * ifx) } release: - freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); + freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); freeAsmop (result, NULL, ic, TRUE); } @@ -5686,6 +5826,66 @@ genGetHbit (iCode * ic) freeAsmop (result, NULL, ic, TRUE); } +/*-----------------------------------------------------------------*/ +/* genSwap - generates code to swap nibbles or bytes */ +/*-----------------------------------------------------------------*/ +static void +genSwap (iCode * ic) +{ + operand *left, *result; + + D(emitcode ("; genSwap","")); + + left = IC_LEFT (ic); + result = IC_RESULT (ic); + aopOp (left, ic, FALSE); + aopOp (result, ic, FALSE); + + switch (AOP_SIZE (left)) + { + case 1: /* swap nibbles in byte */ + MOVA (aopGet (AOP (left), 0, FALSE, FALSE)); + emitcode ("swap", "a"); + aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE)); + break; + case 2: /* swap bytes in word */ + if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result))) + { + MOVA (aopGet (AOP (left), 0, FALSE, FALSE)); + aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE), + 0, isOperandVolatile (result, FALSE)); + aopPut (AOP (result), "a", 1, isOperandVolatile (result, FALSE)); + } + else if (operandsEqu (left, result)) + { + char * reg = "a"; + MOVA (aopGet (AOP (left), 0, FALSE, FALSE)); + if (aopGetUsesAcc(AOP (left), 1) || aopGetUsesAcc(AOP (result), 0)) + { + emitcode ("mov", "b,a"); + reg = "b"; + } + aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE), + 0, isOperandVolatile (result, FALSE)); + aopPut (AOP (result), reg, 1, isOperandVolatile (result, FALSE)); + } + else + { + aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE), + 0, isOperandVolatile (result, FALSE)); + aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE), + 1, isOperandVolatile (result, FALSE)); + } + break; + default: + wassertl(FALSE, "unsupported SWAP operand size"); + } + + freeAsmop (left, NULL, ic, TRUE); + freeAsmop (result, NULL, ic, TRUE); +} + + /*-----------------------------------------------------------------*/ /* AccRol - rotate left accumulator by known count */ /*-----------------------------------------------------------------*/ @@ -6528,7 +6728,7 @@ genLeftShiftLiteral (operand * left, genlshFour (result, left, shCount); break; default: - werror (E_INTERNAL_ERROR, __FILE__, __LINE__, + werror (E_INTERNAL_ERROR, __FILE__, __LINE__, "*** ack! mystery literal shift!\n"); break; } @@ -6998,7 +7198,7 @@ static void genRightShift (iCode * ic) { operand *right, *left, *result; - sym_link *retype; + sym_link *letype; int size, offset; char *l; symbol *tlbl, *tlbl1; @@ -7007,9 +7207,9 @@ genRightShift (iCode * ic) /* if signed then we do it the hard way preserve the sign bit moving it inwards */ - retype = getSpec (operandType (IC_RESULT (ic))); + letype = getSpec (operandType (IC_LEFT (ic))); - if (!SPEC_USIGN (retype)) + if (!SPEC_USIGN (letype)) { genSignedRightShift (ic); return; @@ -7323,21 +7523,40 @@ genNearPointerGet (operand * left, return; } - /* if the value is already in a pointer register + /* if the value is already in a pointer register then don't need anything more */ if (!AOP_INPREG (AOP (left))) { - /* otherwise get a free pointer register */ - aop = newAsmop (0); - preg = getFreePtr (ic, &aop, FALSE); - emitcode ("mov", "%s,%s", - preg->name, - aopGet (AOP (left), 0, FALSE, TRUE)); - rname = preg->name; + if (IS_AOP_PREG (left)) + { + // Aha, it is a pointer, just in disguise. + rname = aopGet (AOP (left), 0, FALSE, FALSE); + if (*rname != '@') + { + fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n", + __FILE__, __LINE__); + } + else + { + // Expected case. + emitcode ("mov", "a%s,%s", rname + 1, rname); + rname++; // skip the '@'. + } + } + else + { + /* otherwise get a free pointer register */ + aop = newAsmop (0); + preg = getFreePtr (ic, &aop, FALSE); + emitcode ("mov", "%s,%s", + preg->name, + aopGet (AOP (left), 0, FALSE, TRUE)); + rname = preg->name; + } } else rname = aopGet (AOP (left), 0, FALSE, FALSE); - + //aopOp (result, ic, FALSE); aopOp (result, ic, result?TRUE:FALSE); @@ -7375,7 +7594,7 @@ genNearPointerGet (operand * left, if (pi) { /* post increment present */ aopPut(AOP ( left ),rname,0, isOperandVolatile (left, FALSE)); } - freeAsmop (NULL, aop, ic, TRUE); + freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE); } else { @@ -7397,8 +7616,8 @@ genNearPointerGet (operand * left, } /* done */ + freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE); freeAsmop (left, NULL, ic, TRUE); - freeAsmop (result, NULL, ic, TRUE); if (pi) pi->generated = 1; } @@ -7494,6 +7713,66 @@ genPagedPointerGet (operand * left, } +/*--------------------------------------------------------------------*/ +/* loadDptrFromOperand - load dptr (and optionally B) from operand op */ +/*--------------------------------------------------------------------*/ +static void +loadDptrFromOperand (operand *op, bool loadBToo) +{ + if (AOP_TYPE (op) != AOP_STR) + { + /* if this is remateriazable */ + if (AOP_TYPE (op) == AOP_IMMD) + { + emitcode ("mov", "dptr,%s", aopGet (AOP (op), 0, TRUE, FALSE)); + if (loadBToo) + { + if (AOP(op)->aopu.aop_immd.from_cast_remat) + emitcode ("mov", "b,%s",aopGet(AOP (op), AOP_SIZE(op)-1, FALSE, FALSE)); + else + { + wassertl(FALSE, "need pointerCode"); + emitcode ("", "; mov b,???"); + /* genPointerGet and genPointerSet originally did different + ** things for this case. Both seem wrong. + ** from genPointerGet: + ** emitcode ("mov", "b,#%d", pointerCode (retype)); + ** from genPointerSet: + ** emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE)); + */ + } + } + } + else if (AOP_TYPE (op) == AOP_DPTR) + { + if (loadBToo) + { + MOVA (aopGet (AOP (op), 0, FALSE, FALSE)); + emitcode ("push", "acc"); + MOVA (aopGet (AOP (op), 1, FALSE, FALSE)); + emitcode ("push", "acc"); + emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE)); + emitcode ("pop", "dph"); + emitcode ("pop", "dpl"); + } + else + { + MOVA (aopGet (AOP (op), 0, FALSE, FALSE)); + emitcode ("push", "acc"); + emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE)); + emitcode ("pop", "dpl"); + } + } + else + { /* we need to get it byte by byte */ + emitcode ("mov", "dpl,%s", aopGet (AOP (op), 0, FALSE, FALSE)); + emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE)); + if (loadBToo) + emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE)); + } + } +} + /*-----------------------------------------------------------------*/ /* genFarPointerGet - gget value from far space */ /*-----------------------------------------------------------------*/ @@ -7507,21 +7786,9 @@ genFarPointerGet (operand * left, D(emitcode ("; genFarPointerGet","")); aopOp (left, ic, FALSE); - - /* if the operand is already in dptr - then we do nothing else we move the value to dptr */ - if (AOP_TYPE (left) != AOP_STR) - { - /* if this is remateriazable */ - if (AOP_TYPE (left) == AOP_IMMD) - emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE)); - else - { /* we need to get it byte by byte */ - emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE)); - emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE)); - } - } - /* so dptr know contains the address */ + loadDptrFromOperand (left, FALSE); + + /* so dptr now contains the address */ aopOp (result, ic, FALSE); /* if bit then unpack */ @@ -7563,21 +7830,9 @@ genCodePointerGet (operand * left, D(emitcode ("; genCodePointerGet","")); aopOp (left, ic, FALSE); - - /* if the operand is already in dptr - then we do nothing else we move the value to dptr */ - if (AOP_TYPE (left) != AOP_STR) - { - /* if this is remateriazable */ - if (AOP_TYPE (left) == AOP_IMMD) - emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE)); - else - { /* we need to get it byte by byte */ - emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE)); - emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE)); - } - } - /* so dptr know contains the address */ + loadDptrFromOperand (left, FALSE); + + /* so dptr now contains the address */ aopOp (result, ic, FALSE); /* if bit then unpack */ @@ -7628,27 +7883,8 @@ genGenPointerGet (operand * left, D(emitcode ("; genGenPointerGet","")); aopOp (left, ic, FALSE); - - /* if the operand is already in dptr - then we do nothing else we move the value to dptr */ - if (AOP_TYPE (left) != AOP_STR) - { - /* if this is remateriazable */ - if (AOP_TYPE (left) == AOP_IMMD) - { - emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE)); - if (AOP(left)->aopu.aop_immd.from_cast_remat) - emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE)); - else - emitcode ("mov", "b,#%d", pointerCode (retype)); - } - else - { /* we need to get it byte by byte */ - emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE)); - emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE)); - emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE)); - } - } + loadDptrFromOperand (left, TRUE); + /* so dptr know contains the address */ aopOp (result, ic, FALSE); @@ -7933,7 +8169,7 @@ genNearPointerSet (operand * right, genDataPointerSet (right, result, ic); return; } - + /* if the value is already in a pointer register then don't need anything more */ if (!AOP_INPREG (AOP (result))) @@ -7953,6 +8189,7 @@ genNearPointerSet (operand * right, else { // Expected case. + emitcode ("mov", "a%s,%s", rname + 1, rname); rname++; // skip the '@'. } } @@ -7973,7 +8210,7 @@ genNearPointerSet (operand * right, } aopOp (right, ic, FALSE); - + /* if bitfield then unpack the bits */ if (IS_BITVAR (retype) || IS_BITVAR (letype)) genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER); @@ -8139,20 +8376,8 @@ genFarPointerSet (operand * right, D(emitcode ("; genFarPointerSet","")); aopOp (result, ic, FALSE); - - /* if the operand is already in dptr - then we do nothing else we move the value to dptr */ - if (AOP_TYPE (result) != AOP_STR) - { - /* if this is remateriazable */ - if (AOP_TYPE (result) == AOP_IMMD) - emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE)); - else - { /* we need to get it byte by byte */ - emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE)); - emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE)); - } - } + loadDptrFromOperand (result, FALSE); + /* so dptr know contains the address */ aopOp (right, ic, FALSE); @@ -8196,27 +8421,8 @@ genGenPointerSet (operand * right, D(emitcode ("; genGenPointerSet","")); aopOp (result, ic, FALSE); - - /* if the operand is already in dptr - then we do nothing else we move the value to dptr */ - if (AOP_TYPE (result) != AOP_STR) - { - /* if this is remateriazable */ - if (AOP_TYPE (result) == AOP_IMMD) - { - emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE)); - if (AOP(result)->aopu.aop_immd.from_cast_remat) - emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE)); - else - emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE)); - } - else - { /* we need to get it byte by byte */ - emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE)); - emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE)); - emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE)); - } - } + loadDptrFromOperand (result, TRUE); + /* so dptr know contains the address */ aopOp (right, ic, FALSE); @@ -8613,7 +8819,9 @@ genCast (iCode * ic) aopOp (result, ic, FALSE); /* if the result is a bit (and not a bitfield) */ - if (AOP_TYPE (result) == AOP_CRY) + // if (AOP_TYPE (result) == AOP_CRY) + if (IS_BITVAR (OP_SYMBOL (result)->type) + && !IS_BITFIELD (OP_SYMBOL (result)->type) ) { /* if the right size is a literal then we know what the value is */ @@ -8907,36 +9115,119 @@ genReceive (iCode * ic) static void genDummyRead (iCode * ic) { - operand *right; + operand *op; int size, offset; D(emitcode("; genDummyRead","")); - right = IC_RIGHT (ic); + op = IC_RIGHT (ic); + if (op && IS_SYMOP (op)) + { + aopOp (op, ic, FALSE); - aopOp (right, ic, FALSE); + /* if the result is a bit */ + if (AOP_TYPE (op) == AOP_CRY) + emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir); + else + { + /* bit variables done */ + /* general case */ + size = AOP_SIZE (op); + offset = 0; + while (size--) + { + MOVA (aopGet (AOP (op), offset, FALSE, FALSE)); + offset++; + } + } - /* if the result is a bit */ - if (AOP_TYPE (right) == AOP_CRY) - { - emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir); - goto release; + freeAsmop (op, NULL, ic, TRUE); } - /* bit variables done */ - /* general case */ - size = AOP_SIZE (right); - offset = 0; - while (size--) + op = IC_LEFT (ic); + if (op && IS_SYMOP (op)) { - emitcode ("mov", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE)); - offset++; + aopOp (op, ic, FALSE); + + /* if the result is a bit */ + if (AOP_TYPE (op) == AOP_CRY) + emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir); + else + { + /* bit variables done */ + /* general case */ + size = AOP_SIZE (op); + offset = 0; + while (size--) + { + MOVA (aopGet (AOP (op), offset, FALSE, FALSE)); + offset++; + } + } + + freeAsmop (op, NULL, ic, TRUE); } +} -release: - freeAsmop (right, NULL, ic, TRUE); +/*-----------------------------------------------------------------*/ +/* genCritical - generate code for start of a critical sequence */ +/*-----------------------------------------------------------------*/ +static void +genCritical (iCode *ic) +{ + symbol *tlbl = newiTempLabel (NULL); + + D(emitcode("; genCritical","")); + + if (IC_RESULT (ic)) + aopOp (IC_RESULT (ic), ic, TRUE); + + emitcode ("setb", "c"); + emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */ + emitcode ("clr", "c"); + emitcode ("", "%05d$:", (tlbl->key + 100)); + + if (IC_RESULT (ic)) + outBitC (IC_RESULT (ic)); /* save old ea in an operand */ + else + emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/ + + if (IC_RESULT (ic)) + freeAsmop (IC_RESULT (ic), NULL, ic, TRUE); } +/*-----------------------------------------------------------------*/ +/* genEndCritical - generate code for end of a critical sequence */ +/*-----------------------------------------------------------------*/ +static void +genEndCritical (iCode *ic) +{ + D(emitcode("; genEndCritical","")); + + if (IC_RIGHT (ic)) + { + aopOp (IC_RIGHT (ic), ic, FALSE); + if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY) + { + emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir); + emitcode ("mov", "ea,c"); + } + else + { + MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE)); + emitcode ("rrc", "a"); + emitcode ("mov", "ea,c"); + } + freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE); + } + else + { + emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */ + emitcode ("mov", "ea,c"); + } +} + + /*-----------------------------------------------------------------*/ /* gen51Code - generate code for 8051 based controllers */ /*-----------------------------------------------------------------*/ @@ -8971,7 +9262,8 @@ gen51Code (iCode * lic) for (ic = lic; ic; ic = ic->next) { - + _G.current_iCode = ic; + if (ic->lineno && cln != ic->lineno) { if (options.debug) @@ -9194,11 +9486,24 @@ gen51Code (iCode * lic) genDummyRead (ic); break; + case CRITICAL: + genCritical (ic); + break; + + case ENDCRITICAL: + genEndCritical (ic); + break; + + case SWAP: + genSwap (ic); + break; + default: ic = ic; } } + _G.current_iCode = NULL; /* now we are ready to call the peep hole optimizer */