X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Fmcs51%2Fgen.c;h=7e61b9de17774c15d138a7921eaf9be969798250;hb=7837c232c608353fb948c183d8e92775f427e5a9;hp=80c01820113ab5c82d85047a1ff74eff3bbe0a02;hpb=cb3db55b4256c2f014c9ea1f9c96030b591e580b;p=fw%2Fsdcc diff --git a/src/mcs51/gen.c b/src/mcs51/gen.c index 80c01820..7e61b9de 100644 --- a/src/mcs51/gen.c +++ b/src/mcs51/gen.c @@ -62,7 +62,7 @@ char **fReturn = fReturn8051; static char *accUse[] = {"a", "b"}; -static short rbank = -1; +static unsigned short rbank = -1; static struct { @@ -73,6 +73,8 @@ static struct short debugLine; short nRegsSaved; set *sendSet; + iCode *current_iCode; + symbol *currentFunc; } _G; @@ -111,7 +113,7 @@ static unsigned char SRMask[] = /* emitcode - writes the code into a file : for now it is simple */ /*-----------------------------------------------------------------*/ static void -emitcode (char *inst, char *fmt,...) +emitcode (char *inst, const char *fmt,...) { va_list ap; char lb[INITIAL_INLINEASM]; @@ -133,12 +135,16 @@ emitcode (char *inst, char *fmt,...) while (isspace (*lbp)) lbp++; + //printf ("%s\n", lb); + if (lbp && *lbp) lineCurr = (lineCurr ? connectLine (lineCurr, newLineNode (lb)) : (lineHead = newLineNode (lb))); lineCurr->isInline = _G.inLine; lineCurr->isDebug = _G.debugLine; + lineCurr->ic = _G.current_iCode; + lineCurr->isComment = (*lbp==';'); va_end (ap); } @@ -146,7 +152,7 @@ emitcode (char *inst, char *fmt,...) /* mova - moves specified value into accumulator */ /*-----------------------------------------------------------------*/ static void -mova (char *x) +mova (const char *x) { /* do some early peephole optimization */ if (!strcmp(x, "a") || !strcmp(x, "acc")) @@ -255,6 +261,60 @@ endOfWorld: exit (1); } + +/*-----------------------------------------------------------------*/ +/* getTempRegs - initialize an array of pointers to GPR registers */ +/* that are not in use. Returns 1 if the requested */ +/* number of registers were available, 0 otherwise. */ +/*-----------------------------------------------------------------*/ +int +getTempRegs(regs **tempRegs, int size, iCode *ic) +{ + bitVect * freeRegs; + int i; + int offset; + + if (!ic) + ic = _G.current_iCode; + if (!ic) + return 0; + if (!_G.currentFunc) + return 0; + + freeRegs = newBitVect(8); + bitVectSetBit (freeRegs, R2_IDX); + bitVectSetBit (freeRegs, R3_IDX); + bitVectSetBit (freeRegs, R4_IDX); + bitVectSetBit (freeRegs, R5_IDX); + bitVectSetBit (freeRegs, R6_IDX); + bitVectSetBit (freeRegs, R7_IDX); + + if (IFFUNC_CALLEESAVES(_G.currentFunc->type)) + { + bitVect * newfreeRegs; + newfreeRegs = bitVectIntersect (freeRegs, _G.currentFunc->regsUsed); + freeBitVect(freeRegs); + freeRegs = newfreeRegs; + } + freeRegs = bitVectCplAnd (freeRegs, ic->rMask); + + offset = 0; + for (i=0; isize; i++) + { + if (bitVectBitValue(freeRegs,i)) + tempRegs[offset++] = mcs51_regWithIdx(i); + if (offset>=size) + { + freeBitVect(freeRegs); + return 1; + } + } + + freeBitVect(freeRegs); + return 1; +} + + /*-----------------------------------------------------------------*/ /* newAsmop - creates a new asmOp */ /*-----------------------------------------------------------------*/ @@ -279,6 +339,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 +441,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 +452,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 +477,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 +765,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 +843,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 +870,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 +936,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 +945,6 @@ aopGetUsesAcc (asmop *aop, int offset) } } - /*-----------------------------------------------------------------*/ /* aopGet - for fetching value of the aop */ /*-----------------------------------------------------------------*/ @@ -823,6 +963,8 @@ 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: @@ -947,7 +1089,7 @@ aopGet (asmop * aop, int offset, bool bit16, bool dname) /* aopPut - puts a string for a aop */ /*-----------------------------------------------------------------*/ static void -aopPut (asmop * aop, char *s, int offset) +aopPut (asmop * aop, const char *s, int offset, bool bvolatile) { char *d = buffer; @@ -962,6 +1104,10 @@ aopPut (asmop * aop, char *s, int offset) /* 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)", @@ -969,7 +1115,8 @@ aopPut (asmop * aop, char *s, int offset) else sprintf (d, "%s", aop->aopu.aop_dir); - if (strcmp (d, s)) + if (strcmp (d, s) || + bvolatile) emitcode ("mov", "%s,%s", d, s); break; @@ -999,7 +1146,7 @@ aopPut (asmop * aop, char *s, int offset) if (aop->code) { werror (E_INTERNAL_ERROR, __FILE__, __LINE__, - "aopPut writting to code space"); + "aopPut writing to code space"); exit (1); } @@ -1112,16 +1259,19 @@ aopPut (asmop * aop, char *s, int offset) case AOP_STR: aop->coff = offset; - if (strcmp (aop->aopu.aop_str[offset], s)) + if (strcmp (aop->aopu.aop_str[offset], s) || + bvolatile) emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s); break; case AOP_ACC: aop->coff = offset; - if (!offset && (strcmp (s, "acc") == 0)) + if (!offset && (strcmp (s, "acc") == 0) && + !bvolatile) break; - if (strcmp (aop->aopu.aop_str[offset], s)) + if (strcmp (aop->aopu.aop_str[offset], s) && + !bvolatile) emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s); break; @@ -1201,46 +1351,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); - 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); - emitcode ("jz", "%05d$", (tlbl->key + 100)); - aopPut (res->aop, zero, 1); - emitcode ("", "%05d$:", (tlbl->key + 100)); - - size = res->aop->size - 2; - offset = 2; - /* put zeros in the rest */ - while (size--) - aopPut (res->aop, zero, offset++); -} /*-----------------------------------------------------------------*/ /* opIsGptr: returns non-zero if the passed operand is */ @@ -1290,13 +1400,13 @@ outAcc (operand * result) size = getDataSize (result); if (size) { - aopPut (AOP (result), "a", 0); + aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE)); size--; offset = 1; /* unsigned or positive */ while (size--) { - aopPut (AOP (result), zero, offset++); + aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE)); } } } @@ -1309,7 +1419,7 @@ outBitC (operand * result) { /* if the result is bit */ if (AOP_TYPE (result) == AOP_CRY) - aopPut (AOP (result), "c", 0); + aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE)); else { emitcode ("clr", "a"); @@ -1339,7 +1449,6 @@ static void genNot (iCode * ic) { symbol *tlbl; - sym_link *optype = operandType (IC_LEFT (ic)); D(emitcode ("; genNot","")); @@ -1356,13 +1465,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); @@ -1394,20 +1496,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--) @@ -1415,7 +1532,7 @@ genCpl (iCode * ic) char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE); MOVA (l); emitcode ("cpl", "a"); - aopPut (AOP (IC_RESULT (ic)), "a", offset++); + aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE)); } @@ -1444,7 +1561,8 @@ genUminusFloat (operand * op, operand * result) { aopPut (AOP (result), aopGet (AOP (op), offset, FALSE, FALSE), - offset); + offset, + isOperandVolatile (result, FALSE)); offset++; } @@ -1453,7 +1571,7 @@ genUminusFloat (operand * op, operand * result) MOVA (l); emitcode ("cpl", "acc.7"); - aopPut (AOP (result), "a", offset); + aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE)); } /*-----------------------------------------------------------------*/ @@ -1515,7 +1633,7 @@ genUminus (iCode * ic) emitcode ("clr", "a"); emitcode ("subb", "a,%s", l); } - aopPut (AOP (IC_RESULT (ic)), "a", offset++); + aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE)); } /* if any remaining bytes in the result */ @@ -1525,7 +1643,7 @@ genUminus (iCode * ic) emitcode ("rlc", "a"); emitcode ("subb", "a,acc"); while (size--) - aopPut (AOP (IC_RESULT (ic)), "a", offset++); + aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE)); } release: @@ -1563,10 +1681,10 @@ saveRegisters (iCode * lic) (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) || IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic))))) return; - + /* safe the registers in use at this time but skip the ones for the result */ - rsave = bitVectCplAnd (bitVectCopy (ic->rMask), + rsave = bitVectCplAnd (bitVectCopy (ic->rMask), mcs51_rUmaskForOp (IC_RESULT(ic))); ic->regsSaved = 1; @@ -1610,7 +1728,7 @@ unsaveRegisters (iCode * ic) /* restore the registers in use at this time but skip the ones for the result */ - rsave = bitVectCplAnd (bitVectCopy (ic->rMask), + rsave = bitVectCplAnd (bitVectCopy (ic->rMask), mcs51_rUmaskForOp (IC_RESULT(ic))); if (options.useXstack) @@ -1657,7 +1775,7 @@ pushSide (operand * oper, int size) AOP_TYPE (oper) != AOP_DIR && strcmp (l, "a")) { - emitcode ("mov", "a,%s", l); + MOVA (l); emitcode ("push", "acc"); } else @@ -1675,7 +1793,7 @@ assignResultValue (operand * oper) int size = AOP_SIZE (oper); while (size--) { - aopPut (AOP (oper), fReturn[offset], offset); + aopPut (AOP (oper), fReturn[offset], offset, isOperandVolatile (oper, FALSE)); offset++; } } @@ -1781,7 +1899,7 @@ genIpush (iCode * ic) AOP_TYPE (IC_LEFT (ic)) != AOP_DIR && strcmp (l, "a")) { - emitcode ("mov", "a,%s", l); + MOVA (l); emitcode ("push", "acc"); } else @@ -1830,16 +1948,16 @@ unsaveRBank (int bank, iCode * ic, bool popPsw) if (!ic) { /* Assume r0 is available for use. */ - r = mcs51_regWithIdx (R0_IDX);; - } + r = mcs51_regWithIdx (R0_IDX);; + } else { aop = newAsmop (0); r = getFreePtr (ic, &aop, FALSE); } - emitcode ("mov", "%s,_spx", r->name); + emitcode ("mov", "%s,_spx", r->name); } - + if (popPsw) { if (options.useXstack) @@ -1873,11 +1991,11 @@ unsaveRBank (int bank, iCode * ic, bool popPsw) { emitcode ("mov", "_spx,%s", r->name); } - + if (aop) { - freeAsmop (NULL, aop, ic, TRUE); - } + freeAsmop (NULL, aop, ic, TRUE); + } } /*-----------------------------------------------------------------*/ @@ -1943,7 +2061,7 @@ saveRBank (int bank, iCode * ic, bool pushPsw) } if (ic) - { + { ic->bankSaved = 1; } } @@ -1976,7 +2094,7 @@ static void genSend(set *sendSet) emitcode ("mov","b1_%d,%s",rb1_count++, aopGet (AOP (IC_LEFT (sic)), offset++,FALSE, FALSE)); } - } + } freeAsmop (IC_LEFT (sic), NULL, sic, TRUE); } } @@ -2014,16 +2132,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); } @@ -2034,14 +2152,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))) { @@ -2133,7 +2251,7 @@ genPcall (iCode * ic) if (swapBanks) { - emitcode ("mov", "psw,#0x%02x", + emitcode ("mov", "psw,#0x%02x", ((FUNC_REGBANK(dtype)) << 3) & 0xff); } @@ -2144,7 +2262,7 @@ genPcall (iCode * ic) if (swapBanks) { - emitcode ("mov", "psw,#0x%02x", + emitcode ("mov", "psw,#0x%02x", ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff); } @@ -2243,30 +2361,30 @@ inExcludeList (char *s) static void genFunction (iCode * ic) { - symbol *sym; + symbol *sym = OP_SYMBOL (IC_LEFT (ic)); sym_link *ftype; bool switchedPSW = FALSE; int calleesaves_saved_register = -1; + int stackAdjust = sym->stack; + int accIsFree = sym->recvSize < 4; + iCode * ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL; _G.nRegsSaved = 0; /* create the function header */ emitcode (";", "-----------------------------------------"); - emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name); + emitcode (";", " function %s", sym->name); emitcode (";", "-----------------------------------------"); emitcode ("", "%s:", sym->rname); ftype = operandType (IC_LEFT (ic)); + _G.currentFunc = sym; if (IFFUNC_ISNAKED(ftype)) { emitcode(";", "naked function: no prologue."); 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) @@ -2320,17 +2438,15 @@ genFunction (iCode * ic) /* save the registers used */ for (i = 0; i < sym->regsUsed->size; i++) { - if (bitVectBitValue (sym->regsUsed, i) || - (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX))) + if (bitVectBitValue (sym->regsUsed, i)) emitcode ("push", "%s", mcs51_regWithIdx (i)->dname); } } - } else { - - /* this function has a function call cannot + + /* this function has a function call. We cannot determines register usage so we will have to push the entire bank */ saveRBank (0, ic, FALSE); @@ -2353,7 +2469,7 @@ genFunction (iCode * ic) * other bank, we must save that bank entirely. */ unsigned long banksToSave = 0; - + if (IFFUNC_HASFCALL(sym->type)) { @@ -2369,11 +2485,11 @@ genFunction (iCode * ic) /* we got to the end OK. */ break; } - + if (i->op == CALL) { sym_link *dtype; - + dtype = operandType (IC_LEFT(i)); if (dtype && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type)) @@ -2387,8 +2503,8 @@ genFunction (iCode * ic) { banksToSave |= (1 << FUNC_REGBANK(dtype)); } - - /* And note that we don't need to do it in + + /* And note that we don't need to do it in * genCall. */ i->bankSaved = 1; @@ -2403,24 +2519,24 @@ genFunction (iCode * ic) * The only thing I can think of to do is * throw a warning and hope. */ - werror(W_FUNCPTR_IN_USING_ISR); + werror(W_FUNCPTR_IN_USING_ISR); } } if (banksToSave && options.useXstack) { - /* Since we aren't passing it an ic, + /* Since we aren't passing it an ic, * saveRBank will assume r0 is available to abuse. * * So switch to our (trashable) bank now, so * the caller's R0 isn't trashed. */ emitcode ("push", "psw"); - emitcode ("mov", "psw,#0x%02x", + emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff); switchedPSW = TRUE; } - + for (ix = 0; ix < MAX_REGISTER_BANKS; ix++) { if (banksToSave & (1 << ix)) @@ -2432,9 +2548,20 @@ genFunction (iCode * ic) // TODO: this needs a closer look SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave; } + + /* Set the register bank to the desired value if nothing else */ + /* has done so yet. */ + if (!switchedPSW) + { + emitcode ("push", "psw"); + emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff); + } } else { + /* This is a non-ISR function. The caller has already switched register */ + /* banks, if necessary, so just handle the callee-saves option. */ + /* if callee-save to be used for this function then save the registers being used in this function */ if (IFFUNC_CALLEESAVES(sym->type)) @@ -2447,8 +2574,7 @@ genFunction (iCode * ic) /* save the registers used */ for (i = 0; i < sym->regsUsed->size; i++) { - if (bitVectBitValue (sym->regsUsed, i) || - (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX))) + if (bitVectBitValue (sym->regsUsed, i)) { /* remember one saved register for later usage */ if (calleesaves_saved_register < 0) @@ -2461,23 +2587,20 @@ genFunction (iCode * ic) } } - /* set the register bank to the desired value */ - if (( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type)) - && !switchedPSW) - { - emitcode ("push", "psw"); - emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff); - } if (IFFUNC_ISREENT (sym->type) || options.stackAuto) { if (options.useXstack) { + if (!accIsFree) + emitcode ("push", "acc"); emitcode ("mov", "r0,%s", spname); emitcode ("mov", "a,_bp"); emitcode ("movx", "@r0,a"); emitcode ("inc", "%s", spname); + if (!accIsFree) + emitcode ("pop", "acc"); } else { @@ -2486,16 +2609,76 @@ genFunction (iCode * ic) } emitcode ("mov", "_bp,%s", spname); } - + + /* For some cases it is worthwhile to perform a RECEIVE iCode */ + /* before setting up the stack frame completely. */ + if (ric && ric->argreg == 1 && IC_RESULT (ric)) + { + symbol * rsym = OP_SYMBOL (IC_RESULT (ric)); + + if (rsym->isitmp) + { + if (rsym && rsym->regType == REG_CND) + rsym = NULL; + if (rsym && (rsym->accuse || rsym->ruonly)) + rsym = NULL; + if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc) + rsym = rsym->usl.spillLoc; + } + + /* If the RECEIVE operand immediately spills to the first entry on the */ + /* stack, we can push it directly (since sp = _bp + 1 at this point) */ + /* rather than the usual @r0/r1 machinations. */ + if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1) + { + int ofs; + + _G.current_iCode = ric; + D(emitcode ("; genReceive","")); + for (ofs=0; ofs < sym->recvSize; ofs++) + { + if (!strcmp (fReturn[ofs], "a")) + emitcode ("push", "acc"); + else + emitcode ("push", fReturn[ofs]); + } + stackAdjust -= sym->recvSize; + if (stackAdjust<0) + { + assert (stackAdjust>=0); + stackAdjust = 0; + } + _G.current_iCode = ic; + ric->generated = 1; + accIsFree = 1; + } + /* If the RECEIVE operand is 4 registers, we can do the moves now */ + /* to free up the accumulator. */ + else if (rsym && rsym->nRegs && sym->recvSize == 4) + { + int ofs; + + _G.current_iCode = ric; + D(emitcode ("; genReceive","")); + for (ofs=0; ofs < sym->recvSize; ofs++) + { + emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]); + } + _G.current_iCode = ic; + ric->generated = 1; + accIsFree = 1; + } + } + /* adjust the stack for the function */ - if (sym->stack) + if (stackAdjust) { - int i = sym->stack; + int i = stackAdjust; if (i > 256) werror (W_STACK_OVERFLOW, sym->name); - if (i > 3 && sym->recvSize < 4) + if (i > 3 && accIsFree) { emitcode ("mov", "a,sp"); @@ -2505,6 +2688,11 @@ genFunction (iCode * ic) } else if (i > 5) { + /* The accumulator is not free, so we will need another register */ + /* to clobber. No need to worry about a possible conflict with */ + /* the above early RECEIVE optimizations since they would have */ + /* freed the accumulator if they were generated. */ + if (IFFUNC_CALLEESAVES(sym->type)) { /* if it's a callee-saves function we need a saved register */ @@ -2539,11 +2727,25 @@ genFunction (iCode * ic) if (sym->xstack) { + if (!accIsFree) + emitcode ("push", "acc"); emitcode ("mov", "a,_spx"); emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff)); emitcode ("mov", "_spx,a"); + if (!accIsFree) + emitcode ("pop", "acc"); } + /* 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 */ + } } /*-----------------------------------------------------------------*/ @@ -2553,13 +2755,25 @@ static void genEndFunction (iCode * ic) { symbol *sym = OP_SYMBOL (IC_LEFT (ic)); - + lineNode *lnp = lineCurr; + bitVect *regsUsed; + bitVect *regsUsedPrologue; + bitVect *regsUnneeded; + int idx; + + _G.currentFunc = NULL; if (IFFUNC_ISNAKED(sym->type)) { 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) { emitcode ("mov", "%s,_bp", spname); @@ -2626,18 +2840,16 @@ genEndFunction (iCode * ic) /* save the registers used */ for (i = sym->regsUsed->size; i >= 0; i--) { - if (bitVectBitValue (sym->regsUsed, i) || - (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX))) + if (bitVectBitValue (sym->regsUsed, i)) emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname); } } - } else { if (options.parms_in_bank1) { int i; - for (i = 7 ; i >= 0 ; i-- ) { + for (i = 7 ; i >= 0 ; i-- ) { emitcode ("pop","%s",rb1regs[i]); } } @@ -2656,7 +2868,7 @@ genEndFunction (iCode * ic) */ unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype); int ix; - + for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--) { if (savedBanks & (1 << ix)) @@ -2664,7 +2876,7 @@ genEndFunction (iCode * ic) unsaveRBank(ix, NULL, FALSE); } } - + if (options.useXstack) { /* Restore bank AFTER calling unsaveRBank, @@ -2683,9 +2895,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) { @@ -2704,9 +2913,6 @@ genEndFunction (iCode * ic) } else { - if (IFFUNC_ISCRITICAL (sym->type)) - emitcode ("setb", "ea"); - if (IFFUNC_CALLEESAVES(sym->type)) { int i; @@ -2722,6 +2928,11 @@ genEndFunction (iCode * ic) emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname); } } + else if (mcs51_ptrRegReq) + { + emitcode ("pop", "%s", mcs51_regWithIdx (R1_IDX)->dname); + emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname); + } } @@ -2742,6 +2953,99 @@ genEndFunction (iCode * ic) emitcode ("ret", ""); } + if (!port->peep.getRegsRead || !port->peep.getRegsWritten) + return; + + /* If this was an interrupt handler using bank 0 that called another */ + /* function, then all registers must be saved; nothing to optimized. */ + if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type) + && !FUNC_REGBANK(sym->type)) + return; + + /* There are no push/pops to optimize if not callee-saves or ISR */ + if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type))) + return; + + /* If there were stack parameters, we cannot optimize without also */ + /* fixing all of the stack offsets; this is too dificult to consider. */ + if (FUNC_HASSTACKPARM(sym->type)) + return; + + /* Compute the registers actually used */ + regsUsed = newBitVect (mcs51_nRegs); + regsUsedPrologue = newBitVect (mcs51_nRegs); + while (lnp) + { + if (lnp->ic && lnp->ic->op == FUNCTION) + regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp)); + else + regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp)); + + if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev + && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION) + break; + if (!lnp->prev) + break; + lnp = lnp->prev; + } + + if (bitVectBitValue (regsUsedPrologue, CND_IDX) + && !bitVectBitValue (regsUsed, CND_IDX)) + { + regsUsed = bitVectUnion (regsUsed, regsUsedPrologue); + if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK(sym->type) + && !sym->stack) + bitVectUnSetBit (regsUsed, CND_IDX); + } + else + regsUsed = bitVectUnion (regsUsed, regsUsedPrologue); + + /* If this was an interrupt handler that called another function */ + /* function, then assume A, B, DPH, & DPL may be modified by it. */ + if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)) + { + regsUsed = bitVectSetBit (regsUsed, DPL_IDX); + regsUsed = bitVectSetBit (regsUsed, DPH_IDX); + regsUsed = bitVectSetBit (regsUsed, B_IDX); + regsUsed = bitVectSetBit (regsUsed, A_IDX); + regsUsed = bitVectSetBit (regsUsed, CND_IDX); + } + + /* Remove the unneeded push/pops */ + regsUnneeded = newBitVect (mcs51_nRegs); + while (lnp) + { + if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION)) + { + if (!strncmp(lnp->line, "push", 4)) + { + idx = bitVectFirstBit (port->peep.getRegsRead(lnp)); + if (idx>=0 && !bitVectBitValue (regsUsed, idx)) + { + connectLine (lnp->prev, lnp->next); + regsUnneeded = bitVectSetBit (regsUnneeded, idx); + } + } + if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3)) + { + idx = bitVectFirstBit (port->peep.getRegsWritten(lnp)); + if (idx>=0 && !bitVectBitValue (regsUsed, idx)) + { + connectLine (lnp->prev, lnp->next); + regsUnneeded = bitVectSetBit (regsUnneeded, idx); + } + } + } + lnp = lnp->next; + } + + for (idx = 0; idx < regsUnneeded->size; idx++) + if (bitVectBitValue (regsUnneeded, idx)) + emitcode ("", ";\teliminated unneeded push/pop %s", mcs51_regWithIdx (idx)->dname); + + freeBitVect (regsUnneeded); + freeBitVect (regsUsed); + freeBitVect (regsUsedPrologue); } /*-----------------------------------------------------------------*/ @@ -2846,7 +3150,7 @@ findLabelBackwards (iCode * ic, int key) count++; /* If we have any pushes or pops, we cannot predict the distance. - I don't like this at all, this should be dealt with in the + I don't like this at all, this should be dealt with in the back-end */ if (ic->op == IPUSH || ic->op == IPOP) { return 0; @@ -2885,7 +3189,7 @@ genPlusIncr (iCode * ic) /* if increment >=16 bits in register or direct space */ if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) && - sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) && + sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) && (size > 1) && (icount == 1)) { @@ -2977,7 +3281,7 @@ genPlusIncr (iCode * ic) { MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE)); emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff); - aopPut (AOP (IC_RESULT (ic)), "a", 0); + aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE)); } else { @@ -3002,7 +3306,7 @@ outBitAcc (operand * result) /* if the result is a bit */ if (AOP_TYPE (result) == AOP_CRY) { - aopPut (AOP (result), "a", 0); + aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE)); } else { @@ -3055,14 +3359,16 @@ adjustArithmeticResult (iCode * ic) !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)))) aopPut (AOP (IC_RESULT (ic)), aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE), - 2); + 2, + isOperandVolatile (IC_RESULT (ic), FALSE)); if (AOP_SIZE (IC_RESULT (ic)) == 3 && AOP_SIZE (IC_RIGHT (ic)) == 3 && !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic)))) aopPut (AOP (IC_RESULT (ic)), aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE), - 2); + 2, + isOperandVolatile (IC_RESULT (ic), FALSE)); if (AOP_SIZE (IC_RESULT (ic)) == 3 && AOP_SIZE (IC_LEFT (ic)) < 3 && @@ -3072,7 +3378,7 @@ adjustArithmeticResult (iCode * ic) { char buffer[5]; sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic))))); - aopPut (AOP (IC_RESULT (ic)), buffer, 2); + aopPut (AOP (IC_RESULT (ic)), buffer, 2, isOperandVolatile (IC_RESULT (ic), FALSE)); } } #else @@ -3089,7 +3395,8 @@ adjustArithmeticResult (iCode * ic) { aopPut (AOP (IC_RESULT (ic)), aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE), - GPTRSIZE - 1); + GPTRSIZE - 1, + isOperandVolatile (IC_RESULT (ic), FALSE)); } if (opIsGptr (IC_RESULT (ic)) && @@ -3098,7 +3405,8 @@ adjustArithmeticResult (iCode * ic) { aopPut (AOP (IC_RESULT (ic)), aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE), - GPTRSIZE - 1); + GPTRSIZE - 1, + isOperandVolatile (IC_RESULT (ic), FALSE)); } if (opIsGptr (IC_RESULT (ic)) && @@ -3109,7 +3417,7 @@ adjustArithmeticResult (iCode * ic) { char buffer[5]; sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic))))); - aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1); + aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1, isOperandVolatile (IC_RESULT (ic), FALSE)); } } #endif @@ -3121,8 +3429,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 :- */ @@ -3172,7 +3482,7 @@ genPlus (iCode * ic) { MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE)); emitcode ("addc", "a,#00"); - aopPut (AOP (IC_RESULT (ic)), "a", offset++); + aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE)); } } goto release; @@ -3184,37 +3494,96 @@ 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)) - { - 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)) + if( 1 == getDataSize (IC_RIGHT (ic)) ) { - MOVA (aopGet (leftOp, offset, FALSE, TRUE)); - emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE)); + aopPut (AOP (IC_RESULT (ic)), + aopGet (leftOp, 1, FALSE, FALSE), + 1, + isOperandVolatile (IC_RESULT (ic), FALSE)); } else - { - MOVA (aopGet (rightOp, offset, FALSE, TRUE)); - emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE)); + { + 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)); } - aopPut (AOP (IC_RESULT (ic)), "a", offset++); - add = "addc"; /* further adds must propagate carry */ + goto release; } - adjustArithmeticResult (ic); - + /* 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 + { + 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)); + } + } + offset++; + } + + adjustArithmeticResult (ic); + release: freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); @@ -3356,11 +3725,11 @@ addSign (operand * result, int offset, int sign) emitcode ("rlc", "a"); emitcode ("subb", "a,acc"); while (size--) - aopPut (AOP (result), "a", offset++); + aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE)); } else while (size--) - aopPut (AOP (result), zero, offset++); + aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE)); } } @@ -3389,7 +3758,7 @@ genMinusBits (iCode * ic) emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100)); emitcode ("inc", "a"); emitcode ("", "%05d$:", (lbl->key + 100)); - aopPut (AOP (IC_RESULT (ic)), "a", 0); + aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE)); addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic))))); } } @@ -3437,17 +3806,17 @@ genMinus (iCode * ic) MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE)); /* first add without previous c */ if (!offset) { - if (!size && lit==-1) { + if (!size && lit== (unsigned long) -1) { emitcode ("dec", "a"); } else { - emitcode ("add", "a,#0x%02x", + emitcode ("add", "a,#0x%02x", (unsigned int) (lit & 0x0FFL)); } } else { emitcode ("addc", "a,#0x%02x", (unsigned int) ((lit >> (offset * 8)) & 0x0FFL)); } - aopPut (AOP (IC_RESULT (ic)), "a", offset++); + aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE)); } } else @@ -3475,11 +3844,11 @@ genMinus (iCode * ic) aopGet(rightOp, offset, FALSE, TRUE)); } - aopPut (AOP (IC_RESULT (ic)), "a", offset++); + aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE)); } } - - + + adjustArithmeticResult (ic); release: @@ -3504,7 +3873,6 @@ genMultbits (operand * left, outBitC (result); } - /*-----------------------------------------------------------------*/ /* genMultOneByte : 8*8=8/16 bit multiplication */ /*-----------------------------------------------------------------*/ @@ -3513,18 +3881,20 @@ genMultOneByte (operand * left, operand * right, operand * result) { - sym_link *opetype = operandType (result); symbol *lbl; - int size=AOP_SIZE(result); + int size = AOP_SIZE (result); + bool runtimeSign, compiletimeSign; + bool lUnsigned, rUnsigned; D(emitcode ("; genMultOneByte","")); - if (size<1 || size>2) { - // this should never happen - fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", + if (size < 1 || size > 2) + { + /* this should never happen */ + fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", AOP_SIZE(result), __FILE__, lineno); exit (1); - } + } /* (if two literals: the value is computed before) */ /* if one literal, literal on the right */ @@ -3533,83 +3903,171 @@ genMultOneByte (operand * left, operand *t = right; right = left; left = t; - //emitcode (";", "swapped left and right"); - } - - if (SPEC_USIGN(opetype) - // ignore the sign of left and right, what else can we do? - || (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)); - emitcode ("mul", "ab"); - aopPut (AOP (result), "a", 0); - if (size==2) { - aopPut (AOP (result), "b", 1); + /* emitcode (";", "swapped left and right"); */ } - return; - } + /* if no literal, unsigned on the right: shorter code */ + if ( AOP_TYPE (right) != AOP_LIT + && SPEC_USIGN (getSpec (operandType (left)))) + { + operand *t = right; + right = left; + left = t; + } + + lUnsigned = SPEC_USIGN (getSpec (operandType (left))); + rUnsigned = SPEC_USIGN (getSpec (operandType (right))); + + if (size == 1 /* no, this is not a bug; with a 1 byte result there's + no need to take care about the signedness! */ + || (lUnsigned && rUnsigned)) + { + /* just an unsigned 8 * 8 = 8 multiply + or 8u * 8u = 16u */ + /* emitcode (";","unsigned"); */ + /* TODO: check for accumulator clash between left & right aops? */ + + 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)); + } - // we have to do a signed multiply + emitcode ("mul", "ab"); + aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE)); + if (size == 2) + aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE)); + return; + } - //emitcode (";", "signed"); - emitcode ("clr", "F0"); // reset sign flag - MOVA (aopGet (AOP (left), 0, FALSE, FALSE)); + /* we have to do a signed multiply */ + /* emitcode (";", "signed"); */ - lbl=newiTempLabel(NULL); - emitcode ("jnb", "acc.7,%05d$", lbl->key+100); - // left side is negative, 8-bit two's complement, this fails for -128 - emitcode ("setb", "F0"); // set sign flag - emitcode ("cpl", "a"); - emitcode ("inc", "a"); + /* now sign adjust for both left & right */ - emitcode ("", "%05d$:", lbl->key+100); + /* let's see what's needed: */ + /* apply negative sign during runtime */ + runtimeSign = FALSE; + /* negative sign from literals */ + compiletimeSign = FALSE; - /* if literal */ - if (AOP_TYPE(right)==AOP_LIT) { - signed char val=floatFromVal (AOP (right)->aopu.aop_lit); - /* AND literal negative */ - if (val < 0) { - emitcode ("cpl", "F0"); // complement sign flag - emitcode ("mov", "b,#0x%02x", -val); - } else { - emitcode ("mov", "b,#0x%02x", val); + if (!lUnsigned) + { + if (AOP_TYPE(left) == AOP_LIT) + { + /* signed literal */ + signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit); + if (val < 0) + compiletimeSign = TRUE; + } + else + /* signed but not literal */ + runtimeSign = TRUE; } - } else { - lbl=newiTempLabel(NULL); - emitcode ("mov", "b,a"); - emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE)); - emitcode ("jnb", "acc.7,%05d$", lbl->key+100); - // right side is negative, 8-bit two's complement - emitcode ("cpl", "F0"); // complement sign flag - emitcode ("cpl", "a"); - emitcode ("inc", "a"); - 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 - emitcode ("cpl", "a"); // lsb - if (size==1) { - emitcode ("inc", "a"); - } else { - emitcode ("add", "a,#1"); - emitcode ("xch", "a,b"); - emitcode ("cpl", "a"); // msb - emitcode ("addc", "a,#0"); - emitcode ("xch", "a,b"); - } - emitcode ("", "%05d$:", lbl->key+100); - aopPut (AOP (result), "a", 0); - if (size==2) { - aopPut (AOP (result), "b", 1); - } + if (!rUnsigned) + { + if (AOP_TYPE(right) == AOP_LIT) + { + /* signed literal */ + signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit); + if (val < 0) + compiletimeSign ^= TRUE; + } + else + /* signed but not literal */ + runtimeSign = TRUE; + } + + /* initialize F0, which stores the runtime sign */ + if (runtimeSign) + { + if (compiletimeSign) + emitcode ("setb", "F0"); /* set sign flag */ + else + emitcode ("clr", "F0"); /* reset sign flag */ + } + + /* save the signs of the operands */ + if (AOP_TYPE(right) == AOP_LIT) + { + signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit); + + if (!rUnsigned && val < 0) + emitcode ("mov", "b,#0x%02x", -val); + else + emitcode ("mov", "b,#0x%02x", (unsigned char) val); + } + else /* ! literal */ + { + if (rUnsigned) /* emitcode (";", "signed"); */ + + emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE)); + else + { + MOVA (aopGet (AOP (right), 0, FALSE, FALSE)); + lbl = newiTempLabel (NULL); + emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100)); + emitcode ("cpl", "F0"); /* complement sign flag */ + emitcode ("cpl", "a"); /* 2's complement */ + emitcode ("inc", "a"); + emitcode ("", "%05d$:", (lbl->key + 100)); + emitcode ("mov", "b,a"); + } + } + + if (AOP_TYPE(left) == AOP_LIT) + { + signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit); + + if (!lUnsigned && val < 0) + emitcode ("mov", "a,#0x%02x", -val); + else + emitcode ("mov", "a,#0x%02x", (unsigned char) val); + } + else /* ! literal */ + { + MOVA (aopGet (AOP (left), 0, FALSE, FALSE)); + + if (!lUnsigned) + { + lbl = newiTempLabel (NULL); + emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100)); + emitcode ("cpl", "F0"); /* complement sign flag */ + emitcode ("cpl", "a"); /* 2's complement */ + emitcode ("inc", "a"); + emitcode ("", "%05d$:", (lbl->key + 100)); + } + } + + /* now the multiplication */ + emitcode ("mul", "ab"); + if (runtimeSign || compiletimeSign) + { + lbl = newiTempLabel (NULL); + if (runtimeSign) + emitcode ("jnb", "F0,%05d$", (lbl->key + 100)); + emitcode ("cpl", "a"); /* lsb 2's complement */ + if (size != 2) + emitcode ("inc", "a"); /* inc doesn't set carry flag */ + else + { + emitcode ("add", "a,#1"); /* this sets carry flag */ + emitcode ("xch", "a,b"); + emitcode ("cpl", "a"); /* msb 2's complement */ + emitcode ("addc", "a,#0"); + emitcode ("xch", "a,b"); + } + emitcode ("", "%05d$:", (lbl->key + 100)); + } + aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE)); + if (size == 2) + aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE)); } /*-----------------------------------------------------------------*/ @@ -3642,7 +4100,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 { @@ -3656,9 +4114,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)); } /*-----------------------------------------------------------------*/ @@ -3682,7 +4140,7 @@ genDivbits (operand * left, emitcode ("div", "ab"); emitcode ("rrc", "a"); - aopPut (AOP (result), "c", 0); + aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE)); } /*-----------------------------------------------------------------*/ @@ -3693,84 +4151,189 @@ genDivOneByte (operand * left, operand * right, operand * result) { - sym_link *opetype = operandType (result); - char *l; + bool lUnsigned, rUnsigned; + bool runtimeSign, compiletimeSign; symbol *lbl; int size, offset; D(emitcode ("; genDivOneByte","")); + /* Why is it necessary that genDivOneByte() can return an int result? + Have a look at: + + volatile unsigned char uc; + volatile signed char sc1, sc2; + volatile int i; + + uc = 255; + sc1 = -1; + i = uc / sc1; + + Or: + + sc1 = -128; + sc2 = -1; + i = sc1 / sc2; + + In all cases a one byte result would overflow, the following cast to int + would return the wrong result. + + Two possible solution: + a) cast operands to int, if ((unsigned) / (signed)) or + ((signed) / (signed)) + b) return an 16 bit signed int; this is what we're doing here! + */ + size = AOP_SIZE (result) - 1; offset = 1; + lUnsigned = SPEC_USIGN (getSpec (operandType (left))); + rUnsigned = SPEC_USIGN (getSpec (operandType (right))); + /* signed or unsigned */ - if (SPEC_USIGN (opetype)) + if (lUnsigned && rUnsigned) { /* unsigned is easy */ emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE)); - l = aopGet (AOP (left), 0, FALSE, FALSE); - MOVA (l); + MOVA (aopGet (AOP (left), 0, FALSE, FALSE)); emitcode ("div", "ab"); - aopPut (AOP (result), "a", 0); + aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE)); while (size--) - aopPut (AOP (result), zero, offset++); + aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE)); return; } - + /* signed is a little bit more difficult */ + /* now sign adjust for both left & right */ + + /* let's see what's needed: */ + /* apply negative sign during runtime */ + runtimeSign = FALSE; + /* negative sign from literals */ + compiletimeSign = FALSE; + + if (!lUnsigned) + { + if (AOP_TYPE(left) == AOP_LIT) + { + /* signed literal */ + signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit); + if (val < 0) + compiletimeSign = TRUE; + } + else + /* signed but not literal */ + runtimeSign = TRUE; + } + + if (!rUnsigned) + { + if (AOP_TYPE(right) == AOP_LIT) + { + /* signed literal */ + signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit); + if (val < 0) + compiletimeSign ^= TRUE; + } + else + /* signed but not literal */ + runtimeSign = TRUE; + } + + /* initialize F0, which stores the runtime sign */ + if (runtimeSign) + { + if (compiletimeSign) + emitcode ("setb", "F0"); /* set sign flag */ + else + emitcode ("clr", "F0"); /* reset sign flag */ + } + /* save the signs of the operands */ - l = aopGet (AOP (left), 0, FALSE, FALSE); - MOVA (l); - emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE)); - emitcode ("push", "acc"); /* save it on the stack */ + if (AOP_TYPE(right) == AOP_LIT) + { + signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit); - /* now sign adjust for both left & right */ - l = aopGet (AOP (right), 0, FALSE, FALSE); - MOVA (l); - lbl = newiTempLabel (NULL); - emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100)); - emitcode ("cpl", "a"); - emitcode ("inc", "a"); - emitcode ("", "%05d$:", (lbl->key + 100)); - emitcode ("mov", "b,a"); + if (!rUnsigned && val < 0) + emitcode ("mov", "b,#0x%02x", -val); + else + emitcode ("mov", "b,#0x%02x", (unsigned char) val); + } + else /* ! literal */ + { + if (rUnsigned) + emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE)); + else + { + MOVA (aopGet (AOP (right), 0, FALSE, FALSE)); + lbl = newiTempLabel (NULL); + emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100)); + emitcode ("cpl", "F0"); /* complement sign flag */ + emitcode ("cpl", "a"); /* 2's complement */ + emitcode ("inc", "a"); + emitcode ("", "%05d$:", (lbl->key + 100)); + emitcode ("mov", "b,a"); + } + } - /* sign adjust left side */ - l = aopGet (AOP (left), 0, FALSE, FALSE); - MOVA (l); + if (AOP_TYPE(left) == AOP_LIT) + { + signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit); - lbl = newiTempLabel (NULL); - emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100)); - emitcode ("cpl", "a"); - emitcode ("inc", "a"); - emitcode ("", "%05d$:", (lbl->key + 100)); + if (!lUnsigned && val < 0) + emitcode ("mov", "a,#0x%02x", -val); + else + emitcode ("mov", "a,#0x%02x", (unsigned char) val); + } + else /* ! literal */ + { + MOVA (aopGet (AOP (left), 0, FALSE, FALSE)); + + if (!lUnsigned) + { + lbl = newiTempLabel (NULL); + emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100)); + emitcode ("cpl", "F0"); /* complement sign flag */ + emitcode ("cpl", "a"); /* 2's complement */ + emitcode ("inc", "a"); + emitcode ("", "%05d$:", (lbl->key + 100)); + } + } /* now the division */ emitcode ("div", "ab"); - /* we are interested in the lower order - only */ - emitcode ("mov", "b,a"); - lbl = newiTempLabel (NULL); - emitcode ("pop", "acc"); - /* if there was an over flow we don't - adjust the sign of the result */ - emitcode ("jb", "ov,%05d$", (lbl->key + 100)); - emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100)); - CLRC; - emitcode ("clr", "a"); - emitcode ("subb", "a,b"); - emitcode ("mov", "b,a"); - emitcode ("", "%05d$:", (lbl->key + 100)); - /* now we are done */ - aopPut (AOP (result), "b", 0); - if (size > 0) + if (runtimeSign || compiletimeSign) { - emitcode ("mov", "c,b.7"); - emitcode ("subb", "a,acc"); - } - while (size--) - aopPut (AOP (result), "a", offset++); + lbl = newiTempLabel (NULL); + if (runtimeSign) + emitcode ("jnb", "F0,%05d$", (lbl->key + 100)); + emitcode ("cpl", "a"); /* lsb 2's complement */ + emitcode ("inc", "a"); + emitcode ("", "%05d$:", (lbl->key + 100)); + aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE)); + if (size > 0) + { + /* msb is 0x00 or 0xff depending on the sign */ + if (runtimeSign) + { + emitcode ("mov", "c,F0"); + emitcode ("subb", "a,acc"); + while (size--) + aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE)); + } + else /* compiletimeSign */ + while (size--) + aopPut (AOP (result), "#0xff", offset++, isOperandVolatile (result, FALSE)); + } + } + else + { + aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE)); + while (size--) + aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE)); + } } /*-----------------------------------------------------------------*/ @@ -3810,8 +4373,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); } @@ -3837,7 +4400,7 @@ genModbits (operand * left, emitcode ("div", "ab"); emitcode ("mov", "a,b"); emitcode ("rrc", "a"); - aopPut (AOP (result), "c", 0); + aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE)); } /*-----------------------------------------------------------------*/ @@ -3848,73 +4411,133 @@ genModOneByte (operand * left, operand * right, operand * result) { - sym_link *opetype = operandType (result); - char *l; + bool lUnsigned, rUnsigned; + bool runtimeSign, compiletimeSign; symbol *lbl; + int size, offset; D(emitcode ("; genModOneByte","")); + size = AOP_SIZE (result) - 1; + offset = 1; + lUnsigned = SPEC_USIGN (getSpec (operandType (left))); + rUnsigned = SPEC_USIGN (getSpec (operandType (right))); + /* signed or unsigned */ - if (SPEC_USIGN (opetype)) + if (lUnsigned && rUnsigned) { /* unsigned is easy */ emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE)); - l = aopGet (AOP (left), 0, FALSE, FALSE); - MOVA (l); + MOVA (aopGet (AOP (left), 0, FALSE, FALSE)); emitcode ("div", "ab"); - aopPut (AOP (result), "b", 0); + aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE)); + while (size--) + aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE)); return; } /* signed is a little bit more difficult */ - /* save the signs of the operands */ - l = aopGet (AOP (left), 0, FALSE, FALSE); - MOVA (l); - - emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE)); - emitcode ("push", "acc"); /* save it on the stack */ - /* now sign adjust for both left & right */ - l = aopGet (AOP (right), 0, FALSE, FALSE); - MOVA (l); - lbl = newiTempLabel (NULL); - emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100)); - emitcode ("cpl", "a"); - emitcode ("inc", "a"); - emitcode ("", "%05d$:", (lbl->key + 100)); - emitcode ("mov", "b,a"); + /* modulus: sign of the right operand has no influence on the result! */ + if (AOP_TYPE(right) == AOP_LIT) + { + signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit); + if (!rUnsigned && val < 0) + emitcode ("mov", "b,#0x%02x", -val); + else + emitcode ("mov", "b,#0x%02x", (unsigned char) val); + } + else /* not literal */ + { + if (rUnsigned) + emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE)); + else + { + MOVA (aopGet (AOP (right), 0, FALSE, FALSE)); + lbl = newiTempLabel (NULL); + emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100)); + emitcode ("cpl", "a"); /* 2's complement */ + emitcode ("inc", "a"); + emitcode ("", "%05d$:", (lbl->key + 100)); + emitcode ("mov", "b,a"); + } + } + + /* let's see what's needed: */ + /* apply negative sign during runtime */ + runtimeSign = FALSE; + /* negative sign from literals */ + compiletimeSign = FALSE; + /* sign adjust left side */ - l = aopGet (AOP (left), 0, FALSE, FALSE); - MOVA (l); + if (AOP_TYPE(left) == AOP_LIT) + { + signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit); - lbl = newiTempLabel (NULL); - emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100)); - emitcode ("cpl", "a"); - emitcode ("inc", "a"); - emitcode ("", "%05d$:", (lbl->key + 100)); + if (!lUnsigned && val < 0) + { + compiletimeSign = TRUE; /* set sign flag */ + emitcode ("mov", "a,#0x%02x", -val); + } + else + emitcode ("mov", "a,#0x%02x", (unsigned char) val); + } + else /* ! literal */ + { + MOVA (aopGet (AOP (left), 0, FALSE, FALSE)); - /* now the multiplication */ - emitcode ("div", "ab"); - /* we are interested in the lower order - only */ - lbl = newiTempLabel (NULL); - emitcode ("pop", "acc"); - /* if there was an over flow we don't - adjust the sign of the result */ - emitcode ("jb", "ov,%05d$", (lbl->key + 100)); - emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100)); - CLRC; - emitcode ("clr", "a"); - emitcode ("subb", "a,b"); - emitcode ("mov", "b,a"); - emitcode ("", "%05d$:", (lbl->key + 100)); + if (!lUnsigned) + { + runtimeSign = TRUE; + emitcode ("clr", "F0"); /* clear sign flag */ - /* now we are done */ - aopPut (AOP (result), "b", 0); + lbl = newiTempLabel (NULL); + emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100)); + emitcode ("setb", "F0"); /* set sign flag */ + emitcode ("cpl", "a"); /* 2's complement */ + emitcode ("inc", "a"); + emitcode ("", "%05d$:", (lbl->key + 100)); + } + } + /* now the modulus */ + emitcode ("div", "ab"); + + if (runtimeSign || compiletimeSign) + { + emitcode ("mov", "a,b"); + lbl = newiTempLabel (NULL); + if (runtimeSign) + emitcode ("jnb", "F0,%05d$", (lbl->key + 100)); + emitcode ("cpl", "a"); /* 2's complement */ + emitcode ("inc", "a"); + emitcode ("", "%05d$:", (lbl->key + 100)); + + aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE)); + if (size > 0) + { + /* msb is 0x00 or 0xff depending on the sign */ + if (runtimeSign) + { + emitcode ("mov", "c,F0"); + emitcode ("subb", "a,acc"); + while (size--) + aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE)); + } + else /* compiletimeSign */ + while (size--) + aopPut (AOP (result), "#0xff", offset++, isOperandVolatile (result, FALSE)); + } + } + else + { + aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE)); + while (size--) + aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE)); + } } /*-----------------------------------------------------------------*/ @@ -3955,8 +4578,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); } @@ -4007,6 +4630,7 @@ genCmp (operand * left, operand * right, { int size, offset = 0; unsigned long lit = 0L; + bool rightInB; D(emitcode ("; genCmp","")); @@ -4064,6 +4688,9 @@ genCmp (operand * left, operand * right, CLRC; while (size--) { + rightInB = aopGetUsesAcc(AOP (right), offset); + if (rightInB) + emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE)); MOVA (aopGet (AOP (left), offset, FALSE, FALSE)); if (sign && size == 0) { @@ -4077,20 +4704,27 @@ genCmp (operand * left, operand * right, } else { - emitcode ("mov", "b,%s", aopGet (AOP (right), offset++, FALSE, FALSE)); + if (!rightInB) + emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE)); emitcode ("xrl", "b,#0x80"); emitcode ("subb", "a,b"); } } else - emitcode ("subb", "a,%s", aopGet (AOP (right), offset++, FALSE, FALSE)); + { + if (rightInB) + emitcode ("subb", "a,b"); + else + emitcode ("subb", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE)); + } + offset++; } } } 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); @@ -4126,7 +4760,8 @@ genCmpGt (iCode * ic, iCode * ifx) letype = getSpec (operandType (left)); retype = getSpec (operandType (right)); - sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype)); + sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) || + (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype)))); /* assign the amsops */ aopOp (left, ic, FALSE); aopOp (right, ic, FALSE); @@ -4155,8 +4790,8 @@ genCmpLt (iCode * ic, iCode * ifx) letype = getSpec (operandType (left)); retype = getSpec (operandType (right)); - sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype)); - + sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) || + (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype)))); /* assign the amsops */ aopOp (left, ic, FALSE); aopOp (right, ic, FALSE); @@ -4181,12 +4816,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); @@ -4210,6 +4847,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))) { @@ -4404,7 +5042,7 @@ genCmpEq (iCode * ic, iCode * ifx) gencjne (left, right, newiTempLabel (NULL)); if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) { - aopPut (AOP (result), "a", 0); + aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE)); goto release; } if (ifx) @@ -4420,8 +5058,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); } @@ -4457,7 +5095,7 @@ hasInc (operand *op, iCode *ic,int osize) sym_link *retype = getSpec (type); iCode *lic = ic->next; int isize ; - + /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */ if (!IS_SYMOP(op)) return NULL; @@ -4468,7 +5106,7 @@ hasInc (operand *op, iCode *ic,int osize) while (lic) { /* if operand of the form op = op + */ if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) && - isOperandEqual(IC_RESULT(lic),op) && + isOperandEqual(IC_RESULT(lic),op) && isOperandLiteral(IC_RIGHT(lic)) && operandLitValue(IC_RIGHT(lic)) == isize) { return lic; @@ -4520,8 +5158,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); } @@ -4562,8 +5200,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); } @@ -4809,6 +5447,8 @@ genAnd (iCode * ic, iCode * ifx) { if (ifx) jmpTrueOrFalse (ifx, tlbl); + else + emitcode ("", "%05d$:", tlbl->key + 100); goto release; } } @@ -4826,12 +5466,14 @@ genAnd (iCode * ic, iCode * ifx) if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF) continue; else if (bytelit == 0) - aopPut (AOP (result), zero, offset); + { + aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE)); + } else if (IS_AOP_PREG (result)) { MOVA (aopGet (AOP (right), offset, FALSE, FALSE)); emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE)); - aopPut (AOP (result), "a", offset); + aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE)); } else emitcode ("anl", "%s,%s", @@ -4848,7 +5490,7 @@ genAnd (iCode * ic, iCode * ifx) if (IS_AOP_PREG (result)) { emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE)); - aopPut (AOP (result), "a", offset); + aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE)); } else @@ -4897,6 +5539,8 @@ genAnd (iCode * ic, iCode * ifx) } else if (ifx) jmpTrueOrFalse (ifx, tlbl); + else + emitcode ("", "%05d$:", tlbl->key + 100); } else { @@ -4910,12 +5554,16 @@ genAnd (iCode * ic, iCode * ifx) { aopPut (AOP (result), aopGet (AOP (left), offset, FALSE, FALSE), - offset); + offset, + isOperandVolatile (result, FALSE)); continue; } else if (bytelit == 0) { - aopPut (AOP (result), zero, offset); + /* dummy read of volatile operand */ + if (isOperandVolatile (left, FALSE)) + MOVA (aopGet (AOP (left), offset, FALSE, FALSE)); + aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE)); continue; } } @@ -4929,14 +5577,14 @@ genAnd (iCode * ic, iCode * ifx) emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE)); } - aopPut (AOP (result), "a", offset); + aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE)); } } } 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); } @@ -5109,12 +5757,18 @@ genOr (iCode * ic, iCode * ifx) if (AOP_TYPE (right) == AOP_LIT) { if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L) - continue; - else if (IS_AOP_PREG (left)) { - MOVA (aopGet (AOP (right), offset, FALSE, FALSE)); + /* dummy read of volatile operand */ + if (isOperandVolatile (left, FALSE)) + MOVA (aopGet (AOP (left), offset, FALSE, FALSE)); + else + continue; + } + else if (IS_AOP_PREG (left)) + { + MOVA (aopGet (AOP (right), offset, FALSE, FALSE)); emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE)); - aopPut (AOP (result), "a", offset); + aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE)); } else emitcode ("orl", "%s,%s", @@ -5131,7 +5785,7 @@ genOr (iCode * ic, iCode * ifx) if (IS_AOP_PREG (left)) { emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE)); - aopPut (AOP (result), "a", offset); + aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE)); } else emitcode ("orl", "%s,a", @@ -5173,6 +5827,8 @@ genOr (iCode * ic, iCode * ifx) } else if (ifx) jmpTrueOrFalse (ifx, tlbl); + else + emitcode ("", "%05d$:", tlbl->key + 100); } else for (; (size--); offset++) @@ -5185,7 +5841,8 @@ genOr (iCode * ic, iCode * ifx) { aopPut (AOP (result), aopGet (AOP (left), offset, FALSE, FALSE), - offset); + offset, + isOperandVolatile (result, FALSE)); continue; } } @@ -5199,13 +5856,13 @@ genOr (iCode * ic, iCode * ifx) emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE)); } - aopPut (AOP (result), "a", offset); + aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE)); } } 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); } @@ -5366,7 +6023,7 @@ genXor (iCode * ic, iCode * ifx) { MOVA (aopGet (AOP (right), offset, FALSE, FALSE)); emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE)); - aopPut (AOP (result), "a", offset); + aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE)); } else emitcode ("xrl", "%s,%s", @@ -5383,7 +6040,7 @@ genXor (iCode * ic, iCode * ifx) if (IS_AOP_PREG (left)) { emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE)); - aopPut (AOP (result), "a", offset); + aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE)); } else emitcode ("xrl", "%s,a", @@ -5445,7 +6102,8 @@ genXor (iCode * ic, iCode * ifx) { aopPut (AOP (result), aopGet (AOP (left), offset, FALSE, FALSE), - offset); + offset, + isOperandVolatile (result, FALSE)); continue; } } @@ -5459,13 +6117,13 @@ genXor (iCode * ic, iCode * ifx) emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE)); } - aopPut (AOP (result), "a", offset); + aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE)); } } 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); } @@ -5547,7 +6205,7 @@ genRRC (iCode * ic) MOVA (l); emitcode ("rrc", "a"); if (AOP_SIZE (result) > 1) - aopPut (AOP (result), "a", offset--); + aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE)); } /* now we need to put the carry into the highest order byte of the result */ @@ -5558,7 +6216,7 @@ genRRC (iCode * ic) } emitcode ("mov", "acc.7,c"); release: - aopPut (AOP (result), "a", AOP_SIZE (result) - 1); + aopPut (AOP (result), "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE)); freeAsmop (left, NULL, ic, TRUE); freeAsmop (result, NULL, ic, TRUE); } @@ -5594,14 +6252,14 @@ genRLC (iCode * ic) } emitcode ("add", "a,acc"); if (AOP_SIZE (result) > 1) - aopPut (AOP (result), "a", offset++); + aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE)); while (size--) { l = aopGet (AOP (left), offset, FALSE, FALSE); MOVA (l); emitcode ("rlc", "a"); if (AOP_SIZE (result) > 1) - aopPut (AOP (result), "a", offset++); + aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE)); } } /* now we need to put the carry into the @@ -5613,7 +6271,7 @@ genRLC (iCode * ic) } emitcode ("mov", "acc.0,c"); release: - aopPut (AOP (result), "a", 0); + aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE)); freeAsmop (left, NULL, ic, TRUE); freeAsmop (result, NULL, ic, TRUE); } @@ -5652,6 +6310,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 */ /*-----------------------------------------------------------------*/ @@ -5790,7 +6508,7 @@ shiftR1Left2Result (operand * left, int offl, AccSRsh (shCount); else AccRsh (shCount); - aopPut (AOP (result), "a", offr); + aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE)); } /*-----------------------------------------------------------------*/ @@ -5805,7 +6523,7 @@ shiftL1Left2Result (operand * left, int offl, MOVA (l); /* shift left accumulator */ AccLsh (shCount); - aopPut (AOP (result), "a", offr); + aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE)); } /*-----------------------------------------------------------------*/ @@ -5823,19 +6541,19 @@ movLeft2Result (operand * left, int offl, if (*l == '@' && (IS_AOP_PREG (result))) { emitcode ("mov", "a,%s", l); - aopPut (AOP (result), "a", offr); + aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE)); } else { if (!sign) - aopPut (AOP (result), l, offr); + aopPut (AOP (result), l, offr, isOperandVolatile (result, FALSE)); else { /* MSB sign in acc.7 ! */ if (getDataSize (left) == offl + 1) { emitcode ("mov", "a,%s", l); - aopPut (AOP (result), "a", offr); + aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE)); } } } @@ -5931,16 +6649,16 @@ AccAXLsh (char *x, int shCount) AccAXRrl1 (x); // BCCCCCCD:D000000B AccAXRrl1 (x); // BBCCCCCC:DD000000 #else - emitcode("rrc","a"); - emitcode("xch","a,%s", x); - emitcode("rrc","a"); - emitcode("mov","c,acc.0"); //<< get correct bit - emitcode("xch","a,%s", x); - - emitcode("rrc","a"); - emitcode("xch","a,%s", x); - emitcode("rrc","a"); - emitcode("xch","a,%s", x); + emitcode("rrc","a"); + emitcode("xch","a,%s", x); + emitcode("rrc","a"); + emitcode("mov","c,acc.0"); //<< get correct bit + emitcode("xch","a,%s", x); + + emitcode("rrc","a"); + emitcode("xch","a,%s", x); + emitcode("rrc","a"); + emitcode("xch","a,%s", x); #endif break; case 7: // a:x <<= 7 @@ -6163,7 +6881,7 @@ shiftL2Left2Result (operand * left, int offl, } /* ax << shCount (x = lsb(result)) */ AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount); - aopPut (AOP (result), "a", offr + MSB16); + aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE)); } @@ -6193,7 +6911,7 @@ shiftR2Left2Result (operand * left, int offl, else AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount); if (getDataSize (result) > 1) - aopPut (AOP (result), "a", offr + MSB16); + aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE)); } /*-----------------------------------------------------------------*/ @@ -6209,7 +6927,7 @@ shiftLLeftOrResult (operand * left, int offl, /* or with result */ emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE)); /* back to result */ - aopPut (AOP (result), "a", offr); + aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE)); } /*-----------------------------------------------------------------*/ @@ -6225,7 +6943,7 @@ shiftRLeftOrResult (operand * left, int offl, /* or with result */ emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE)); /* back to result */ - aopPut (AOP (result), "a", offr); + aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE)); } /*-----------------------------------------------------------------*/ @@ -6263,7 +6981,7 @@ genlshTwo (operand * result, operand * left, int shCount) else movLeft2Result (left, LSB, result, MSB16, 0); } - aopPut (AOP (result), zero, LSB); + aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE)); } /* 1 <= shCount <= 7 */ @@ -6296,7 +7014,7 @@ shiftLLong (operand * left, operand * result, int offr) emitcode ("xch", "a,%s", aopGet (AOP (left), LSB + offr, FALSE, FALSE)); else - aopPut (AOP (result), "a", LSB + offr); + aopPut (AOP (result), "a", LSB + offr, isOperandVolatile (result, FALSE)); } if (size >= MSB16 + offr) @@ -6312,7 +7030,7 @@ shiftLLong (operand * left, operand * result, int offr) emitcode ("xch", "a,%s", aopGet (AOP (left), MSB16 + offr, FALSE, FALSE)); else - aopPut (AOP (result), "a", MSB16 + offr); + aopPut (AOP (result), "a", MSB16 + offr, isOperandVolatile (result, FALSE)); } if (size >= MSB24 + offr) @@ -6328,7 +7046,7 @@ shiftLLong (operand * left, operand * result, int offr) emitcode ("xch", "a,%s", aopGet (AOP (left), MSB24 + offr, FALSE, FALSE)); else - aopPut (AOP (result), "a", MSB24 + offr); + aopPut (AOP (result), "a", MSB24 + offr, isOperandVolatile (result, FALSE)); } if (size > MSB32 + offr) @@ -6339,10 +7057,10 @@ shiftLLong (operand * left, operand * result, int offr) MOVA (l); } emitcode ("rlc", "a"); - aopPut (AOP (result), "a", MSB32 + offr); + aopPut (AOP (result), "a", MSB32 + offr, isOperandVolatile (result, FALSE)); } if (offr != LSB) - aopPut (AOP (result), zero, LSB); + aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE)); } /*-----------------------------------------------------------------*/ @@ -6367,9 +7085,9 @@ genlshFour (operand * result, operand * left, int shCount) shiftL1Left2Result (left, LSB, result, MSB32, shCount); else movLeft2Result (left, LSB, result, MSB32, 0); - aopPut (AOP (result), zero, LSB); - aopPut (AOP (result), zero, MSB16); - aopPut (AOP (result), zero, MSB24); + aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE)); + aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE)); + aopPut (AOP (result), zero, MSB24, isOperandVolatile (result, FALSE)); return; } @@ -6386,8 +7104,8 @@ genlshFour (operand * result, operand * left, int shCount) movLeft2Result (left, MSB16, result, MSB32, 0); movLeft2Result (left, LSB, result, MSB24, 0); } - aopPut (AOP (result), zero, MSB16); - aopPut (AOP (result), zero, LSB); + aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE)); + aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE)); return; } @@ -6410,7 +7128,7 @@ genlshFour (operand * result, operand * left, int shCount) movLeft2Result (left, MSB24, result, MSB32, 0); movLeft2Result (left, MSB16, result, MSB24, 0); movLeft2Result (left, LSB, result, MSB16, 0); - aopPut (AOP (result), zero, LSB); + aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE)); } else if (shCount == 1) shiftLLong (left, result, MSB16); @@ -6419,7 +7137,7 @@ genlshFour (operand * result, operand * left, int shCount) shiftL2Left2Result (left, MSB16, result, MSB24, shCount); shiftL1Left2Result (left, LSB, result, MSB16, shCount); shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount); - aopPut (AOP (result), zero, LSB); + aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE)); } } } @@ -6477,7 +7195,7 @@ genLeftShiftLiteral (operand * left, else if (shCount >= (size * 8)) while (size--) - aopPut (AOP (result), zero, size); + aopPut (AOP (result), zero, size, isOperandVolatile (result, FALSE)); else { switch (size) @@ -6494,7 +7212,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; } @@ -6557,10 +7275,10 @@ genLeftShift (iCode * ic) { emitcode ("mov", "a,%s", l); - aopPut (AOP (result), "a", offset); + aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE)); } else - aopPut (AOP (result), l, offset); + aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE)); offset++; } } @@ -6582,7 +7300,7 @@ genLeftShift (iCode * ic) emitcode ("add", "a,acc"); emitcode ("", "%05d$:", tlbl1->key + 100); emitcode ("djnz", "b,%05d$", tlbl->key + 100); - aopPut (AOP (result), "a", 0); + aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE)); goto release; } @@ -6593,13 +7311,13 @@ genLeftShift (iCode * ic) l = aopGet (AOP (result), offset, FALSE, FALSE); MOVA (l); emitcode ("add", "a,acc"); - aopPut (AOP (result), "a", offset++); + aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE)); while (--size) { l = aopGet (AOP (result), offset, FALSE, FALSE); MOVA (l); emitcode ("rlc", "a"); - aopPut (AOP (result), "a", offset++); + aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE)); } reAdjustPreg (AOP (result)); @@ -6664,7 +7382,7 @@ shiftRLong (operand * left, int offl, } MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE)); - + if (offl==MSB16) { // shift is > 8 if (sign) { @@ -6673,11 +7391,11 @@ shiftRLong (operand * left, int offl, if (isSameRegs) emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE)); else { - aopPut (AOP (result), "a", MSB32); + aopPut (AOP (result), "a", MSB32, isOperandVolatile (result, FALSE)); MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE)); } } else { - aopPut (AOP(result), zero, MSB32); + aopPut (AOP(result), zero, MSB32, isOperandVolatile (result, FALSE)); } } @@ -6692,7 +7410,7 @@ shiftRLong (operand * left, int offl, if (isSameRegs && offl==MSB16) { emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE)); } else { - aopPut (AOP (result), "a", MSB32-offl); + aopPut (AOP (result), "a", MSB32-offl, isOperandVolatile (result, FALSE)); MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE)); } @@ -6700,17 +7418,17 @@ shiftRLong (operand * left, int offl, if (isSameRegs && offl==1) { emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE)); } else { - aopPut (AOP (result), "a", MSB24-offl); + aopPut (AOP (result), "a", MSB24-offl, isOperandVolatile (result, FALSE)); MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE)); } emitcode ("rrc", "a"); - aopPut (AOP (result), "a", MSB16 - offl); + aopPut (AOP (result), "a", MSB16 - offl, isOperandVolatile (result, FALSE)); if (offl == LSB) { MOVA (aopGet (AOP (left), LSB, FALSE, FALSE)); emitcode ("rrc", "a"); - aopPut (AOP (result), "a", LSB); + aopPut (AOP (result), "a", LSB, isOperandVolatile (result, FALSE)); } } @@ -6905,10 +7623,10 @@ genSignedRightShift (iCode * ic) { emitcode ("mov", "a,%s", l); - aopPut (AOP (result), "a", offset); + aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE)); } else - aopPut (AOP (result), l, offset); + aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE)); offset++; } } @@ -6919,7 +7637,7 @@ genSignedRightShift (iCode * ic) size = AOP_SIZE (result); offset = size - 1; - emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE)); + MOVA (aopGet (AOP (left), offset, FALSE, FALSE)); emitcode ("rlc", "a"); emitcode ("mov", "ov,c"); /* if it is only one byte then */ @@ -6933,7 +7651,7 @@ genSignedRightShift (iCode * ic) emitcode ("rrc", "a"); emitcode ("", "%05d$:", tlbl1->key + 100); emitcode ("djnz", "b,%05d$", tlbl->key + 100); - aopPut (AOP (result), "a", 0); + aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE)); goto release; } @@ -6946,7 +7664,7 @@ genSignedRightShift (iCode * ic) l = aopGet (AOP (result), offset, FALSE, FALSE); MOVA (l); emitcode ("rrc", "a"); - aopPut (AOP (result), "a", offset--); + aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE)); } reAdjustPreg (AOP (result)); emitcode ("", "%05d$:", tlbl1->key + 100); @@ -6964,7 +7682,7 @@ static void genRightShift (iCode * ic) { operand *right, *left, *result; - sym_link *retype; + sym_link *letype; int size, offset; char *l; symbol *tlbl, *tlbl1; @@ -6973,9 +7691,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; @@ -7029,10 +7747,10 @@ genRightShift (iCode * ic) { emitcode ("mov", "a,%s", l); - aopPut (AOP (result), "a", offset); + aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE)); } else - aopPut (AOP (result), l, offset); + aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE)); offset++; } } @@ -7053,7 +7771,7 @@ genRightShift (iCode * ic) emitcode ("rrc", "a"); emitcode ("", "%05d$:", tlbl1->key + 100); emitcode ("djnz", "b,%05d$", tlbl->key + 100); - aopPut (AOP (result), "a", 0); + aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE)); goto release; } @@ -7066,7 +7784,7 @@ genRightShift (iCode * ic) l = aopGet (AOP (result), offset, FALSE, FALSE); MOVA (l); emitcode ("rrc", "a"); - aopPut (AOP (result), "a", offset--); + aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE)); } reAdjustPreg (AOP (result)); @@ -7079,116 +7797,137 @@ release: } /*-----------------------------------------------------------------*/ -/* genUnpackBits - generates code for unpacking bits */ +/* emitPtrByteGet - emits code to get a byte into A through a */ +/* pointer register (R0, R1, or DPTR). The */ +/* original value of A can be preserved in B. */ /*-----------------------------------------------------------------*/ static void -genUnpackBits (operand * result, char *rname, int ptype) +emitPtrByteGet (char *rname, int p_type, bool preserveAinB) { - int shCnt; - int rlen = 0; - sym_link *etype; - int offset = 0; - int rsize; - - D(emitcode ("; genUnpackBits","")); - - etype = getSpec (operandType (result)); - rsize = getSize (operandType (result)); - /* read the first byte */ - switch (ptype) + switch (p_type) { - - case POINTER: case IPOINTER: + case POINTER: + if (preserveAinB) + emitcode ("mov", "b,a"); emitcode ("mov", "a,@%s", rname); break; case PPOINTER: + if (preserveAinB) + emitcode ("mov", "b,a"); emitcode ("movx", "a,@%s", rname); break; case FPOINTER: + if (preserveAinB) + emitcode ("mov", "b,a"); emitcode ("movx", "a,@dptr"); break; case CPOINTER: + if (preserveAinB) + emitcode ("mov", "b,a"); emitcode ("clr", "a"); emitcode ("movc", "a,@a+dptr"); break; case GPOINTER: + if (preserveAinB) + { + emitcode ("push", "b"); + emitcode ("push", "acc"); + } emitcode ("lcall", "__gptrget"); + if (preserveAinB) + emitcode ("pop", "b"); break; } +} - rlen = SPEC_BLEN (etype); - - /* if we have bitdisplacement then it fits */ - /* into this byte completely or if length is */ - /* less than a byte */ - if ((shCnt = SPEC_BSTR (etype)) || - (SPEC_BLEN (etype) <= 8)) - { - - /* shift right acc */ - AccRsh (shCnt); - - emitcode ("anl", "a,#0x%02x", - ((unsigned char) -1) >> (8 - SPEC_BLEN (etype))); - aopPut (AOP (result), "a", offset++); - goto finish; - } - - /* bit field did not fit in a byte */ - aopPut (AOP (result), "a", offset++); - - while (1) +/*-----------------------------------------------------------------*/ +/* emitPtrByteSet - emits code to set a byte from src through a */ +/* pointer register (R0, R1, or DPTR). */ +/*-----------------------------------------------------------------*/ +static void +emitPtrByteSet (char *rname, int p_type, char *src) +{ + switch (p_type) { + case IPOINTER: + case POINTER: + if (*src=='@') + { + MOVA (src); + emitcode ("mov", "@%s,a", rname); + } + else + emitcode ("mov", "@%s,%s", rname, src); + break; - switch (ptype) - { - case POINTER: - case IPOINTER: - emitcode ("inc", "%s", rname); - emitcode ("mov", "a,@%s", rname); - break; + case PPOINTER: + MOVA (src); + emitcode ("movx", "@%s,a", rname); + break; - case PPOINTER: - emitcode ("inc", "%s", rname); - emitcode ("movx", "a,@%s", rname); - break; + case FPOINTER: + MOVA (src); + emitcode ("movx", "@dptr,a"); + break; - case FPOINTER: - emitcode ("inc", "dptr"); - emitcode ("movx", "a,@dptr"); - break; + case GPOINTER: + MOVA (src); + emitcode ("lcall", "__gptrput"); + break; + } +} - case CPOINTER: - emitcode ("clr", "a"); - emitcode ("inc", "dptr"); - emitcode ("movc", "a,@a+dptr"); - break; +/*-----------------------------------------------------------------*/ +/* genUnpackBits - generates code for unpacking bits */ +/*-----------------------------------------------------------------*/ +static void +genUnpackBits (operand * result, char *rname, int ptype) +{ + int offset = 0; /* result byte offset */ + int rsize; /* result size */ + int rlen = 0; /* remaining bitfield length */ + sym_link *etype; /* bitfield type information */ + int blen; /* bitfield length */ + int bstr; /* bitfield starting bit within byte */ - case GPOINTER: - emitcode ("inc", "dptr"); - emitcode ("lcall", "__gptrget"); - break; - } + D(emitcode ("; genUnpackBits","")); - rlen -= 8; - /* if we are done */ - if (rlen < 8) - break; + etype = getSpec (operandType (result)); + rsize = getSize (operandType (result)); + blen = SPEC_BLEN (etype); + bstr = SPEC_BSTR (etype); - aopPut (AOP (result), "a", offset++); + /* If the bitfield length is less than a byte */ + if (blen < 8) + { + emitPtrByteGet (rname, ptype, FALSE); + AccRsh (bstr); + emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen)); + aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE)); + goto finish; + } + /* Bit field did not fit in a byte. Copy all + but the partial byte at the end. */ + for (rlen=blen;rlen>=8;rlen-=8) + { + emitPtrByteGet (rname, ptype, FALSE); + aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE)); + if (rlen>8) + emitcode ("inc", "%s", rname); } + /* Handle the partial byte at the end */ if (rlen) { - // emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen)); - AccLsh (8 - rlen); - aopPut (AOP (result), "a", offset++); + emitPtrByteGet (rname, ptype, FALSE); + emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen)); + aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE)); } finish: @@ -7196,9 +7935,8 @@ finish: { rsize -= offset; while (rsize--) - aopPut (AOP (result), zero, offset++); + aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE)); } - return; } @@ -7227,7 +7965,7 @@ genDataPointerGet (operand * left, sprintf (buffer, "(%s + %d)", l + 1, offset); else sprintf (buffer, "%s", l + 1); - aopPut (AOP (result), buffer, offset++); + aopPut (AOP (result), buffer, offset++, isOperandVolatile (result, FALSE)); } freeAsmop (left, NULL, ic, TRUE); @@ -7258,37 +7996,56 @@ genNearPointerGet (operand * left, aopOp (left, ic, FALSE); /* if left is rematerialisable and - result is not bit variable type and + result is not bitfield variable type and the left is pointer to data space i.e lower 128 bytes of space */ if (AOP_TYPE (left) == AOP_IMMD && - !IS_BITVAR (retype) && + !IS_BITFIELD (retype) && DCL_TYPE (ltype) == POINTER) { genDataPointerGet (left, result, ic); 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); /* if bitfield then unpack the bits */ - if (IS_BITVAR (retype)) + if (IS_BITFIELD (retype)) genUnpackBits (result, rname, POINTER); else { @@ -7302,12 +8059,12 @@ genNearPointerGet (operand * left, { emitcode ("mov", "a,@%s", rname); - aopPut (AOP (result), "a", offset); + aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE)); } else { sprintf (buffer, "@%s", rname); - aopPut (AOP (result), buffer, offset); + aopPut (AOP (result), buffer, offset, isOperandVolatile (result, FALSE)); } offset++; if (size || pi) @@ -7319,9 +8076,9 @@ genNearPointerGet (operand * left, if (aop) /* we had to allocate for this iCode */ { if (pi) { /* post increment present */ - aopPut(AOP ( left ),rname,0); + aopPut(AOP ( left ),rname,0, isOperandVolatile (left, FALSE)); } - freeAsmop (NULL, aop, ic, TRUE); + freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE); } else { @@ -7343,8 +8100,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; } @@ -7387,7 +8144,7 @@ genPagedPointerGet (operand * left, aopOp (result, ic, FALSE); /* if bitfield then unpack the bits */ - if (IS_BITVAR (retype)) + if (IS_BITFIELD (retype)) genUnpackBits (result, rname, PPOINTER); else { @@ -7399,7 +8156,7 @@ genPagedPointerGet (operand * left, { emitcode ("movx", "a,@%s", rname); - aopPut (AOP (result), "a", offset); + aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE)); offset++; @@ -7411,7 +8168,7 @@ genPagedPointerGet (operand * left, /* now some housekeeping stuff */ if (aop) /* we had to allocate for this iCode */ { - if (pi) aopPut ( AOP (left), rname, 0); + if (pi) aopPut ( AOP (left), rname, 0, isOperandVolatile (left, FALSE)); freeAsmop (NULL, aop, ic, TRUE); } else @@ -7440,6 +8197,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 */ /*-----------------------------------------------------------------*/ @@ -7453,25 +8270,13 @@ genFarPointerGet (operand * left, D(emitcode ("; genFarPointerGet","")); aopOp (left, ic, FALSE); + loadDptrFromOperand (left, 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 */ + /* so dptr now contains the address */ aopOp (result, ic, FALSE); /* if bit then unpack */ - if (IS_BITVAR (retype)) + if (IS_BITFIELD (retype)) genUnpackBits (result, "dptr", FPOINTER); else { @@ -7481,15 +8286,15 @@ genFarPointerGet (operand * left, while (size--) { emitcode ("movx", "a,@dptr"); - aopPut (AOP (result), "a", offset++); + aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE)); if (size || pi) emitcode ("inc", "dptr"); } } - + if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) { - aopPut ( AOP (left), "dpl", 0); - aopPut ( AOP (left), "dph", 1); + aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE)); + aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE)); pi->generated = 1; } freeAsmop (left, NULL, ic, TRUE); @@ -7509,25 +8314,13 @@ genCodePointerGet (operand * left, D(emitcode ("; genCodePointerGet","")); aopOp (left, ic, FALSE); + loadDptrFromOperand (left, 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 */ + /* so dptr now contains the address */ aopOp (result, ic, FALSE); /* if bit then unpack */ - if (IS_BITVAR (retype)) + if (IS_BITFIELD (retype)) genUnpackBits (result, "dptr", CPOINTER); else { @@ -7540,21 +8333,21 @@ genCodePointerGet (operand * left, { emitcode ("clr", "a"); emitcode ("movc", "a,@a+dptr"); - aopPut (AOP (result), "a", offset++); + aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE)); emitcode ("inc", "dptr"); } else - { + { emitcode ("mov", "a,#0x%02x", offset); emitcode ("movc", "a,@a+dptr"); - aopPut (AOP (result), "a", offset++); + aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE)); } } } if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) { - aopPut ( AOP (left), "dpl", 0); - aopPut ( AOP (left), "dph", 1); + aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE)); + aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE)); pi->generated = 1; } freeAsmop (left, NULL, ic, TRUE); @@ -7574,32 +8367,13 @@ genGenPointerGet (operand * left, D(emitcode ("; genGenPointerGet","")); aopOp (left, ic, FALSE); + loadDptrFromOperand (left, TRUE); - /* 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)); - } - } /* so dptr know contains the address */ aopOp (result, ic, FALSE); /* if bit then unpack */ - if (IS_BITVAR (retype)) + if (IS_BITFIELD (retype)) genUnpackBits (result, "dptr", GPOINTER); else { @@ -7609,15 +8383,15 @@ genGenPointerGet (operand * left, while (size--) { emitcode ("lcall", "__gptrget"); - aopPut (AOP (result), "a", offset++); + aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE)); if (size || pi) emitcode ("inc", "dptr"); } } if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) { - aopPut ( AOP (left), "dpl", 0); - aopPut ( AOP (left), "dph", 1); + aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE)); + aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE)); pi->generated = 1; } freeAsmop (left, NULL, ic, TRUE); @@ -7688,6 +8462,8 @@ genPointerGet (iCode * ic, iCode *pi) } + + /*-----------------------------------------------------------------*/ /* genPackBits - generates code for packed bit storage */ /*-----------------------------------------------------------------*/ @@ -7696,168 +8472,125 @@ genPackBits (sym_link * etype, operand * right, char *rname, int p_type) { - int shCount = 0; - int offset = 0; - int rLen = 0; - int blen, bstr; - char *l; + int offset = 0; /* source byte offset */ + int rlen = 0; /* remaining bitfield length */ + int blen; /* bitfield length */ + int bstr; /* bitfield starting bit within byte */ + int litval; /* source literal value (if AOP_LIT) */ + unsigned char mask; /* bitmask within current byte */ D(emitcode ("; genPackBits","")); blen = SPEC_BLEN (etype); bstr = SPEC_BSTR (etype); - l = aopGet (AOP (right), offset++, FALSE, FALSE); - MOVA (l); - - /* if the bit lenth is less than or */ - /* it exactly fits a byte then */ - if (SPEC_BLEN (etype) <= 8) - { - shCount = SPEC_BSTR (etype); - - /* shift left acc */ - AccLsh (shCount); - - if (SPEC_BLEN (etype) < 8) - { /* if smaller than a byte */ - - - switch (p_type) - { - case POINTER: - emitcode ("mov", "b,a"); - emitcode ("mov", "a,@%s", rname); - break; - - case FPOINTER: - emitcode ("mov", "b,a"); - emitcode ("movx", "a,@dptr"); - break; - - case GPOINTER: - emitcode ("push", "b"); - emitcode ("push", "acc"); - emitcode ("lcall", "__gptrget"); - emitcode ("pop", "b"); - break; - } - - emitcode ("anl", "a,#0x%02x", (unsigned char) - ((unsigned char) (0xFF << (blen + bstr)) | - (unsigned char) (0xFF >> (8 - bstr)))); - emitcode ("orl", "a,b"); - if (p_type == GPOINTER) - emitcode ("pop", "b"); - } - } - - switch (p_type) + /* If the bitfield length is less than a byte */ + if (blen < 8) { - case POINTER: - emitcode ("mov", "@%s,a", rname); - break; + mask = ((unsigned char) (0xFF << (blen + bstr)) | + (unsigned char) (0xFF >> (8 - bstr))); - case FPOINTER: - emitcode ("movx", "@dptr,a"); - break; - - case GPOINTER: - emitcode ("lcall", "__gptrput"); - break; + if (AOP_TYPE (right) == AOP_LIT) + { + /* Case with a bitfield length <8 and literal source + */ + litval = (int) floatFromVal (AOP (right)->aopu.aop_lit); + litval <<= bstr; + litval &= (~mask) & 0xff; + emitPtrByteGet (rname, p_type, FALSE); + if ((mask|litval)!=0xff) + emitcode ("anl","a,#0x%02x", mask); + if (litval) + emitcode ("orl","a,#0x%02x", litval); + } + else + { + if ((blen==1) && (p_type!=GPOINTER)) + { + /* Case with a bitfield length == 1 and no generic pointer + */ + if (AOP_TYPE (right) == AOP_CRY) + emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir); + else + { + MOVA (aopGet (AOP (right), 0, FALSE, FALSE)); + emitcode ("rrc","a"); + } + emitPtrByteGet (rname, p_type, FALSE); + emitcode ("mov","acc.%d,c",bstr); + } + else + { + /* Case with a bitfield length < 8 and arbitrary source + */ + MOVA (aopGet (AOP (right), 0, FALSE, FALSE)); + /* shift and mask source value */ + AccLsh (bstr); + emitcode ("anl", "a,#0x%02x", (~mask) & 0xff); + + /* transfer A to B and get next byte */ + emitPtrByteGet (rname, p_type, TRUE); + + emitcode ("anl", "a,#0x%02x", mask); + emitcode ("orl", "a,b"); + if (p_type == GPOINTER) + emitcode ("pop", "b"); + } + } + + emitPtrByteSet (rname, p_type, "a"); + return; } - /* if we r done */ - if (SPEC_BLEN (etype) <= 8) - return; - - emitcode ("inc", "%s", rname); - rLen = SPEC_BLEN (etype); - - /* now generate for lengths greater than one byte */ - while (1) + /* Bit length is greater than 7 bits. In this case, copy */ + /* all except the partial byte at the end */ + for (rlen=blen;rlen>=8;rlen-=8) { - - l = aopGet (AOP (right), offset++, FALSE, TRUE); - - rLen -= 8; - if (rLen < 8) - break; - - switch (p_type) - { - case POINTER: - if (*l == '@') - { - MOVA (l); - emitcode ("mov", "@%s,a", rname); - } - else - emitcode ("mov", "@%s,%s", rname, l); - break; - - case FPOINTER: - MOVA (l); - emitcode ("movx", "@dptr,a"); - break; - - case GPOINTER: - MOVA (l); - emitcode ("lcall", "__gptrput"); - break; - } - emitcode ("inc", "%s", rname); + emitPtrByteSet (rname, p_type, + aopGet (AOP (right), offset++, FALSE, TRUE) ); + if (rlen>8) + emitcode ("inc", "%s", rname); } - MOVA (l); - - /* last last was not complete */ - if (rLen) + /* If there was a partial byte at the end */ + if (rlen) { - /* save the byte & read byte */ - switch (p_type) - { - case POINTER: - emitcode ("mov", "b,a"); - emitcode ("mov", "a,@%s", rname); - break; + mask = (((unsigned char) -1 << rlen) & 0xff); - case FPOINTER: - emitcode ("mov", "b,a"); - emitcode ("movx", "a,@dptr"); - break; + if (AOP_TYPE (right) == AOP_LIT) + { + /* Case with partial byte and literal source + */ + litval = (int) floatFromVal (AOP (right)->aopu.aop_lit); + litval >>= (blen-rlen); + litval &= (~mask) & 0xff; + emitPtrByteGet (rname, p_type, FALSE); + if ((mask|litval)!=0xff) + emitcode ("anl","a,#0x%02x", mask); + if (litval) + emitcode ("orl","a,#0x%02x", litval); + } + else + { + /* Case with partial byte and arbitrary source + */ + MOVA (aopGet (AOP (right), offset++, FALSE, FALSE)); + emitcode ("anl", "a,#0x%02x", (~mask) & 0xff); - case GPOINTER: - emitcode ("push", "b"); - emitcode ("push", "acc"); - emitcode ("lcall", "__gptrget"); - emitcode ("pop", "b"); - break; - } + /* transfer A to B and get next byte */ + emitPtrByteGet (rname, p_type, TRUE); - emitcode ("anl", "a,#0x%02x", (((unsigned char) -1 << rLen) & 0xff)); - emitcode ("orl", "a,b"); + emitcode ("anl", "a,#0x%02x", mask); + emitcode ("orl", "a,b"); + if (p_type == GPOINTER) + emitcode ("pop", "b"); + } + emitPtrByteSet (rname, p_type, "a"); } - if (p_type == GPOINTER) - emitcode ("pop", "b"); - - switch (p_type) - { +} - case POINTER: - emitcode ("mov", "@%s,a", rname); - break; - case FPOINTER: - emitcode ("movx", "@dptr,a"); - break; - - case GPOINTER: - emitcode ("lcall", "__gptrput"); - break; - } -} /*-----------------------------------------------------------------*/ /* genDataPointerSet - remat pointer to data space */ /*-----------------------------------------------------------------*/ @@ -7920,7 +8653,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))) @@ -7940,6 +8673,7 @@ genNearPointerSet (operand * right, else { // Expected case. + emitcode ("mov", "a%s,%s", rname + 1, rname); rname++; // skip the '@'. } } @@ -7960,10 +8694,10 @@ 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); + if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) + genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER); else { /* we have can just get the values */ @@ -7989,7 +8723,8 @@ genNearPointerSet (operand * right, /* now some housekeeping stuff */ if (aop) /* we had to allocate for this iCode */ { - if (pi) aopPut (AOP (result),rname,0); + if (pi) + aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE)); freeAsmop (NULL, aop, ic, TRUE); } else @@ -8056,8 +8791,8 @@ genPagedPointerSet (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, PPOINTER); + if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) + genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER); else { /* we have can just get the values */ @@ -8081,7 +8816,8 @@ genPagedPointerSet (operand * right, /* now some housekeeping stuff */ if (aop) /* we had to allocate for this iCode */ { - if (pi) aopPut (AOP (result),rname,0); + if (pi) + aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE)); freeAsmop (NULL, aop, ic, TRUE); } else @@ -8124,26 +8860,14 @@ genFarPointerSet (operand * right, D(emitcode ("; genFarPointerSet","")); aopOp (result, ic, FALSE); + loadDptrFromOperand (result, 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)); - } - } /* so dptr know contains the address */ aopOp (right, ic, FALSE); /* if bit then unpack */ - if (IS_BITVAR (retype) || IS_BITVAR (letype)) - genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER); + if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) + genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER); else { size = AOP_SIZE (right); @@ -8159,8 +8883,8 @@ genFarPointerSet (operand * right, } } if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) { - aopPut (AOP(result),"dpl",0); - aopPut (AOP(result),"dph",1); + aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE)); + aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE)); pi->generated=1; } freeAsmop (result, NULL, ic, TRUE); @@ -8181,33 +8905,14 @@ genGenPointerSet (operand * right, D(emitcode ("; genGenPointerSet","")); aopOp (result, ic, FALSE); + loadDptrFromOperand (result, TRUE); - /* 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)); - } - } /* so dptr know contains the address */ aopOp (right, ic, FALSE); /* if bit then unpack */ - if (IS_BITVAR (retype) || IS_BITVAR (letype)) - genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER); + if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) + genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER); else { size = AOP_SIZE (right); @@ -8224,8 +8929,8 @@ genGenPointerSet (operand * right, } if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) { - aopPut (AOP(result),"dpl",0); - aopPut (AOP(result),"dph",1); + aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE)); + aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE)); pi->generated=1; } freeAsmop (result, NULL, ic, TRUE); @@ -8292,7 +8997,7 @@ genPointerSet (iCode * ic, iCode *pi) break; default: - werror (E_INTERNAL_ERROR, __FILE__, __LINE__, + werror (E_INTERNAL_ERROR, __FILE__, __LINE__, "genPointerSet: illegal pointer type"); } @@ -8361,12 +9066,12 @@ genAddrOf (iCode * ic) emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ? ((char) (sym->stack - _G.nRegsSaved)) : ((char) sym->stack)) & 0xff); - aopPut (AOP (IC_RESULT (ic)), "a", 0); + aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE)); } else { /* we can just move _bp */ - aopPut (AOP (IC_RESULT (ic)), "_bp", 0); + aopPut (AOP (IC_RESULT (ic)), "_bp", 0, isOperandVolatile (IC_RESULT (ic), FALSE)); } /* fill the result with zero */ size = AOP_SIZE (IC_RESULT (ic)) - 1; @@ -8374,7 +9079,7 @@ genAddrOf (iCode * ic) offset = 1; while (size--) { - aopPut (AOP (IC_RESULT (ic)), zero, offset++); + aopPut (AOP (IC_RESULT (ic)), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE)); } goto release; @@ -8393,7 +9098,7 @@ genAddrOf (iCode * ic) offset * 8); else sprintf (s, "#%s", sym->rname); - aopPut (AOP (IC_RESULT (ic)), s, offset++); + aopPut (AOP (IC_RESULT (ic)), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE)); } release: @@ -8428,7 +9133,7 @@ genFarFarAssign (operand * result, operand * right, iCode * ic) while (size--) { emitcode ("pop", "acc"); - aopPut (AOP (result), "a", --offset); + aopPut (AOP (result), "a", --offset, isOperandVolatile (result, FALSE)); } freeAsmop (result, NULL, ic, FALSE); @@ -8450,9 +9155,10 @@ genAssign (iCode * ic) right = IC_RIGHT (ic); /* if they are the same */ - if (operandsEqu (result, right)) { + if (operandsEqu (result, right) && + !isOperandVolatile (result, FALSE) && + !isOperandVolatile (right, FALSE)) return; - } aopOp (right, ic, FALSE); @@ -8469,7 +9175,9 @@ genAssign (iCode * ic) aopOp (result, ic, TRUE); /* if they are the same registers */ - if (sameRegs (AOP (right), AOP (result))) + if (sameRegs (AOP (right), AOP (result)) && + !isOperandVolatile (result, FALSE) && + !isOperandVolatile (right, FALSE)) goto release; /* if the result is a bit */ @@ -8481,9 +9189,9 @@ genAssign (iCode * ic) if (AOP_TYPE (right) == AOP_LIT) { if (((int) operandLitValue (right))) - aopPut (AOP (result), one, 0); + aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE)); else - aopPut (AOP (result), zero, 0); + aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE)); goto release; } @@ -8491,13 +9199,13 @@ genAssign (iCode * ic) if (AOP_TYPE (right) == AOP_CRY) { emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir); - aopPut (AOP (result), "c", 0); + aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE)); goto release; } /* we need to or */ toBoolean (right); - aopPut (AOP (result), "a", 0); + aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE)); goto release; } @@ -8517,11 +9225,12 @@ genAssign (iCode * ic) while (size--) { if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0) - aopPut (AOP (result), "a", size); + aopPut (AOP (result), "a", size, isOperandVolatile (result, FALSE)); else aopPut (AOP (result), aopGet (AOP (right), size, FALSE, FALSE), - size); + size, + isOperandVolatile (result, FALSE)); } } else @@ -8530,7 +9239,8 @@ genAssign (iCode * ic) { aopPut (AOP (result), aopGet (AOP (right), offset, FALSE, FALSE), - offset); + offset, + isOperandVolatile (result, FALSE)); offset++; } } @@ -8592,17 +9302,19 @@ genCast (iCode * ic) aopOp (right, ic, FALSE); aopOp (result, ic, FALSE); - /* if the result is a bit */ - if (IS_BITVAR(OP_SYMBOL(result)->type)) + /* if the result is a bit (and not a bitfield) */ + // 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 */ if (AOP_TYPE (right) == AOP_LIT) { if (((int) operandLitValue (right))) - aopPut (AOP (result), one, 0); + aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE)); else - aopPut (AOP (result), zero, 0); + aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE)); goto release; } @@ -8611,16 +9323,17 @@ genCast (iCode * ic) if (AOP_TYPE (right) == AOP_CRY) { emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir); - aopPut (AOP (result), "c", 0); + aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE)); goto release; } /* we need to or */ toBoolean (right); - aopPut (AOP (result), "a", 0); + aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE)); goto release; } + /* if they are the same size : or less */ if (AOP_SIZE (result) <= AOP_SIZE (right)) { @@ -8636,7 +9349,8 @@ genCast (iCode * ic) { aopPut (AOP (result), aopGet (AOP (right), offset, FALSE, FALSE), - offset); + offset, + isOperandVolatile (result, FALSE)); offset++; } goto release; @@ -8674,23 +9388,24 @@ genCast (iCode * ic) { aopPut (AOP (result), aopGet (AOP (right), offset, FALSE, FALSE), - offset); + offset, + isOperandVolatile (result, FALSE)); offset++; } /* the last byte depending on type */ { int gpVal = pointerTypeToGPByte(p_type, NULL, NULL); char gpValStr[10]; - + if (gpVal == -1) { // pointerTypeToGPByte will have bitched. exit(1); } - + sprintf(gpValStr, "#0x%d", gpVal); - aopPut (AOP (result), gpValStr, GPTRSIZE - 1); - } + aopPut (AOP (result), gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE)); + } goto release; } @@ -8701,7 +9416,8 @@ genCast (iCode * ic) { aopPut (AOP (result), aopGet (AOP (right), offset, FALSE, FALSE), - offset); + offset, + isOperandVolatile (result, FALSE)); offset++; } goto release; @@ -8716,7 +9432,8 @@ genCast (iCode * ic) { aopPut (AOP (result), aopGet (AOP (right), offset, FALSE, FALSE), - offset); + offset, + isOperandVolatile (result, FALSE)); offset++; } @@ -8726,7 +9443,7 @@ genCast (iCode * ic) if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY) { while (size--) - aopPut (AOP (result), zero, offset++); + aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE)); } else { @@ -8737,7 +9454,7 @@ genCast (iCode * ic) emitcode ("rlc", "a"); emitcode ("subb", "a,acc"); while (size--) - aopPut (AOP (result), "a", offset++); + aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE)); } /* we are done hurray !!!! */ @@ -8792,7 +9509,7 @@ genDjnz (iCode * ic, iCode * ifx) * it back after the decrement. */ char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE); - + if (strcmp(rByte, "a")) { /* Something is hopelessly wrong */ @@ -8805,14 +9522,14 @@ genDjnz (iCode * ic, iCode * ifx) return 0; } emitcode ("dec", "%s", rByte); - aopPut(AOP(IC_RESULT(ic)), rByte, 0); + aopPut(AOP(IC_RESULT(ic)), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE)); emitcode ("jnz", "%05d$", lbl->key + 100); } else if (IS_AOP_PREG (IC_RESULT (ic))) { emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE)); - emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE)); + MOVA (aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE)); emitcode ("jnz", "%05d$", lbl->key + 100); } else @@ -8844,7 +9561,47 @@ genReceive (iCode * ic) if (isOperandInFarSpace (IC_RESULT (ic)) && (OP_SYMBOL (IC_RESULT (ic))->isspilt || IS_TRUE_SYMOP (IC_RESULT (ic)))) { - + + regs *tempRegs[4]; + int receivingA = 0; + int roffset = 0; + + for (offset = 0; offset0; offset--) + emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]); + emitcode("mov","a,%s", fReturn[0]); + _G.accInUse++; + aopOp (IC_RESULT (ic), ic, FALSE); + _G.accInUse--; + aopPut (AOP (IC_RESULT (ic)), "a", offset, + isOperandVolatile (IC_RESULT (ic), FALSE)); + for (offset = 1; offsetname, offset, + isOperandVolatile (IC_RESULT (ic), FALSE)); + goto release; + } + } + else + { + if (getTempRegs(tempRegs, size, ic)) + { + for (offset = 0; offsetname, fReturn[offset]); + aopOp (IC_RESULT (ic), ic, FALSE); + for (offset = 0; offsetname, offset, + isOperandVolatile (IC_RESULT (ic), FALSE)); + goto release; + } + } + offset = fReturnSizeMCS51 - size; while (size--) { emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ? @@ -8856,9 +9613,9 @@ genReceive (iCode * ic) offset = 0; while (size--) { emitcode ("pop", "acc"); - aopPut (AOP (IC_RESULT (ic)), "a", offset++); + aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE)); } - + } else { _G.accInUse++; aopOp (IC_RESULT (ic), ic, FALSE); @@ -8870,12 +9627,132 @@ genReceive (iCode * ic) aopOp (IC_RESULT (ic), ic, FALSE); rb1off = ic->argreg; while (size--) { - aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++); + aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE)); } } + +release: freeAsmop (IC_RESULT (ic), NULL, ic, TRUE); } +/*-----------------------------------------------------------------*/ +/* genDummyRead - generate code for dummy read of volatiles */ +/*-----------------------------------------------------------------*/ +static void +genDummyRead (iCode * ic) +{ + operand *op; + int size, offset; + + D(emitcode("; genDummyRead","")); + + op = IC_RIGHT (ic); + if (op && IS_SYMOP (op)) + { + 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); + } + + op = IC_LEFT (ic); + if (op && IS_SYMOP (op)) + { + 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); + } +} + +/*-----------------------------------------------------------------*/ +/* 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 */ /*-----------------------------------------------------------------*/ @@ -8884,7 +9761,9 @@ gen51Code (iCode * lic) { iCode *ic; int cln = 0; + /* int cseq = 0; */ + _G.currentFunc = NULL; lineHead = lineCurr = NULL; /* print the allocation information */ @@ -8910,6 +9789,7 @@ gen51Code (iCode * lic) for (ic = lic; ic; ic = ic->next) { + _G.current_iCode = ic; if (ic->lineno && cln != ic->lineno) { @@ -8922,18 +9802,25 @@ gen51Code (iCode * lic) _G.debugLine = 0; } if (!options.noCcodeInAsm) { - emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno, + emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno, printCLine(ic->filename, ic->lineno)); } cln = ic->lineno; } + #if 0 + if (ic->seqPoint && ic->seqPoint != cseq) + { + emitcode ("", "; sequence point %d", ic->seqPoint); + cseq = ic->seqPoint; + } + #endif if (options.iCodeInAsm) { char regsInUse[80]; int i; for (i=0; i<8; i++) { sprintf (®sInUse[i], - "%c", ic->riu & (1<riu & (1<seq, printILine(ic)); @@ -9129,11 +10016,28 @@ gen51Code (iCode * lic) addSet (&_G.sendSet, ic); break; + case DUMMY_READ_VOLATILE: + 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 */