X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Fds390%2Fgen.c;h=1984a2e98ad588c2c92baa2937e666de23a7a7c0;hb=2817542c3072299402d4a58a77541779c1baa1b6;hp=55d1fa292d5844973e58040f0a039a46fdd8cef2;hpb=0dc374981b8fe9fca8eb4add0a8e33c9e0232b59;p=fw%2Fsdcc diff --git a/src/ds390/gen.c b/src/ds390/gen.c index 55d1fa29..1984a2e9 100644 --- a/src/ds390/gen.c +++ b/src/ds390/gen.c @@ -41,13 +41,15 @@ #ifdef HAVE_ENDIAN_H #include #else -#if !defined(__BORLANDC__) && !defined(_MSC_VER) +#if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__) #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN" #warning "If you running sdcc on an INTEL 80x86 Platform you are okay" #endif #endif #endif +#define BETTER_LITERAL_SHIFT + char *aopLiteral (value * val, int offset); /* this is the down and dirty file with all kinds of @@ -62,8 +64,11 @@ static char *spname; #define D(x) x unsigned fReturnSizeDS390 = 5; /* shared with ralloc.c */ -static char *fReturn[] = +static char *fReturn24[] = {"dpl", "dph", "dpx", "b", "a"}; +static char *fReturn16[] = +{"dpl", "dph", "b", "a"}; +static char **fReturn = fReturn24; static char *accUse[] = {"a", "b"}; @@ -81,7 +86,7 @@ static struct } _G; -static void saverbank (int, iCode *, bool); +static void saveRBank (int, iCode *, bool); #define RESULTONSTACK(x) \ (IC_RESULT(x) && IC_RESULT(x)->aop && \ @@ -124,7 +129,7 @@ static void emitcode (char *inst, char *fmt,...) { va_list ap; - char lb[MAX_INLINEASM]; + char lb[INITIAL_INLINEASM]; char *lbp = lb; va_start (ap, fmt); @@ -166,9 +171,9 @@ getFreePtr (iCode * ic, asmop ** aopp, bool result) /* first check if r0 & r1 are used by this instruction, in which case we are in trouble */ - if ((r0iu = bitVectBitValue (ic->rUsed, R0_IDX)) && - (r1iu = bitVectBitValue (ic->rUsed, R1_IDX))) - { + r0iu = bitVectBitValue (ic->rUsed, R0_IDX); + r1iu = bitVectBitValue (ic->rUsed, R1_IDX); + if (r0iu && r1iu) { goto endOfWorld; } @@ -310,7 +315,11 @@ _startLazyDPSEvaluation (void) { _currentDPS = 0; _desiredDPS = 0; +#ifdef BETTER_LITERAL_SHIFT + _lazyDPS++; +#else _lazyDPS = 1; +#endif } /*-----------------------------------------------------------------*/ @@ -349,14 +358,21 @@ _flushLazyDPS (void) static void _endLazyDPSEvaluation (void) { - if (_currentDPS) +#ifdef BETTER_LITERAL_SHIFT + _lazyDPS--; +#else + _lazyDPS = 0; +#endif + if (!_lazyDPS) + { + if (_currentDPS) { genSetDPTR (0); _flushLazyDPS (); } - _lazyDPS = 0; - _currentDPS = 0; - _desiredDPS = 0; + _currentDPS = 0; + _desiredDPS = 0; + } } @@ -443,15 +459,15 @@ aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2) if (useDP2) { - /* genSetDPTR(1); */ - emitcode ("mov", "dpx1,#0x40"); + if (options.model == MODEL_FLAT24) + emitcode ("mov", "dpx1,#0x40"); emitcode ("mov", "dph1,#0x00"); emitcode ("mov", "dpl1, a"); - /* genSetDPTR(0); */ } else { - emitcode ("mov", "dpx,#0x40"); + if (options.model == MODEL_FLAT24) + emitcode ("mov", "dpx,#0x40"); emitcode ("mov", "dph,#0x00"); emitcode ("mov", "dpl, a"); } @@ -1471,8 +1487,9 @@ outBitC (operand * result) static void toBoolean (operand * oper) { - int size = AOP_SIZE (oper) - 1; - int offset = 1; + int size = AOP_SIZE (oper) - 1; + int offset = 1; + bool usedB = FALSE; /* The generic part of a generic pointer should * not participate in it's truth value. @@ -1487,8 +1504,9 @@ toBoolean (operand * oper) } _startLazyDPSEvaluation (); - if (AOP_NEEDSACC (oper)) + if (AOP_NEEDSACC (oper) && size) { + usedB = TRUE; emitcode ("push", "b"); emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE)); } @@ -1498,7 +1516,7 @@ toBoolean (operand * oper) } while (size--) { - if (AOP_NEEDSACC (oper)) + if (usedB) { emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE)); } @@ -1509,7 +1527,7 @@ toBoolean (operand * oper) } _endLazyDPSEvaluation (); - if (AOP_NEEDSACC (oper)) + if (usedB) { emitcode ("mov", "a,b"); emitcode ("pop", "b"); @@ -1745,7 +1763,8 @@ saveRegisters (iCode * lic) /* if the registers have been saved already then do nothing */ - if (ic->regsSaved || (OP_SYMBOL (IC_LEFT (ic))->calleeSave)) + if (ic->regsSaved || (OP_SYMBOL (IC_LEFT (ic))->calleeSave) || + SPEC_NAKED(OP_SYM_ETYPE(IC_LEFT(ic)))) return; /* find the registers in use at this time @@ -1779,18 +1798,12 @@ saveRegisters (iCode * lic) for (i = 0; i < ds390_nRegs; i++) { if (bitVectBitValue (rsave, i)) - emitcode ("push", "%s ;jwk saveRegisters", ds390_regWithIdx (i)->dname); + emitcode ("push", "%s", ds390_regWithIdx (i)->dname); } detype = getSpec (operandType (IC_LEFT (ic))); - if (detype && - (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) && - IS_ISR (currFunc->etype) && - !ic->bankSaved) - - saverbank (SPEC_BANK (detype), ic, TRUE); - } + /*-----------------------------------------------------------------*/ /* unsaveRegisters - pop the pushed registers */ /*-----------------------------------------------------------------*/ @@ -1828,7 +1841,7 @@ unsaveRegisters (iCode * ic) for (i = ds390_nRegs; i >= 0; i--) { if (bitVectBitValue (rsave, i)) - emitcode ("pop", "%s ;jwk unsaveRegisters", ds390_regWithIdx (i)->dname); + emitcode ("pop", "%s", ds390_regWithIdx (i)->dname); } } @@ -1950,7 +1963,7 @@ genIpush (iCode * ic) MOVA (l); l = "acc"; } - emitcode ("push", "%s ;jwk genIpush: !parm", l); + emitcode ("push", "%s", l); } _endLazyDPSEvaluation (); return; @@ -1987,7 +2000,7 @@ genIpush (iCode * ic) emitcode ("push", "acc"); } else - emitcode ("push", "%s ;jwk genIpush", l); + emitcode ("push", "%s", l); } _endLazyDPSEvaluation (); @@ -2016,7 +2029,7 @@ genIpop (iCode * ic) _startLazyDPSEvaluation (); while (size--) { - emitcode ("pop", "%s ;jwk genIpop", aopGet (AOP (IC_LEFT (ic)), offset--, + emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--, FALSE, TRUE, TRUE)); } _endLazyDPSEvaluation (); @@ -2025,31 +2038,42 @@ genIpop (iCode * ic) } /*-----------------------------------------------------------------*/ -/* unsaverbank - restores the resgister bank from stack */ +/* unsaveRBank - restores the resgister bank from stack */ /*-----------------------------------------------------------------*/ static void -unsaverbank (int bank, iCode * ic, bool popPsw) +unsaveRBank (int bank, iCode * ic, bool popPsw) { int i; - asmop *aop; + asmop *aop = NULL; regs *r = NULL; + if (options.useXstack) + { + if (!ic) + { + /* Assume r0 is available for use. */ + r = ds390_regWithIdx (R0_IDX);; + } + else + { + aop = newAsmop (0); + r = getFreePtr (ic, &aop, FALSE); + } + emitcode ("mov", "%s,_spx", r->name); + } + if (popPsw) { if (options.useXstack) - { - aop = newAsmop (0); - r = getFreePtr (ic, &aop, FALSE); - - - emitcode ("mov", "%s,_spx", r->name); + { emitcode ("movx", "a,@%s", r->name); emitcode ("mov", "psw,a"); emitcode ("dec", "%s", r->name); - } else + { emitcode ("pop", "psw"); + } } for (i = (ds390_nRegs - 1); i >= 0; i--) @@ -2069,30 +2093,38 @@ unsaverbank (int bank, iCode * ic, bool popPsw) if (options.useXstack) { - emitcode ("mov", "_spx,%s", r->name); - freeAsmop (NULL, aop, ic, TRUE); - } + + if (aop) + { + freeAsmop (NULL, aop, ic, TRUE); + } } /*-----------------------------------------------------------------*/ -/* saverbank - saves an entire register bank on the stack */ +/* saveRBank - saves an entire register bank on the stack */ /*-----------------------------------------------------------------*/ static void -saverbank (int bank, iCode * ic, bool pushPsw) +saveRBank (int bank, iCode * ic, bool pushPsw) { int i; - asmop *aop; + asmop *aop = NULL; regs *r = NULL; if (options.useXstack) { - - aop = newAsmop (0); - r = getFreePtr (ic, &aop, FALSE); - emitcode ("mov", "%s,_spx", r->name); - + if (!ic) + { + /* Assume r0 is available for use. */ + r = ds390_regWithIdx (R0_IDX);; + } + else + { + aop = newAsmop (0); + r = getFreePtr (ic, &aop, FALSE); + } + emitcode ("mov", "%s,_spx", r->name); } for (i = 0; i < ds390_nRegs; i++) @@ -2117,16 +2149,24 @@ saverbank (int bank, iCode * ic, bool pushPsw) emitcode ("movx", "@%s,a", r->name); emitcode ("inc", "%s", r->name); emitcode ("mov", "_spx,%s", r->name); - freeAsmop (NULL, aop, ic, TRUE); - } else + { emitcode ("push", "psw"); + } emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff); } - ic->bankSaved = 1; - + + if (aop) + { + freeAsmop (NULL, aop, ic, TRUE); + } + + if (ic) + { + ic->bankSaved = 1; + } } /*-----------------------------------------------------------------*/ @@ -2136,26 +2176,40 @@ static void genCall (iCode * ic) { sym_link *detype; + bool restoreBank = FALSE; + bool swapBanks = FALSE; - D (emitcode (";", "genCall "); - ); - - /* if caller saves & we have not saved then */ - if (!ic->regsSaved) - saveRegisters (ic); + D (emitcode (";", "genCall ");); - /* if we are calling a function that is not using + /* if we are calling a not _naked function that is not using the same register bank then we need to save the destination registers on the stack */ detype = getSpec (operandType (IC_LEFT (ic))); - if (detype && + if (detype && !SPEC_NAKED(detype) && (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) && - IS_ISR (currFunc->etype) && - !ic->bankSaved) - - saverbank (SPEC_BANK (detype), ic, TRUE); - + IS_ISR (currFunc->etype)) + { + if (!ic->bankSaved) + { + /* This is unexpected; the bank should have been saved in + * genFunction. + */ + saveRBank (SPEC_BANK (detype), ic, FALSE); + restoreBank = TRUE; + } + swapBanks = TRUE; + } + + /* if caller saves & we have not saved then */ + if (!ic->regsSaved) + saveRegisters (ic); + /* if send set is not empty the assign */ + /* We've saved all the registers we care about; + * therefore, we may clobber any register not used + * in the calling convention (i.e. anything not in + * fReturn. + */ if (_G.sendSet) { iCode *sic; @@ -2165,33 +2219,63 @@ genCall (iCode * ic) { int size, offset = 0; - aopOp (IC_LEFT (sic), sic, FALSE, TRUE); + aopOp (IC_LEFT (sic), sic, FALSE, FALSE); size = AOP_SIZE (IC_LEFT (sic)); _startLazyDPSEvaluation (); while (size--) { - char *l = aopGet (AOP (IC_LEFT (sic)), offset, + char *l = aopGet (AOP(IC_LEFT(sic)), offset, FALSE, FALSE, TRUE); - if (strcmp (l, fReturn[offset])) { - genSetDPTR(0); - _flushLazyDPS(); - emitcode ("mov", "%s,%s ;jwk lazy genCall", - fReturn[offset], - l); - } + if ((AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR) && size) + { + emitcode("mov", "%s,%s", regs390[offset].name, l); + } + else if (strcmp (l, fReturn[offset])) + { + emitcode ("mov", "%s,%s", + fReturn[offset], + l); + } offset++; } _endLazyDPSEvaluation (); + if (AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR) + { + size = AOP_SIZE (IC_LEFT (sic)); + if (size) + { + size--; + } + while (size) + { + size--; + emitcode("mov", "%s,%s", + fReturn[size], regs390[size].name); + } + } freeAsmop (IC_LEFT (sic), NULL, sic, TRUE); } _G.sendSet = NULL; - } + } + + if (swapBanks) + { + emitcode ("mov", "psw,#0x%02x", + ((SPEC_BANK(detype)) << 3) & 0xff); + } + /* make the call */ emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ? OP_SYMBOL (IC_LEFT (ic))->rname : OP_SYMBOL (IC_LEFT (ic))->name)); + if (swapBanks) + { + emitcode ("mov", "psw,#0x%02x", + ((SPEC_BANK(currFunc->etype)) << 3) & 0xff); + } + /* if we need assign a result value */ if ((IS_ITEMP (IC_RESULT (ic)) && (OP_SYMBOL (IC_RESULT (ic))->nRegs || @@ -2204,8 +2288,6 @@ genCall (iCode * ic) int size = getSize (operandType (IC_RESULT (ic))); /* Special case for 1 or 2 byte return in far space. */ - emitcode (";", "Kevin function call abuse #1"); - MOVA (fReturn[0]); if (size > 1) { @@ -2247,18 +2329,15 @@ genCall (iCode * ic) else for (i = 0; i < ic->parmBytes; i++) emitcode ("dec", "%s", spname); - } - /* if register bank was saved then pop them */ - if (ic->bankSaved) - unsaverbank (SPEC_BANK (detype), ic, TRUE); - /* if we hade saved some registers then unsave them */ if (ic->regsSaved && !(OP_SYMBOL (IC_LEFT (ic))->calleeSave)) unsaveRegisters (ic); - + /* if register bank was saved then pop them */ + if (restoreBank) + unsaveRBank (SPEC_BANK (detype), ic, FALSE); } /*-----------------------------------------------------------------*/ @@ -2285,7 +2364,7 @@ genPcall (iCode * ic) if (detype && IS_ISR (currFunc->etype) && (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype))) - saverbank (SPEC_BANK (detype), ic, TRUE); + saveRBank (SPEC_BANK (detype), ic, TRUE); /* push the return address on to the stack */ @@ -2379,7 +2458,7 @@ genPcall (iCode * ic) if (detype && (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype))) - unsaverbank (SPEC_BANK (detype), ic, TRUE); + unsaveRBank (SPEC_BANK (detype), ic, TRUE); /* if we hade saved some registers then unsave them */ @@ -2442,9 +2521,9 @@ genFunction (iCode * ic) { symbol *sym; sym_link *fetype; + bool switchedPSW = FALSE; - D (emitcode (";", "genFunction "); - ); + D (emitcode (";", "genFunction ");); _G.nRegsSaved = 0; /* create the function header */ @@ -2455,6 +2534,12 @@ genFunction (iCode * ic) emitcode ("", "%s:", sym->rname); fetype = getSpec (operandType (IC_LEFT (ic))); + if (SPEC_NAKED(fetype)) + { + emitcode(";", "naked function: no prologue."); + return; + } + /* if critical function then turn interrupts off */ if (SPEC_CRTCL (fetype)) emitcode ("clr", "ea"); @@ -2537,10 +2622,99 @@ genFunction (iCode * ic) else { /* this function has a function call cannot - determines register usage so we will have the + determines register usage so we will have to push the entire bank */ - saverbank (0, ic, FALSE); + saveRBank (0, ic, FALSE); + } + } + else + { + /* This ISR uses a non-zero bank. + * + * We assume that the bank is available for our + * exclusive use. + * + * However, if this ISR calls a function which uses some + * other bank, we must save that bank entirely. + */ + unsigned long banksToSave = 0; + + if (sym->hasFcall) + { + +#define MAX_REGISTER_BANKS 4 + + iCode *i; + int ix; + + for (i = ic; i; i = i->next) + { + if (i->op == ENDFUNCTION) + { + /* we got to the end OK. */ + break; + } + + if (i->op == CALL) + { + sym_link *detype; + + detype = getSpec(operandType (IC_LEFT(i))); + if (detype + && SPEC_BANK(detype) != SPEC_BANK(sym->etype)) + { + /* Mark this bank for saving. */ + if (SPEC_BANK(detype) >= MAX_REGISTER_BANKS) + { + werror(E_NO_SUCH_BANK, SPEC_BANK(detype)); + } + else + { + banksToSave |= (1 << SPEC_BANK(detype)); + } + + /* And note that we don't need to do it in + * genCall. + */ + i->bankSaved = 1; + } + } + if (i->op == PCALL) + { + /* This is a mess; we have no idea what + * register bank the called function might + * use. + * + * The only thing I can think of to do is + * throw a warning and hope. + */ + werror(W_FUNCPTR_IN_USING_ISR); + } + } + + if (banksToSave && options.useXstack) + { + /* 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", + (SPEC_BANK (sym->etype) << 3) & 0x00ff); + switchedPSW = TRUE; + } + + for (ix = 0; ix < MAX_REGISTER_BANKS; ix++) + { + if (banksToSave & (1 << ix)) + { + saveRBank(ix, NULL, FALSE); + } + } } + SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave; } } else @@ -2569,7 +2743,8 @@ genFunction (iCode * ic) } /* set the register bank to the desired value */ - if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype)) + if ((SPEC_BANK (sym->etype) || IS_ISR (sym->etype)) + && !switchedPSW) { emitcode ("push", "psw"); emitcode ("mov", "psw,#0x%02x", (SPEC_BANK (sym->etype) << 3) & 0x00ff); @@ -2632,8 +2807,13 @@ genEndFunction (iCode * ic) { symbol *sym = OP_SYMBOL (IC_LEFT (ic)); - D (emitcode (";", "genEndFunction "); - ); + D (emitcode (";", "genEndFunction ");); + + if (SPEC_NAKED(sym->etype)) + { + emitcode(";", "naked function: no epilogue."); + return; + } if (IS_RENT (sym->etype) || options.stackAuto) { @@ -2668,7 +2848,16 @@ genEndFunction (iCode * ic) /* restore the register bank */ if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype)) - emitcode ("pop", "psw"); + { + if (!SPEC_BANK (sym->etype) || !IS_ISR (sym->etype) + || !options.useXstack) + { + /* Special case of ISR using non-zero bank with useXstack + * is handled below. + */ + emitcode ("pop", "psw"); + } + } if (IS_ISR (sym->etype)) { @@ -2679,7 +2868,6 @@ genEndFunction (iCode * ic) registers :-) */ if (!SPEC_BANK (sym->etype)) { - /* if this function does not call any other function then we can be economical and save only those registers that are used */ @@ -2703,9 +2891,35 @@ genEndFunction (iCode * ic) else { /* this function has a function call cannot - determines register usage so we will have the + determines register usage so we will have to pop the entire bank */ - unsaverbank (0, ic, FALSE); + unsaveRBank (0, ic, FALSE); + } + } + else + { + /* This ISR uses a non-zero bank. + * + * Restore any register banks saved by genFunction + * in reverse order. + */ + unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype); + int ix; + + for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--) + { + if (savedBanks & (1 << ix)) + { + unsaveRBank(ix, NULL, FALSE); + } + } + + if (options.useXstack) + { + /* Restore bank AFTER calling unsaveRBank, + * since it can trash r0. + */ + emitcode ("pop", "psw"); } } @@ -2734,9 +2948,7 @@ genEndFunction (iCode * ic) emitcode ("setb", "ea"); /* if debug then send end of function */ -/* if (options.debug && currFunc) { */ - if (currFunc) - { + if (options.debug && currFunc) { _G.debugLine = 1; emitcode ("", "C$%s$%d$%d$%d ==.", FileBaseName (ic->filename), currFunc->lastLine, @@ -2774,7 +2986,7 @@ genEndFunction (iCode * ic) } /* if debug then send end of function */ - if (currFunc) + if (options.debug && currFunc) { _G.debugLine = 1; emitcode ("", "C$%s$%d$%d$%d ==.", @@ -2826,8 +3038,11 @@ genRet (iCode * ic) } else { + /* Since A is the last element of fReturn, + * is is OK to clobber it in the aopGet. + */ l = aopGet (AOP (IC_LEFT (ic)), offset, - FALSE, FALSE, FALSE); + FALSE, FALSE, TRUE); if (strcmp (fReturn[offset], l)) emitcode ("mov", "%s,%s", fReturn[offset++], l); } @@ -3299,7 +3514,7 @@ genPlus (iCode * ic) _startLazyDPSEvaluation (); while (size--) { - if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC) + if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic))) { MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE)); if (offset == 0) @@ -3311,13 +3526,33 @@ genPlus (iCode * ic) } else { + if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0)) + { + /* right is going to use ACC or we would have taken the + * above branch. + */ + assert(AOP_NEEDSACC(IC_RIGHT(ic))); + D(emitcode(";", "+ AOP_ACC special case.");); + emitcode("xch", "a, %s", DP2_RESULT_REG); + } MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE)); if (offset == 0) - emitcode ("add", "a,%s", - aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE)); + { + if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) + { + emitcode("add", "a, %s", DP2_RESULT_REG); + } + else + { + emitcode ("add", "a,%s", + aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE)); + } + } else + { emitcode ("addc", "a,%s", aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE)); + } } if (!pushResult) { @@ -3496,16 +3731,24 @@ addSign (operand * result, int offset, int sign) int size = (getDataSize (result) - offset); if (size > 0) { + _startLazyDPSEvaluation(); if (sign) { emitcode ("rlc", "a"); emitcode ("subb", "a,acc"); while (size--) + { aopPut (AOP (result), "a", offset++); + } } else + { while (size--) + { aopPut (AOP (result), zero, offset++); + } + } + _endLazyDPSEvaluation(); } } @@ -3517,8 +3760,7 @@ genMinusBits (iCode * ic) { symbol *lbl = newiTempLabel (NULL); - D (emitcode (";", "genMinusBits "); - ); + D (emitcode (";", "genMinusBits ");); if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) { @@ -3604,12 +3846,17 @@ genMinus (iCode * ic) else { /* first add without previous c */ - if (!offset) - emitcode ("add", "a,#0x%02x", - (unsigned int) (lit & 0x0FFL)); - else + if (!offset) { + if (!size && lit==-1) { + emitcode ("dec", "a"); + } else { + emitcode ("add", "a,#0x%02x", + (unsigned int) (lit & 0x0FFL)); + } + } else { emitcode ("addc", "a,#0x%02x", (unsigned int) ((lit >> (offset * 8)) & 0x0FFL)); + } } if (pushResult) @@ -3677,11 +3924,10 @@ genMultOneByte (operand * left, symbol *lbl; int size=AOP_SIZE(result); - emitcode (";",__FUNCTION__); if (size<1 || size>2) { // this should never happen fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", - AOP_SIZE(result), __FUNCTION__, lineno); + AOP_SIZE(result), __FILE__, lineno); exit (1); } @@ -3715,7 +3961,6 @@ genMultOneByte (operand * left, emitcode (";", "signed"); emitcode ("clr", "F0"); // reset sign flag - emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE)); MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE)); lbl=newiTempLabel(NULL); @@ -3726,22 +3971,24 @@ genMultOneByte (operand * left, emitcode ("inc", "a"); emitcode ("", "%05d$:", lbl->key+100); - emitcode ("xch", "a,b"); /* if literal */ if (AOP_TYPE(right)==AOP_LIT) { + signed char val=floatFromVal (AOP (right)->aopu.aop_lit); /* AND literal negative */ - if ((int) floatFromVal (AOP (right)->aopu.aop_lit) < 0) { - // two's complement for literal<0 - emitcode ("xrl", "PSW,#0x20"); // xrl sign flag - emitcode ("cpl", "a"); - emitcode ("inc", "a"); + if ((int) val < 0) { + emitcode ("cpl", "F0"); // complement sign flag + emitcode ("mov", "b,#0x%02x", -val); + } else { + emitcode ("mov", "b,#0x%02x", val); } } else { lbl=newiTempLabel(NULL); + emitcode ("mov", "b,a"); + emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE)); emitcode ("jnb", "acc.7,%05d$", lbl->key+100); // right side is negative, 8-bit two's complement - emitcode ("xrl", "PSW,#0x20"); // xrl sign flag + emitcode ("cpl", "F0"); // complement sign flag emitcode ("cpl", "a"); emitcode ("inc", "a"); emitcode ("", "%05d$:", lbl->key+100); @@ -5110,9 +5357,20 @@ genAnd (iCode * ic, iCode * ifx) emitcode ("setb", "c"); while (sizer--) { - MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE)); - emitcode ("anl", "a,%s", - aopGet (AOP (left), offset, FALSE, FALSE, FALSE)); + if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) { + emitcode ("anl", "a,%s", + aopGet (AOP (right), offset, FALSE, FALSE, FALSE)); + } else { + if (AOP_TYPE(left)==AOP_ACC) { + emitcode("mov", "b,a"); + MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE)); + emitcode("anl", "a,b"); + }else { + MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE)); + emitcode ("anl", "a,%s", + aopGet (AOP (left), offset, FALSE, FALSE, FALSE)); + } + } emitcode ("jnz", "%05d$", tlbl->key + 100); offset++; } @@ -5412,9 +5670,14 @@ genOr (iCode * ic, iCode * ifx) emitcode ("setb", "c"); while (sizer--) { - MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE)); - emitcode ("orl", "a,%s", - aopGet (AOP (left), offset, FALSE, FALSE, FALSE)); + if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) { + emitcode ("orl", "a,%s", + aopGet (AOP (right), offset, FALSE, FALSE, FALSE)); + } else { + MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE)); + emitcode ("orl", "a,%s", + aopGet (AOP (left), offset, FALSE, FALSE, FALSE)); + } emitcode ("jnz", "%05d$", tlbl->key + 100); offset++; } @@ -5686,9 +5949,14 @@ genXor (iCode * ic, iCode * ifx) } else { - MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE)); - emitcode ("xrl", "a,%s", - aopGet (AOP (left), offset, FALSE, FALSE, FALSE)); + if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) { + emitcode ("xrl", "a,%s", + aopGet (AOP (right), offset, FALSE, FALSE, FALSE)); + } else { + MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE)); + emitcode ("xrl", "a,%s", + aopGet (AOP (left), offset, FALSE, FALSE, FALSE)); + } } emitcode ("jnz", "%05d$", tlbl->key + 100); offset++; @@ -5754,14 +6022,14 @@ release: static void genInline (iCode * ic) { - char buffer[MAX_INLINEASM]; - char *bp = buffer; - char *bp1 = buffer; + char *buffer, *bp, *bp1; D (emitcode (";", "genInline "); ); _G.inLine += (!options.asmpeep); + + buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1); strcpy (buffer, IC_INLINE (ic)); /* emit each line as a code */ @@ -6019,8 +6287,7 @@ AccRsh (int shCount) } } -#if 0 -//REMOVE ME!!! +#ifdef BETTER_LITERAL_SHIFT /*-----------------------------------------------------------------*/ /* AccSRsh - signed right shift accumulator by known count */ /*-----------------------------------------------------------------*/ @@ -6058,8 +6325,7 @@ AccSRsh (int shCount) } #endif -#if 0 -//REMOVE ME!!! +#ifdef BETTER_LITERAL_SHIFT /*-----------------------------------------------------------------*/ /* shiftR1Left2Result - shift right one byte from left to result */ /*-----------------------------------------------------------------*/ @@ -6078,8 +6344,7 @@ shiftR1Left2Result (operand * left, int offl, } #endif -#if 0 -//REMOVE ME!!! +#ifdef BETTER_LITERAL_SHIFT /*-----------------------------------------------------------------*/ /* shiftL1Left2Result - shift left one byte from left to result */ /*-----------------------------------------------------------------*/ @@ -6087,17 +6352,14 @@ static void shiftL1Left2Result (operand * left, int offl, operand * result, int offr, int shCount) { - char *l; - l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE); - MOVA (l); + MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE)); /* shift left accumulator */ AccLsh (shCount); aopPut (AOP (result), "a", offr); } #endif -#if 0 -//REMOVE ME!!! +#ifdef BETTER_LITERAL_SHIFT /*-----------------------------------------------------------------*/ /* movLeft2Result - move byte from left to result */ /*-----------------------------------------------------------------*/ @@ -6107,18 +6369,20 @@ movLeft2Result (operand * left, int offl, { char *l; if (!sameRegs (AOP (left), AOP (result)) || (offl != offr)) - { - l = aopGet (AOP (left), offl, FALSE, FALSE, FALSE); + { + l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE); if (*l == '@' && (IS_AOP_PREG (result))) - { + { emitcode ("mov", "a,%s", l); aopPut (AOP (result), "a", offr); - } + } else - { + { if (!sign) + { aopPut (AOP (result), l, offr); + } else { /* MSB sign in acc.7 ! */ @@ -6128,13 +6392,12 @@ movLeft2Result (operand * left, int offl, aopPut (AOP (result), "a", offr); } } - } - } + } + } } #endif -#if 0 -//REMOVE ME!!! +#ifdef BETTER_LITERAL_SHIFT /*-----------------------------------------------------------------*/ /* AccAXRrl1 - right rotate c->a:x->c by 1 */ /*-----------------------------------------------------------------*/ @@ -6148,7 +6411,7 @@ AccAXRrl1 (char *x) } #endif -#if 0 +#ifdef BETTER_LITERAL_SHIFT //REMOVE ME!!! /*-----------------------------------------------------------------*/ /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */ @@ -6163,8 +6426,7 @@ AccAXLrl1 (char *x) } #endif -#if 0 -//REMOVE ME!!! +#ifdef BETTER_LITERAL_SHIFT /*-----------------------------------------------------------------*/ /* AccAXLsh1 - left shift a:x<-0 by 1 */ /*-----------------------------------------------------------------*/ @@ -6178,8 +6440,7 @@ AccAXLsh1 (char *x) } #endif -#if 0 -//REMOVE ME!!! +#ifdef BETTER_LITERAL_SHIFT /*-----------------------------------------------------------------*/ /* AccAXLsh - left shift a:x by known count (0..7) */ /*-----------------------------------------------------------------*/ @@ -6263,7 +6524,7 @@ AccAXLsh (char *x, int shCount) } #endif -#if 0 +#ifdef BETTER_LITERAL_SHIFT //REMOVE ME!!! /*-----------------------------------------------------------------*/ /* AccAXRsh - right shift a:x known count (0..7) */ @@ -6346,8 +6607,7 @@ AccAXRsh (char *x, int shCount) } #endif -#if 0 -//REMOVE ME!!! +#ifdef BETTER_LITERAL_SHIFT /*-----------------------------------------------------------------*/ /* AccAXRshS - right shift signed a:x known count (0..7) */ /*-----------------------------------------------------------------*/ @@ -6449,8 +6709,93 @@ AccAXRshS (char *x, int shCount) } #endif -#if 0 -//REMOVE ME!!! +#ifdef BETTER_LITERAL_SHIFT +static void +_loadLeftIntoAx(char **lsb, + operand *left, + operand *result, + int offl, + int offr) +{ + // Get the initial value from left into a pair of registers. + // MSB must be in A, LSB can be any register. + // + // If the result is held in registers, it is an optimization + // if the LSB can be held in the register which will hold the, + // result LSB since this saves us from having to copy it into + // the result following AccAXLsh. + // + // If the result is addressed indirectly, this is not a gain. + if (AOP_NEEDSACC(result)) + { + char *leftByte; + + _startLazyDPSEvaluation(); + if (AOP_TYPE(left) == AOP_DPTR2) + { + // Get MSB in A. + MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE)); + // get LSB in DP2_RESULT_REG. + leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE); + assert(!strcmp(leftByte, DP2_RESULT_REG)); + } + else + { + // get LSB into DP2_RESULT_REG + leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE); + if (strcmp(leftByte, DP2_RESULT_REG)) + { + emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte); + } + // And MSB in A. + leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE); + assert(strcmp(leftByte, DP2_RESULT_REG)); + MOVA(leftByte); + } + _endLazyDPSEvaluation(); + *lsb = DP2_RESULT_REG; + } + else + { + if (sameRegs (AOP (result), AOP (left)) && + ((offl + MSB16) == offr)) + { + /* don't crash result[offr] */ + MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE)); + emitcode ("xch", "a,%s", + aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE)); + } + else + { + movLeft2Result (left, offl, result, offr, 0); + MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE)); + } + *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE); + assert(strcmp(*lsb,"a")); + } +} + +static void +_storeAxResults(char *lsb, + operand *result, + int offr) +{ + _startLazyDPSEvaluation(); + if (AOP_NEEDSACC(result)) + { + /* We have to explicitly update the result LSB. + */ + emitcode("xch","a,%s", lsb); + aopPut(AOP(result), "a", offr); + emitcode("mov","a,%s", lsb); + } + if (getDataSize (result) > 1) + { + aopPut (AOP (result), "a", offr + MSB16); + } + _endLazyDPSEvaluation(); +} + /*-----------------------------------------------------------------*/ /* shiftL2Left2Result - shift left two bytes from left to result */ /*-----------------------------------------------------------------*/ @@ -6458,26 +6803,17 @@ static void shiftL2Left2Result (operand * left, int offl, operand * result, int offr, int shCount) { - if (sameRegs (AOP (result), AOP (left)) && - ((offl + MSB16) == offr)) - { - /* don't crash result[offr] */ - MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE)); - emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE, FALSE)); - } - else - { - movLeft2Result (left, offl, result, offr, 0); - MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE)); - } - /* ax << shCount (x = lsb(result)) */ - AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount); - aopPut (AOP (result), "a", offr + MSB16); + char *lsb; + + _loadLeftIntoAx(&lsb, left, result, offl, offr); + + AccAXLsh (lsb, shCount); + + _storeAxResults(lsb, result, offr); } #endif -#if 0 -//REMOVE ME!!! +#ifdef BETTER_LITERAL_SHIFT /*-----------------------------------------------------------------*/ /* shiftR2Left2Result - shift right two bytes from left to result */ /*-----------------------------------------------------------------*/ @@ -6486,26 +6822,22 @@ shiftR2Left2Result (operand * left, int offl, operand * result, int offr, int shCount, int sign) { - if (sameRegs (AOP (result), AOP (left)) && - ((offl + MSB16) == offr)) - { - /* don't crash result[offr] */ - MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE)); - emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE, FALSE)); - } - else - { - movLeft2Result (left, offl, result, offr, 0); - MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE)); - } + char *lsb; + + _loadLeftIntoAx(&lsb, left, result, offl, offr); + /* a:x >> shCount (x = lsb(result)) */ if (sign) - AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount); + { + AccAXRshS(lsb, shCount); + } else - AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount); - if (getDataSize (result) > 1) - aopPut (AOP (result), "a", offr + MSB16); -} + { + AccAXRsh(lsb, shCount); + } + + _storeAxResults(lsb, result, offr); +} #endif #if 0 @@ -6546,22 +6878,19 @@ shiftRLeftOrResult (operand * left, int offl, } #endif -#if 0 -//REMOVE ME!!! +#ifdef BETTER_LITERAL_SHIFT /*-----------------------------------------------------------------*/ /* genlshOne - left shift a one byte quantity by known count */ /*-----------------------------------------------------------------*/ static void genlshOne (operand * result, operand * left, int shCount) { - D (emitcode (";", "genlshOne "); - ); + D (emitcode (";", "genlshOne ");); shiftL1Left2Result (left, LSB, result, LSB, shCount); } #endif -#if 0 -//REMOVE ME!!! +#ifdef BETTER_LITERAL_SHIFT /*-----------------------------------------------------------------*/ /* genlshTwo - left shift two bytes by known amount != 0 */ /*-----------------------------------------------------------------*/ @@ -6570,33 +6899,50 @@ genlshTwo (operand * result, operand * left, int shCount) { int size; - D (emitcode (";", "genlshTwo "); - ); + D (emitcode (";", "genlshTwo ");); size = getDataSize (result); /* if shCount >= 8 */ if (shCount >= 8) - { + { shCount -= 8; + _startLazyDPSEvaluation(); + if (size > 1) { if (shCount) + { + _endLazyDPSEvaluation(); shiftL1Left2Result (left, LSB, result, MSB16, shCount); + aopPut (AOP (result), zero, LSB); + } else + { movLeft2Result (left, LSB, result, MSB16, 0); + aopPut (AOP (result), zero, LSB); + _endLazyDPSEvaluation(); + } } - aopPut (AOP (result), zero, LSB); - } + else + { + aopPut (AOP (result), zero, LSB); + _endLazyDPSEvaluation(); + } + } /* 1 <= shCount <= 7 */ else { if (size == 1) + { shiftL1Left2Result (left, LSB, result, LSB, shCount); + } else + { shiftL2Left2Result (left, LSB, result, LSB, shCount); + } } } #endif @@ -6772,12 +7118,11 @@ genlshFour (operand * result, operand * left, int shCount) } #endif -#if 0 -//REMOVE ME!!! +#ifdef BETTER_LITERAL_SHIFT /*-----------------------------------------------------------------*/ /* genLeftShiftLiteral - left shifting by known count */ /*-----------------------------------------------------------------*/ -static void +static bool genLeftShiftLiteral (operand * left, operand * right, operand * result, @@ -6786,16 +7131,44 @@ genLeftShiftLiteral (operand * left, int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit); int size; - D (emitcode (";", "genLeftShiftLiteral (%d)", shCount); - ); + size = getSize (operandType (result)); - freeAsmop (right, NULL, ic, TRUE); + D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size);); - aopOp (left, ic, FALSE, FALSE); - aopOp (result, ic, FALSE, TRUE); + /* We only handle certain easy cases so far. */ + if ((shCount != 0) + && (shCount < (size * 8)) + && (size != 1) + && (size != 2)) + { + D(emitcode (";", "genLeftShiftLiteral wimping out");); + return FALSE; + } - size = getSize (operandType (result)); + freeAsmop (right, NULL, ic, TRUE); + aopOp(left, ic, FALSE, FALSE); + aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR)); + +#if 1 // debug spew + if (IS_SYMOP(left) && OP_SYMBOL(left)->aop) + { + emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left)); + if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc) + { + emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname); + } + } + if (IS_SYMOP(result) && OP_SYMBOL(result)->aop) + { + emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result)); + if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc) + { + emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname); + } + } +#endif + #if VIEW_SIZE emitcode ("; shift left ", "result %d, left %d", size, AOP_SIZE (left)); @@ -6803,18 +7176,25 @@ genLeftShiftLiteral (operand * left, /* I suppose that the left size >= result size */ if (shCount == 0) - { - while (size--) + { + _startLazyDPSEvaluation(); + while (size--) { movLeft2Result (left, size, result, size, 0); } - } - + _endLazyDPSEvaluation(); + } else if (shCount >= (size * 8)) + { + _startLazyDPSEvaluation(); while (size--) + { aopPut (AOP (result), zero, size); + } + _endLazyDPSEvaluation(); + } else - { + { switch (size) { case 1: @@ -6822,17 +7202,21 @@ genLeftShiftLiteral (operand * left, break; case 2: - case 3: /* bug: this is for generic pointers, I bet. */ genlshTwo (result, left, shCount); break; - +#if 0 case 4: genlshFour (result, left, shCount); break; +#endif + default: + fprintf(stderr, "*** ack! mystery literal shift!\n"); + break; } } freeAsmop (left, NULL, ic, TRUE); freeAsmop (result, NULL, ic, TRUE); + return TRUE; } #endif @@ -6855,13 +7239,16 @@ genLeftShift (iCode * ic) aopOp (right, ic, FALSE, FALSE); -#if 0 + +#ifdef BETTER_LITERAL_SHIFT /* if the shift count is known then do it as efficiently as possible */ if (AOP_TYPE (right) == AOP_LIT) { - genLeftShiftLiteral (left, right, result, ic); - return; + if (genLeftShiftLiteral (left, right, result, ic)) + { + return; + } } #endif @@ -6871,8 +7258,20 @@ genLeftShift (iCode * ic) more that 32 bits make no sense anyway, ( the largest size of an object can be only 32 bits ) */ - emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE)); - emitcode ("inc", "b"); + if (AOP_TYPE (right) == AOP_LIT) + { + /* Really should be handled by genLeftShiftLiteral, + * but since I'm too lazy to fix that today, at least we can make + * some small improvement. + */ + emitcode("mov", "b,#0x%02x", + ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1); + } + else + { + emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE)); + emitcode ("inc", "b"); + } freeAsmop (right, NULL, ic, TRUE); aopOp (left, ic, FALSE, FALSE); aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR); @@ -6949,8 +7348,7 @@ release: freeAsmop (result, NULL, ic, TRUE); } -#if 0 -//REMOVE ME!!! +#ifdef BETTER_LITERAL_SHIFT /*-----------------------------------------------------------------*/ /* genrshOne - right shift a one byte quantity by known count */ /*-----------------------------------------------------------------*/ @@ -6958,14 +7356,12 @@ static void genrshOne (operand * result, operand * left, int shCount, int sign) { - D (emitcode (";", "genrshOne"); - ); + D (emitcode (";", "genrshOne");); shiftR1Left2Result (left, LSB, result, LSB, shCount, sign); } #endif -#if 0 -//REMOVE ME!!! +#ifdef BETTER_LITERAL_SHIFT /*-----------------------------------------------------------------*/ /* genrshTwo - right shift two bytes by known amount != 0 */ /*-----------------------------------------------------------------*/ @@ -6973,24 +7369,31 @@ static void genrshTwo (operand * result, operand * left, int shCount, int sign) { - D (emitcode (";", "genrshTwo"); - ); + D (emitcode (";", "genrshTwo");); /* if shCount >= 8 */ if (shCount >= 8) { shCount -= 8; + _startLazyDPSEvaluation(); if (shCount) + { shiftR1Left2Result (left, MSB16, result, LSB, shCount, sign); + } else + { movLeft2Result (left, MSB16, result, LSB, sign); + } addSign (result, MSB16, sign); + _endLazyDPSEvaluation(); } /* 1 <= shCount <= 7 */ else + { shiftR2Left2Result (left, LSB, result, LSB, shCount, sign); + } } #endif @@ -7004,28 +7407,54 @@ static void shiftRLong (operand * left, int offl, operand * result, int sign) { - if (!sign) + int isSameRegs=sameRegs(AOP(left),AOP(result)); + + if (isSameRegs && offl>1) { + // we are in big trouble, but this shouldn't happen + werror(E_INTERNAL_ERROR, __FILE__, __LINE__); + } + + MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE)); + + if (offl==MSB16) { + // shift is > 8 + if (sign) { + emitcode ("rlc", "a"); + emitcode ("subb", "a,acc"); + emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE)); + } else { + aopPut (AOP(result), zero, MSB32); + } + } + + if (!sign) { emitcode ("clr", "c"); - MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE)); - if (sign) + } else { emitcode ("mov", "c,acc.7"); - emitcode ("rrc", "a"); - aopPut (AOP (result), "a", MSB32 - offl); - if (offl == MSB16) - /* add sign of "a" */ - addSign (result, MSB32, sign); + } - MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE)); emitcode ("rrc", "a"); - aopPut (AOP (result), "a", MSB24 - offl); - MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE)); + if (isSameRegs && offl==MSB16) { + emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE)); + } else { + aopPut (AOP (result), "a", MSB32); + MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE)); + } + + emitcode ("rrc", "a"); + if (isSameRegs && offl==1) { + emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE)); + } else { + aopPut (AOP (result), "a", MSB24); + MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE)); + } emitcode ("rrc", "a"); aopPut (AOP (result), "a", MSB16 - offl); if (offl == LSB) { - MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, TRUE)); + MOVA (aopGet (AOP (left), LSB, FALSE, FALSE)); emitcode ("rrc", "a"); aopPut (AOP (result), "a", LSB); } @@ -7105,12 +7534,11 @@ genrshFour (operand * result, operand * left, } #endif -#if 0 -//REMOVE ME!!! +#ifdef BETTER_LITERAL_SHIFT /*-----------------------------------------------------------------*/ /* genRightShiftLiteral - right shifting by known count */ /*-----------------------------------------------------------------*/ -static void +static bool genRightShiftLiteral (operand * left, operand * right, operand * result, @@ -7120,8 +7548,19 @@ genRightShiftLiteral (operand * left, int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit); int size; - D (emitcode (";", "genRightShiftLiteral"); - ); + size = getSize (operandType (result)); + + D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size);); + + /* We only handle certain easy cases so far. */ + if ((shCount != 0) + && (shCount < (size * 8)) + && (size != 1) + && (size != 2)) + { + D(emitcode (";", "genRightShiftLiteral wimping out");); + return FALSE; + } freeAsmop (right, NULL, ic, TRUE); @@ -7133,22 +7572,26 @@ genRightShiftLiteral (operand * left, AOP_SIZE (left)); #endif - size = getDataSize (left); /* test the LEFT size !!! */ /* I suppose that the left size >= result size */ if (shCount == 0) - { + { size = getDataSize (result); + _startLazyDPSEvaluation(); while (size--) + { movLeft2Result (left, size, result, size, 0); - } - + } + _endLazyDPSEvaluation(); + } else if (shCount >= (size * 8)) { if (sign) + { /* get sign in acc.7 */ MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE)); + } addSign (result, LSB, sign); } else @@ -7162,10 +7605,11 @@ genRightShiftLiteral (operand * left, case 2: genrshTwo (result, left, shCount, sign); break; - +#if 0 case 4: genrshFour (result, left, shCount, sign); break; +#endif default: break; } @@ -7173,6 +7617,7 @@ genRightShiftLiteral (operand * left, freeAsmop (left, NULL, ic, TRUE); freeAsmop (result, NULL, ic, TRUE); } + return TRUE; } #endif @@ -7187,8 +7632,7 @@ genSignedRightShift (iCode * ic) char *l; symbol *tlbl, *tlbl1; - D (emitcode (";", "genSignedRightShift "); - ); + D (emitcode (";", "genSignedRightShift ");); /* we do it the hard way put the shift count in b and loop thru preserving the sign */ @@ -7199,11 +7643,13 @@ genSignedRightShift (iCode * ic) aopOp (right, ic, FALSE, FALSE); -#if 0 +#ifdef BETTER_LITERAL_SHIFT if (AOP_TYPE (right) == AOP_LIT) { - genRightShiftLiteral (left, right, result, ic, 1); - return; + if (genRightShiftLiteral (left, right, result, ic, 1)) + { + return; + } } #endif /* shift count is unknown then we have to form @@ -7212,8 +7658,20 @@ genSignedRightShift (iCode * ic) more that 32 bits make no sense anyway, ( the largest size of an object can be only 32 bits ) */ - emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE)); - emitcode ("inc", "b"); + if (AOP_TYPE (right) == AOP_LIT) + { + /* Really should be handled by genRightShiftLiteral, + * but since I'm too lazy to fix that today, at least we can make + * some small improvement. + */ + emitcode("mov", "b,#0x%02x", + ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1); + } + else + { + emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE)); + emitcode ("inc", "b"); + } freeAsmop (right, NULL, ic, TRUE); aopOp (left, ic, FALSE, FALSE); aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR); @@ -7301,8 +7759,7 @@ genRightShift (iCode * ic) char *l; symbol *tlbl, *tlbl1; - D (emitcode (";", "genRightShift "); - ); + D (emitcode (";", "genRightShift ");); /* if signed then we do it the hard way preserve the sign bit moving it inwards */ @@ -7327,13 +7784,15 @@ genRightShift (iCode * ic) aopOp (right, ic, FALSE, FALSE); -#if 0 +#ifdef BETTER_LITERAL_SHIFT /* if the shift count is known then do it as efficiently as possible */ if (AOP_TYPE (right) == AOP_LIT) { - genRightShiftLiteral (left, right, result, ic, 0); - return; + if (genRightShiftLiteral (left, right, result, ic, 0)) + { + return; + } } #endif @@ -7342,9 +7801,21 @@ genRightShift (iCode * ic) only the lower order byte since shifting more that 32 bits make no sense anyway, ( the largest size of an object can be only 32 bits ) */ - - emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE)); - emitcode ("inc", "b"); + + if (AOP_TYPE (right) == AOP_LIT) + { + /* Really should be handled by genRightShiftLiteral, + * but since I'm too lazy to fix that today, at least we can make + * some small improvement. + */ + emitcode("mov", "b,#0x%02x", + ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1); + } + else + { + emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE)); + emitcode ("inc", "b"); + } freeAsmop (right, NULL, ic, TRUE); aopOp (left, ic, FALSE, FALSE); aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR); @@ -7792,7 +8263,8 @@ genFarPointerGet (operand * left, { emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE)); emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE)); - emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE)); + if (options.model == MODEL_FLAT24) + emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE)); } else { @@ -7801,7 +8273,8 @@ genFarPointerGet (operand * left, ); emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE)); emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE)); - emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE)); + if (options.model == MODEL_FLAT24) + emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE)); emitcode ("pop", "dph"); emitcode ("pop", "dpl"); } @@ -7867,7 +8340,8 @@ emitcodePointerGet (operand * left, { emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE)); emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE)); - emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE)); + if (options.model == MODEL_FLAT24) + emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE)); } else { @@ -7876,7 +8350,8 @@ emitcodePointerGet (operand * left, ); emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE)); emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE)); - emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE)); + if (options.model == MODEL_FLAT24) + emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE)); emitcode ("pop", "dph"); emitcode ("pop", "dpl"); } @@ -7946,21 +8421,29 @@ genGenPointerGet (operand * left, l=aopGet(AOP(left),0,FALSE,FALSE,TRUE); genSetDPTR(0); _flushLazyDPS(); - emitcode ("mov", "dpl,%s ;jwk lazy genGenPointerGet", l); + emitcode ("mov", "dpl,%s", l); l=aopGet(AOP(left),1,FALSE,FALSE,TRUE); genSetDPTR(0); _flushLazyDPS(); - emitcode ("mov", "dph,%s ;jwk lazy genGenPointerGet", l); - l=aopGet(AOP(left),2,FALSE,FALSE,TRUE); - genSetDPTR(0); - _flushLazyDPS(); - emitcode ("mov", "dpx,%s ;jwk lazy genGenPointerGet", l); - emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE)); + emitcode ("mov", "dph,%s", l); + if (options.model == MODEL_FLAT24) { + l=aopGet(AOP(left),2,FALSE,FALSE,TRUE); + genSetDPTR(0); + _flushLazyDPS(); + emitcode ("mov", "dpx,%s", l); + emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE)); + } else { + emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE)); + } } else { emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE)); emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE)); - emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE)); - emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE)); + if (options.model == MODEL_FLAT24) { + emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE)); + emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE)); + } else { + emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE)); + } } _endLazyDPSEvaluation (); } @@ -8464,7 +8947,8 @@ genFarPointerSet (operand * right, { emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE)); emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE)); - emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE)); + if (options.model == MODEL_FLAT24) + emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE)); } else { @@ -8473,7 +8957,8 @@ genFarPointerSet (operand * right, ); emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE)); emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE)); - emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE)); + if (options.model == MODEL_FLAT24) + emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE)); emitcode ("pop", "dph"); emitcode ("pop", "dpl"); } @@ -8539,8 +9024,12 @@ genGenPointerSet (operand * right, { /* we need to get it byte by byte */ emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE)); emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE)); - emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE)); - emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE)); + if (options.model == MODEL_FLAT24) { + emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE)); + emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE)); + } else { + emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE)); + } } _endLazyDPSEvaluation (); } @@ -8640,8 +9129,7 @@ genIfx (iCode * ic, iCode * popIc) operand *cond = IC_COND (ic); int isbit = 0; - D (emitcode (";", "genIfx "); - ); + D (emitcode (";", "genIfx ");); aopOp (cond, ic, FALSE, FALSE); @@ -8749,6 +9237,106 @@ release: } +/*-----------------------------------------------------------------*/ +/* genArrayInit - generates code for address of */ +/*-----------------------------------------------------------------*/ +static void +genArrayInit (iCode * ic) +{ + literalList *iLoop; + int ix, count; + int elementSize = 0, eIndex; + unsigned val, lastVal; + sym_link *type; + + D (emitcode (";", "genArrayInit ");); + + aopOp (IC_LEFT(ic), ic, FALSE, FALSE); + + if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD) + { + // Load immediate value into DPTR. + emitcode("mov", "dptr, %s", + aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, TRUE)); + } + else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR) + { + werror (E_INTERNAL_ERROR, __FILE__, __LINE__, + "Unexpected operand to genArrayInit.\n"); + exit(1); + } + + type = operandType(IC_LEFT(ic)); + + if (type && type->next) + { + elementSize = getSize(type->next); + } + else + { + werror (E_INTERNAL_ERROR, __FILE__, __LINE__, + "can't determine element size in genArrayInit.\n"); + exit(1); + } + + iLoop = IC_ARRAYILIST(ic); + lastVal = 0xffff; + + while (iLoop) + { + bool firstpass = TRUE; + + emitcode(";", "store %d x 0x%x to DPTR (element size %d)", + iLoop->count, (int)iLoop->literalValue, elementSize); + + ix = iLoop->count; + + while (ix) + { + symbol *tlbl = NULL; + + count = ix > 256 ? 256 : ix; + + if (count > 1) + { + tlbl = newiTempLabel (NULL); + if (firstpass || (count & 0xff)) + { + emitcode("mov", "b, #0x%x", count & 0xff); + } + + emitcode ("", "%05d$:", tlbl->key + 100); + } + + firstpass = FALSE; + + for (eIndex = 0; eIndex < elementSize; eIndex++) + { + val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff; + if (val != lastVal) + { + emitcode("mov", "a, #0x%x", val); + lastVal = val; + } + + emitcode("movx", "@dptr, a"); + emitcode("inc", "dptr"); + } + + if (count > 1) + { + emitcode("djnz", "b, %05d$", tlbl->key + 100); + } + + ix -= count; + } + + iLoop = iLoop->next; + } + + freeAsmop (IC_LEFT(ic), NULL, ic, TRUE); +} + /*-----------------------------------------------------------------*/ /* genFarFarAssign - assignment when both are in far space */ /*-----------------------------------------------------------------*/ @@ -8757,19 +9345,64 @@ genFarFarAssign (operand * result, operand * right, iCode * ic) { int size = AOP_SIZE (right); int offset = 0; - char *l; - - if (size > 1) - { - /* This is a net loss for size == 1, but a big gain - * otherwise. - */ - D (emitcode (";", "genFarFarAssign (improved)"); - ); + symbol *rSym = NULL; + if (size == 1) + { + /* quick & easy case. */ + D(emitcode(";","genFarFarAssign (1 byte case)");); + MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE)); + freeAsmop (right, NULL, ic, FALSE); + /* now assign DPTR to result */ + _G.accInUse++; + aopOp(result, ic, FALSE, FALSE); + _G.accInUse--; + aopPut(AOP(result), "a", 0); + freeAsmop(result, NULL, ic, FALSE); + return; + } + + /* See if we've got an underlying symbol to abuse. */ + if (IS_SYMOP(result) && OP_SYMBOL(result)) + { + if (IS_TRUE_SYMOP(result)) + { + rSym = OP_SYMBOL(result); + } + else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc) + { + rSym = OP_SYMBOL(result)->usl.spillLoc; + } + } + + if (size > 1 && rSym && rSym->rname && !rSym->onStack) + { + /* We can use the '390 auto-toggle feature to good effect here. */ + + D(emitcode(";","genFarFarAssign (390 auto-toggle fun)");); + emitcode("mov", "dps, #0x21"); /* Select DPTR2 & auto-toggle. */ + emitcode ("mov", "dptr,#%s", rSym->rname); + /* DP2 = result, DP1 = right, DP1 is current. */ + while (size) + { + emitcode("movx", "a,@dptr"); + emitcode("movx", "@dptr,a"); + if (--size) + { + emitcode("inc", "dptr"); + emitcode("inc", "dptr"); + } + } + emitcode("mov", "dps, #0"); + freeAsmop (right, NULL, ic, FALSE); + } + else + { + D (emitcode (";", "genFarFarAssign");); aopOp (result, ic, TRUE, TRUE); _startLazyDPSEvaluation (); + while (size--) { aopPut (AOP (result), @@ -8779,33 +9412,7 @@ genFarFarAssign (operand * result, operand * right, iCode * ic) _endLazyDPSEvaluation (); freeAsmop (result, NULL, ic, FALSE); freeAsmop (right, NULL, ic, FALSE); - } - else - { - D (emitcode (";", "genFarFarAssign "); - ); - - /* first push the right side on to the stack */ - _startLazyDPSEvaluation (); - while (size--) - { - l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE); - MOVA (l); - emitcode ("push", "acc"); - } - - freeAsmop (right, NULL, ic, FALSE); - /* now assign DPTR to result */ - aopOp (result, ic, FALSE, FALSE); - size = AOP_SIZE (result); - while (size--) - { - emitcode ("pop", "acc"); - aopPut (AOP (result), "a", --offset); - } - freeAsmop (result, NULL, ic, FALSE); - _endLazyDPSEvaluation (); - } + } } /*-----------------------------------------------------------------*/ @@ -8891,8 +9498,6 @@ genAssign (iCode * ic) (AOP_TYPE (right) == AOP_LIT) && !IS_FLOAT (operandType (right))) { - D (emitcode (";", "Kevin's better literal load code"); - ); _startLazyDPSEvaluation (); while (size && ((unsigned int) (lit >> (offset * 8)) != 0)) { @@ -9241,9 +9846,21 @@ genDjnz (iCode * ic, iCode * ifx) * the accumulator, we must explicitly write * it back after the decrement. */ - emitcode ("dec", "%s", - aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, FALSE)); - aopPut(AOP(IC_RESULT(ic)), "acc", 0); + char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE); + + if (strcmp(rByte, "a")) + { + /* Something is hopelessly wrong */ + fprintf(stderr, "*** warning: internal error at %s:%d\n", + __FILE__, __LINE__); + /* We can just give up; the generated code will be inefficient, + * but what the hey. + */ + freeAsmop (IC_RESULT (ic), NULL, ic, TRUE); + return 0; + } + emitcode ("dec", "%s", rByte); + aopPut(AOP(IC_RESULT(ic)), rByte, 0); emitcode ("jnz", "%05d$", lbl->key + 100); } else if (IS_AOP_PREG (IC_RESULT (ic))) @@ -9322,6 +9939,14 @@ gen390Code (iCode * lic) lineHead = lineCurr = NULL; + if (options.model == MODEL_FLAT24) { + fReturnSizeDS390 = 5; + fReturn = fReturn24; + } else { + fReturnSizeDS390 = 4; + fReturn = fReturn16; + options.stack10bit=0; + } #if 0 //REMOVE ME!!! /* print the allocation information */ @@ -9553,6 +10178,10 @@ gen390Code (iCode * lic) addSet (&_G.sendSet, ic); break; + case ARRAYINIT: + genArrayInit(ic); + break; + default: ic = ic; }