X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Fmcs51%2Fgen.c;h=0e6d7091fd9a75b274eefdaf66445b93c43ebc8e;hb=91dd45a032c32b5925c0b8c6898423e3a980d6ba;hp=a305f416540e9a2bc6072ad6e6a4e6cb2da2a737;hpb=c797f99fa696d884316f1162a8d29e6b57b5f102;p=fw%2Fsdcc diff --git a/src/mcs51/gen.c b/src/mcs51/gen.c index a305f416..0e6d7091 100644 --- a/src/mcs51/gen.c +++ b/src/mcs51/gen.c @@ -28,6 +28,9 @@ Made everything static -------------------------------------------------------------------------*/ +#define D(x) +//#define D(x) x + #include #include #include @@ -38,15 +41,19 @@ #ifdef HAVE_SYS_ISA_DEFS_H #include #else +#ifdef HAVE_MACHINE_ENDIAN_H +#include +#else #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 +#endif #include "common.h" #include "SDCCpeeph.h" @@ -89,7 +96,7 @@ _G; extern int mcs51_ptrRegReq; extern int mcs51_nRegs; extern FILE *codeOutFile; -static void saverbank (int, iCode *, bool); +static void saveRBank (int, iCode *, bool); #define RESULTONSTACK(x) \ (IC_RESULT(x) && IC_RESULT(x)->aop && \ IC_RESULT(x)->aop->type == AOP_STK ) @@ -120,7 +127,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); @@ -162,9 +169,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; } @@ -233,11 +240,10 @@ endOfWorld: return NULL; } - piCode (ic, stdout); /* other wise this is true end of the world */ werror (E_INTERNAL_ERROR, __FILE__, __LINE__, "getFreePtr should never reach here"); - exit (0); + exit (1); } /*-----------------------------------------------------------------*/ @@ -253,21 +259,6 @@ newAsmop (short type) return aop; } -static void -genSetDPTR (int n) -{ - if (!n) - { - emitcode (";", "Select standard DPTR"); - emitcode ("mov", "dps, #0x00"); - } - else - { - emitcode (";", "Select alternate DPTR"); - emitcode ("mov", "dps, #0x01"); - } -} - /*-----------------------------------------------------------------*/ /* pointerCode - returns the code for a pointer type */ /*-----------------------------------------------------------------*/ @@ -286,7 +277,12 @@ static asmop * aopForSym (iCode * ic, symbol * sym, bool result) { asmop *aop; - memmap *space = SPEC_OCLS (sym->etype); + memmap *space; + + wassertl (ic != NULL, "Got a null iCode"); + wassertl (sym != NULL, "Got a null symbol"); + + space = SPEC_OCLS (sym->etype); /* if already has one */ if (sym->aop) @@ -386,9 +382,9 @@ aopForRemat (symbol * sym) for (;;) { if (ic->op == '+') - val += operandLitValue (IC_RIGHT (ic)); + val += (int) operandLitValue (IC_RIGHT (ic)); else if (ic->op == '-') - val -= operandLitValue (IC_RIGHT (ic)); + val -= (int) operandLitValue (IC_RIGHT (ic)); else break; @@ -568,7 +564,6 @@ aopOp (operand * op, iCode * ic, bool result) sym = OP_SYMBOL (op); - /* if the type is a conditional */ if (sym->regType == REG_CND) { @@ -604,7 +599,8 @@ aopOp (operand * op, iCode * ic, bool result) if (sym->ruonly) { - int i; + unsigned i; + aop = op->aop = sym->aop = newAsmop (AOP_STR); aop->size = getSize (sym->type); for (i = 0; i < fReturnSizeMCS51; i++) @@ -780,13 +776,6 @@ aopGet (asmop * aop, int offset, bool bit16, bool dname) return rs; case AOP_DPTR: - case AOP_DPTR2: - - if (aop->type == AOP_DPTR2) - { - genSetDPTR (1); - } - while (offset > aop->coff) { emitcode ("inc", "dptr"); @@ -809,12 +798,6 @@ aopGet (asmop * aop, int offset, bool bit16, bool dname) { emitcode ("movx", "a,@dptr"); } - - if (aop->type == AOP_DPTR2) - { - genSetDPTR (0); - } - return (dname ? "acc" : "a"); @@ -875,7 +858,7 @@ aopGet (asmop * aop, int offset, bool bit16, bool dname) werror (E_INTERNAL_ERROR, __FILE__, __LINE__, "aopget got unsupported aop->type"); - exit (0); + exit (1); } /*-----------------------------------------------------------------*/ /* aopPut - puts a string for a aop */ @@ -884,13 +867,12 @@ static void aopPut (asmop * aop, char *s, int offset) { char *d = buffer; - symbol *lbl; if (aop->size && offset > (aop->size - 1)) { werror (E_INTERNAL_ERROR, __FILE__, __LINE__, "aopPut got offset > aop->size"); - exit (0); + exit (1); } /* will assign value to value */ @@ -931,18 +913,11 @@ aopPut (asmop * aop, char *s, int offset) break; case AOP_DPTR: - case AOP_DPTR2: - - if (aop->type == AOP_DPTR2) - { - genSetDPTR (1); - } - if (aop->code) { werror (E_INTERNAL_ERROR, __FILE__, __LINE__, "aopPut writting to code space"); - exit (0); + exit (1); } while (offset > aop->coff) @@ -963,11 +938,6 @@ aopPut (asmop * aop, char *s, int offset) MOVA (s); emitcode ("movx", "@dptr,a"); - - if (aop->type == AOP_DPTR2) - { - genSetDPTR (0); - } break; case AOP_R0: @@ -1039,17 +1009,18 @@ aopPut (asmop * aop, char *s, int offset) emitcode ("mov", "%s,c", aop->aopu.aop_dir); else { - lbl = newiTempLabel (NULL); - if (strcmp (s, "a")) { MOVA (s); } - emitcode ("clr", "c"); - emitcode ("jz", "%05d$", lbl->key + 100); - emitcode ("cpl", "c"); - emitcode ("", "%05d$:", lbl->key + 100); - emitcode ("mov", "%s,c", aop->aopu.aop_dir); + { + symbol *lbl = newiTempLabel (NULL); + emitcode ("clr", "c"); + emitcode ("jz", "%05d$", lbl->key + 100); + emitcode ("cpl", "c"); + emitcode ("", "%05d$:", lbl->key + 100); + emitcode ("mov", "%s,c", aop->aopu.aop_dir); + } } } break; @@ -1072,7 +1043,7 @@ aopPut (asmop * aop, char *s, int offset) default: werror (E_INTERNAL_ERROR, __FILE__, __LINE__, "aopPut got unsupported aop->type"); - exit (0); + exit (1); } } @@ -1112,38 +1083,24 @@ pointToEnd (asmop * aop) static void reAdjustPreg (asmop * aop) { - int size; - - aop->coff = 0; - if ((size = aop->size) <= 1) + if ((aop->coff==0) || aop->size <= 1) return; - size--; + switch (aop->type) { case AOP_R0: case AOP_R1: - while (size--) + while (aop->coff--) emitcode ("dec", "%s", aop->aopu.aop_ptr->name); break; case AOP_DPTR: - case AOP_DPTR2: - if (aop->type == AOP_DPTR2) - { - genSetDPTR (1); - } - while (size--) + while (aop->coff--) { emitcode ("lcall", "__decdptr"); } - - if (aop->type == AOP_DPTR2) - { - genSetDPTR (0); - } break; - } - + aop->coff = 0; } #define AOP(op) op->aop @@ -1153,8 +1110,7 @@ reAdjustPreg (asmop * aop) AOP_TYPE(x) == AOP_R0)) #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \ - AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \ - AOP(x)->paged)) + AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged)) #define AOP_INPREG(x) (x && (x->type == AOP_REG && \ (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \ @@ -1185,7 +1141,6 @@ genNotFloat (operand * op, operand * res) aopGet (op->aop, offset++, FALSE, FALSE)); } - tlbl = newiTempLabel (NULL); tlbl = newiTempLabel (NULL); aopPut (res->aop, one, 1); @@ -1487,7 +1442,6 @@ saveRegisters (iCode * lic) int i; iCode *ic; bitVect *rsave; - sym_link *detype; /* look for call */ for (ic = lic; ic; ic = ic->next) @@ -1500,9 +1454,10 @@ saveRegisters (iCode * lic) return; } - /* if the registers have been saved already then + /* if the registers have been saved already or don't need to be then do nothing */ - if (ic->regsSaved || (OP_SYMBOL (IC_LEFT (ic))->calleeSave)) + if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) || + IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))) return; /* find the registers in use at this time @@ -1538,16 +1493,8 @@ saveRegisters (iCode * lic) if (bitVectBitValue (rsave, i)) emitcode ("push", "%s", mcs51_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 */ /*-----------------------------------------------------------------*/ @@ -1673,6 +1620,7 @@ genIpush (iCode * ic) int size, offset = 0; char *l; + D(emitcode (";", "genIpush")); /* if this is not a parm push : ie. it is spill push and spill push is always done on the local stack */ @@ -1760,31 +1708,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 = mcs51_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 = (mcs51_nRegs - 1); i >= 0; i--) @@ -1804,30 +1763,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); + if (!ic) + { + /* Assume r0 is available for use. */ + r = mcs51_regWithIdx (R0_IDX);; + } + else + { + aop = newAsmop (0); + r = getFreePtr (ic, &aop, FALSE); + } emitcode ("mov", "%s,_spx", r->name); - } for (i = 0; i < mcs51_nRegs; i++) @@ -1852,16 +1819,25 @@ 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; + } } /*-----------------------------------------------------------------*/ @@ -1870,23 +1846,11 @@ saverbank (int bank, iCode * ic, bool pushPsw) static void genCall (iCode * ic) { - sym_link *detype; - - /* if caller saves & we have not saved then */ - if (!ic->regsSaved) - saveRegisters (ic); - - /* if we are calling a 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 && - (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) && - IS_ISR (currFunc->etype) && - !ic->bankSaved) - - saverbank (SPEC_BANK (detype), ic, TRUE); + sym_link *dtype; + bool restoreBank = FALSE; + bool swapBanks = FALSE; + D(emitcode(";", "genCall")); /* if send set is not empty the assign */ if (_G.sendSet) { @@ -1912,11 +1876,47 @@ genCall (iCode * ic) } _G.sendSet = NULL; } + + /* 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 */ + dtype = operandType (IC_LEFT (ic)); + if (dtype && !IFFUNC_ISNAKED(dtype) && + (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) && + IFFUNC_ISISR (currFunc->type)) + { + if (!ic->bankSaved) + { + /* This is unexpected; the bank should have been saved in + * genFunction. + */ + saveRBank (FUNC_REGBANK (dtype), ic, FALSE); + restoreBank = TRUE; + } + swapBanks = TRUE; + } + + /* if caller saves & we have not saved then */ + if (!ic->regsSaved) + saveRegisters (ic); + + if (swapBanks) + { + emitcode ("mov", "psw,#0x%02x", + ((FUNC_REGBANK(dtype)) << 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", + ((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 || @@ -1947,18 +1947,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)) + if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype)) unsaveRegisters (ic); - + /* if register bank was saved then pop them */ + if (restoreBank) + unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE); } /*-----------------------------------------------------------------*/ @@ -1967,7 +1964,7 @@ genCall (iCode * ic) static void genPcall (iCode * ic) { - sym_link *detype; + sym_link *dtype; symbol *rlbl = newiTempLabel (NULL); @@ -1978,11 +1975,11 @@ genPcall (iCode * ic) /* if we are calling a 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 && - IS_ISR (currFunc->etype) && - (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype))) - saverbank (SPEC_BANK (detype), ic, TRUE); + dtype = operandType (IC_LEFT (ic)); + if (dtype && + IFFUNC_ISISR (currFunc->type) && + (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) + saveRBank (FUNC_REGBANK (dtype), ic, TRUE); /* push the return address on to the stack */ @@ -2062,16 +2059,15 @@ genPcall (iCode * ic) } /* if register bank was saved then unsave them */ - if (detype && - (SPEC_BANK (currFunc->etype) != - SPEC_BANK (detype))) - unsaverbank (SPEC_BANK (detype), ic, TRUE); + if (dtype && + (FUNC_REGBANK (currFunc->type) != + FUNC_REGBANK (dtype))) + unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE); /* if we hade saved some registers then unsave them */ if (ic->regsSaved) unsaveRegisters (ic); - } /*-----------------------------------------------------------------*/ @@ -2127,7 +2123,8 @@ static void genFunction (iCode * ic) { symbol *sym; - sym_link *fetype; + sym_link *ftype; + bool switchedPSW = FALSE; _G.nRegsSaved = 0; /* create the function header */ @@ -2136,19 +2133,25 @@ genFunction (iCode * ic) emitcode (";", "-----------------------------------------"); emitcode ("", "%s:", sym->rname); - fetype = getSpec (operandType (IC_LEFT (ic))); + ftype = operandType (IC_LEFT (ic)); + + if (IFFUNC_ISNAKED(ftype)) + { + emitcode(";", "naked function: no prologue."); + return; + } /* if critical function then turn interrupts off */ - if (SPEC_CRTCL (fetype)) + if (IFFUNC_ISCRITICAL (ftype)) emitcode ("clr", "ea"); /* here we need to generate the equates for the register bank if required */ - if (SPEC_BANK (fetype) != rbank) + if (FUNC_REGBANK (ftype) != rbank) { int i; - rbank = SPEC_BANK (fetype); + rbank = FUNC_REGBANK (ftype); for (i = 0; i < mcs51_nRegs; i++) { if (strcmp (regs8051[i].base, "0") == 0) @@ -2165,7 +2168,7 @@ genFunction (iCode * ic) /* if this is an interrupt service routine then save acc, b, dpl, dph */ - if (IS_ISR (sym->etype)) + if (IFFUNC_ISISR (sym->type)) { if (!inExcludeList ("acc")) @@ -2179,13 +2182,13 @@ genFunction (iCode * ic) /* if this isr has no bank i.e. is going to run with bank 0 , then we need to save more registers :-) */ - if (!SPEC_BANK (sym->etype)) + if (!FUNC_REGBANK (sym->type)) { /* if this function does not call any other function then we can be economical and save only those registers that are used */ - if (!sym->hasFcall) + if (!IFFUNC_HASFCALL(sym->type)) { int i; @@ -2205,17 +2208,107 @@ 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 (IFFUNC_HASFCALL(sym->type)) + { + +#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 *dtype; + + dtype = operandType (IC_LEFT(i)); + if (dtype + && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type)) + { + /* Mark this bank for saving. */ + if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS) + { + werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype)); + } + else + { + banksToSave |= (1 << FUNC_REGBANK(dtype)); + } + + /* 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", + (FUNC_REGBANK (sym->type) << 3) & 0x00ff); + switchedPSW = TRUE; + } + + for (ix = 0; ix < MAX_REGISTER_BANKS; ix++) + { + if (banksToSave & (1 << ix)) + { + saveRBank(ix, NULL, FALSE); + } + } } + // jwk: this needs a closer look + SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave; } } else { /* if callee-save to be used for this function then save the registers being used in this function */ - if (sym->calleeSave) + if (IFFUNC_CALLEESAVES(sym->type)) { int i; @@ -2237,13 +2330,14 @@ genFunction (iCode * ic) } /* set the register bank to the desired value */ - if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype)) + if ((FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type)) + && !switchedPSW) { emitcode ("push", "psw"); - emitcode ("mov", "psw,#0x%02x", (SPEC_BANK (sym->etype) << 3) & 0x00ff); + emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff); } - if (IS_RENT (sym->etype) || options.stackAuto) + if (IFFUNC_ISREENT (sym->type) || options.stackAuto) { if (options.useXstack) @@ -2300,7 +2394,13 @@ genEndFunction (iCode * ic) { symbol *sym = OP_SYMBOL (IC_LEFT (ic)); - if (IS_RENT (sym->etype) || options.stackAuto) + if (IFFUNC_ISNAKED(sym->type)) + { + emitcode(";", "naked function: no epilogue."); + return; + } + + if (IFFUNC_ISREENT (sym->type) || options.stackAuto) { emitcode ("mov", "%s,_bp", spname); } @@ -2316,7 +2416,7 @@ genEndFunction (iCode * ic) } - if ((IS_RENT (sym->etype) || options.stackAuto)) + if ((IFFUNC_ISREENT (sym->type) || options.stackAuto)) { if (options.useXstack) { @@ -2332,23 +2432,31 @@ genEndFunction (iCode * ic) } /* restore the register bank */ - if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype)) - emitcode ("pop", "psw"); + if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type)) + { + if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type) + || !options.useXstack) + { + /* Special case of ISR using non-zero bank with useXstack + * is handled below. + */ + emitcode ("pop", "psw"); + } + } - if (IS_ISR (sym->etype)) + if (IFFUNC_ISISR (sym->type)) { /* now we need to restore the registers */ /* if this isr has no bank i.e. is going to run with bank 0 , then we need to save more registers :-) */ - if (!SPEC_BANK (sym->etype)) + if (!FUNC_REGBANK (sym->type)) { - /* if this function does not call any other function then we can be economical and save only those registers that are used */ - if (!sym->hasFcall) + if (!IFFUNC_HASFCALL(sym->type)) { int i; @@ -2368,9 +2476,36 @@ 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. + */ + // jwk: this needs a closer look + 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"); } } @@ -2383,12 +2518,12 @@ genEndFunction (iCode * ic) if (!inExcludeList ("acc")) emitcode ("pop", "acc"); - if (SPEC_CRTCL (sym->etype)) + if (IFFUNC_ISCRITICAL (sym->type)) emitcode ("setb", "ea"); /* if debug then send end of function */ -/* if (options.debug && currFunc) { */ - if (currFunc) + /* if (options.debug && currFunc) */ + if (options.debug && currFunc) { _G.debugLine = 1; emitcode ("", "C$%s$%d$%d$%d ==.", @@ -2405,10 +2540,10 @@ genEndFunction (iCode * ic) } else { - if (SPEC_CRTCL (sym->etype)) + if (IFFUNC_ISCRITICAL (sym->type)) emitcode ("setb", "ea"); - if (sym->calleeSave) + if (IFFUNC_CALLEESAVES(sym->type)) { int i; @@ -2427,7 +2562,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 ==.", @@ -2571,7 +2706,7 @@ genPlusIncr (iCode * ic) /* if the literal value of the right hand side is greater than 4 then it is not worth it */ - if ((icount = floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4) + if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4) return FALSE; /* if increment 16 bits in register */ @@ -3118,12 +3253,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)); + } } aopPut (AOP (IC_RESULT (ic)), "a", offset++); } @@ -3152,7 +3292,7 @@ genMultbits (operand * left, /*-----------------------------------------------------------------*/ -/* genMultOneByte : 8 bit multiplication & division */ +/* genMultOneByte : 8*8=8/16 bit multiplication */ /*-----------------------------------------------------------------*/ static void genMultOneByte (operand * left, @@ -3160,89 +3300,99 @@ genMultOneByte (operand * left, operand * result) { sym_link *opetype = operandType (result); - char *l; symbol *lbl; - int size, offset; + int size=AOP_SIZE(result); + + 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 two literals: the value is computed before) */ /* if one literal, literal on the right */ if (AOP_TYPE (left) == AOP_LIT) { 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"); + 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); } + return; + } - size = AOP_SIZE (result); - /* signed or unsigned */ - emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE)); - l = aopGet (AOP (left), 0, FALSE, FALSE); - MOVA (l); - emitcode ("mul", "ab"); - /* if result size = 1, mul signed = mul unsigned */ - aopPut (AOP (result), "a", 0); - if (size > 1) - { - if (SPEC_USIGN (opetype)) - { - aopPut (AOP (result), "b", 1); - if (size > 2) - /* for filling the MSBs */ - emitcode ("clr", "a"); - } - else - { - emitcode ("mov", "a,b"); + // we have to do a signed multiply - /* adjust the MSB if left or right neg */ + //emitcode (";", "signed"); + emitcode ("clr", "F0"); // reset sign flag + MOVA (aopGet (AOP (left), 0, FALSE, FALSE)); - /* if one literal */ - if (AOP_TYPE (right) == AOP_LIT) - { - /* AND literal negative */ - if ((int) floatFromVal (AOP (right)->aopu.aop_lit) < 0) - { - /* adjust MSB (c==0 after mul) */ - emitcode ("subb", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE)); - } - } - else - { - lbl = newiTempLabel (NULL); - emitcode ("xch", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE)); - emitcode ("cjne", "a,#0x80,%05d$", (lbl->key + 100)); - emitcode ("", "%05d$:", (lbl->key + 100)); - emitcode ("xch", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE)); - lbl = newiTempLabel (NULL); - emitcode ("jc", "%05d$", (lbl->key + 100)); - emitcode ("subb", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE)); - emitcode ("", "%05d$:", (lbl->key + 100)); - } + 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"); - lbl = newiTempLabel (NULL); - emitcode ("xch", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE)); - emitcode ("cjne", "a,#0x80,%05d$", (lbl->key + 100)); - emitcode ("", "%05d$:", (lbl->key + 100)); - emitcode ("xch", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE)); - lbl = newiTempLabel (NULL); - emitcode ("jc", "%05d$", (lbl->key + 100)); - emitcode ("subb", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE)); - emitcode ("", "%05d$:", (lbl->key + 100)); + emitcode ("", "%05d$:", lbl->key+100); + + /* 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); + } + } 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"); + } - aopPut (AOP (result), "a", 1); - if (size > 2) - { - /* get the sign */ - emitcode ("rlc", "a"); - emitcode ("subb", "a,acc"); - } - } - size -= 2; - offset = 2; - if (size > 0) - while (size--) - aopPut (AOP (result), "a", offset++); - } + emitcode ("", "%05d$:", lbl->key+100); + aopPut (AOP (result), "a", 0); + if (size==2) { + aopPut (AOP (result), "b", 1); + } } /*-----------------------------------------------------------------*/ @@ -3278,7 +3428,7 @@ genMult (iCode * ic) } /* should have been converted to function call */ - assert (1); + assert (0); release: freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); @@ -3427,7 +3577,7 @@ genDiv (iCode * ic) } /* should have been converted to function call */ - assert (1); + assert (0); release: freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); @@ -3565,7 +3715,7 @@ genMod (iCode * ic) } /* should have been converted to function call */ - assert (1); + assert (0); release: freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); @@ -3614,7 +3764,7 @@ genIfxJump (iCode * ic, char *jval) /*-----------------------------------------------------------------*/ static void genCmp (operand * left, operand * right, - operand * result, iCode * ifx, int sign) + operand * result, iCode * ifx, int sign, iCode *ic) { int size, offset = 0; unsigned long lit = 0L; @@ -3698,6 +3848,8 @@ genCmp (operand * left, operand * right, } release: + freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); + freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) { outBitC (result); @@ -3737,10 +3889,8 @@ genCmpGt (iCode * ic, iCode * ifx) aopOp (right, ic, FALSE); aopOp (result, ic, TRUE); - genCmp (right, left, result, ifx, sign); + genCmp (right, left, result, ifx, sign,ic); - freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); - freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); freeAsmop (result, NULL, ic, TRUE); } @@ -3767,10 +3917,8 @@ genCmpLt (iCode * ic, iCode * ifx) aopOp (right, ic, FALSE); aopOp (result, ic, TRUE); - genCmp (left, right, result, ifx, sign); + genCmp (left, right, result, ifx, sign,ic); - freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); - freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); freeAsmop (result, NULL, ic, TRUE); } @@ -4049,6 +4197,40 @@ ifxForOp (operand * op, iCode * ic) return NULL; } + +/*-----------------------------------------------------------------*/ +/* hasInc - operand is incremented before any other use */ +/*-----------------------------------------------------------------*/ +static iCode * +hasInc (operand *op, iCode *ic) +{ + sym_link *type = operandType(op); + 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; + + if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL; + isize = getSize(type->next); + while (lic) { + /* if operand of the form op = op + */ + if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) && + isOperandEqual(IC_RESULT(lic),op) && + isOperandLiteral(IC_RIGHT(lic)) && + operandLitValue(IC_RIGHT(lic)) == isize) { + return lic; + } + /* if the operand used or deffed */ + if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) { + return NULL; + } + lic = lic->next; + } + return NULL; +} + /*-----------------------------------------------------------------*/ /* genAndOp - for && operation */ /*-----------------------------------------------------------------*/ @@ -4431,9 +4613,20 @@ genAnd (iCode * ic, iCode * ifx) emitcode ("setb", "c"); while (sizer--) { - MOVA (aopGet (AOP (right), offset, FALSE, FALSE)); - emitcode ("anl", "a,%s", - aopGet (AOP (left), offset, FALSE, FALSE)); + if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) { + emitcode ("anl", "a,%s", + aopGet (AOP (right), offset, FALSE, FALSE)); + } else { + if (AOP_TYPE(left)==AOP_ACC) { + emitcode("mov", "b,a"); + MOVA (aopGet (AOP (right), offset, FALSE, FALSE)); + emitcode("anl", "a,b"); + }else { + MOVA (aopGet (AOP (right), offset, FALSE, FALSE)); + emitcode ("anl", "a,%s", + aopGet (AOP (left), offset, FALSE, FALSE)); + } + } emitcode ("jnz", "%05d$", tlbl->key + 100); offset++; } @@ -4700,9 +4893,14 @@ genOr (iCode * ic, iCode * ifx) emitcode ("setb", "c"); while (sizer--) { - MOVA (aopGet (AOP (right), offset, FALSE, FALSE)); - emitcode ("orl", "a,%s", - aopGet (AOP (left), offset, FALSE, FALSE)); + if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) { + emitcode ("orl", "a,%s", + aopGet (AOP (right), offset, FALSE, FALSE)); + } else { + MOVA (aopGet (AOP (right), offset, FALSE, FALSE)); + emitcode ("orl", "a,%s", + aopGet (AOP (left), offset, FALSE, FALSE)); + } emitcode ("jnz", "%05d$", tlbl->key + 100); offset++; } @@ -4952,9 +5150,14 @@ genXor (iCode * ic, iCode * ifx) } else { - MOVA (aopGet (AOP (right), offset, FALSE, FALSE)); - emitcode ("xrl", "a,%s", - aopGet (AOP (left), offset, FALSE, FALSE)); + if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) { + emitcode ("xrl", "a,%s", + aopGet (AOP (right), offset, FALSE, FALSE)); + } else { + MOVA (aopGet (AOP (right), offset, FALSE, FALSE)); + emitcode ("xrl", "a,%s", + aopGet (AOP (left), offset, FALSE, FALSE)); + } } emitcode ("jnz", "%05d$", tlbl->key + 100); offset++; @@ -5009,11 +5212,11 @@ release: static void genInline (iCode * ic) { - char buffer[MAX_INLINEASM]; - char *bp = buffer; - char *bp1 = buffer; + char *buffer, *bp, *bp1; _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 */ @@ -5064,6 +5267,12 @@ genRRC (iCode * ic) /* move it to the result */ size = AOP_SIZE (result); offset = size - 1; + if (size == 1) { /* special case for 1 byte */ + l = aopGet (AOP (left), offset, FALSE, FALSE); + MOVA (l); + emitcode ("rr", "a"); + goto release; + } CLRC; while (size--) { @@ -5081,6 +5290,7 @@ genRRC (iCode * ic) MOVA (l); } emitcode ("mov", "acc.7,c"); + release: aopPut (AOP (result), "a", AOP_SIZE (result) - 1); freeAsmop (left, NULL, ic, TRUE); freeAsmop (result, NULL, ic, TRUE); @@ -5109,6 +5319,10 @@ genRLC (iCode * ic) { l = aopGet (AOP (left), offset, FALSE, FALSE); MOVA (l); + if (size == 0) { /* special case for 1 byte */ + emitcode("rl","a"); + goto release; + } emitcode ("add", "a,acc"); if (AOP_SIZE (result) > 1) aopPut (AOP (result), "a", offset++); @@ -5129,6 +5343,7 @@ genRLC (iCode * ic) MOVA (l); } emitcode ("mov", "acc.0,c"); + release: aopPut (AOP (result), "a", 0); freeAsmop (left, NULL, ic, TRUE); freeAsmop (result, NULL, ic, TRUE); @@ -5440,7 +5655,7 @@ AccAXLsh (char *x, int shCount) SRMask[shCount]); // 000000BB:CCCCCCDD emitcode ("mov", "c,acc.0"); // c = B emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB -#if 0 +#if 0 // REMOVE ME AccAXRrl1 (x); // BCCCCCCD:D000000B AccAXRrl1 (x); // BBCCCCCC:DD000000 #else @@ -5874,7 +6089,7 @@ genlshFour (operand * result, operand * left, int shCount) movLeft2Result (left, LSB, result, MSB32, 0); aopPut (AOP (result), zero, LSB); aopPut (AOP (result), zero, MSB16); - aopPut (AOP (result), zero, MSB32); + aopPut (AOP (result), zero, MSB24); return; } @@ -5990,13 +6205,15 @@ genLeftShiftLiteral (operand * left, break; case 2: - case 3: genlshTwo (result, left, shCount); break; case 4: genlshFour (result, left, shCount); break; + default: + fprintf(stderr, "*** ack! mystery literal shift!\n"); + break; } } freeAsmop (left, NULL, ic, TRUE); @@ -6150,22 +6367,48 @@ static void shiftRLong (operand * left, int offl, operand * result, int sign) { - if (!sign) - emitcode ("clr", "c"); + 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 (sign) + + 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"); + } 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)); emitcode ("rrc", "a"); - aopPut (AOP (result), "a", MSB24 - offl); - MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE)); + 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); @@ -6566,7 +6809,7 @@ genUnpackBits (operand * result, char *rname, int ptype) case CPOINTER: emitcode ("clr", "a"); - emitcode ("movc", "a,%s", "@a+dptr"); + emitcode ("movc", "a,@a+dptr"); break; case GPOINTER: @@ -6619,7 +6862,7 @@ genUnpackBits (operand * result, char *rname, int ptype) case CPOINTER: emitcode ("clr", "a"); emitcode ("inc", "dptr"); - emitcode ("movc", "a", "@a+dptr"); + emitcode ("movc", "a,@a+dptr"); break; case GPOINTER: @@ -6690,7 +6933,8 @@ genDataPointerGet (operand * left, static void genNearPointerGet (operand * left, operand * result, - iCode * ic) + iCode * ic, + iCode * pi) { asmop *aop = NULL; regs *preg = NULL; @@ -6730,9 +6974,9 @@ genNearPointerGet (operand * left, } else rname = aopGet (AOP (left), 0, FALSE, FALSE); - - freeAsmop (left, NULL, ic, TRUE); - aopOp (result, ic, FALSE); + + //aopOp (result, ic, FALSE); + aopOp (result, ic, result?TRUE:FALSE); /* if bitfield then unpack the bits */ if (IS_BITVAR (retype)) @@ -6757,15 +7001,17 @@ genNearPointerGet (operand * left, aopPut (AOP (result), buffer, offset); } offset++; - if (size) + if (size || pi) emitcode ("inc", "%s", rname); } } /* now some housekeeping stuff */ - if (aop) + if (aop) /* we had to allocate for this iCode */ { - /* we had to allocate for this iCode */ + if (pi) { /* post increment present */ + aopPut(AOP ( left ),rname,0); + } freeAsmop (NULL, aop, ic, TRUE); } else @@ -6775,10 +7021,11 @@ genNearPointerGet (operand * left, if size > 0 && this could be used again we have to point it back to where it belongs */ - if (AOP_SIZE (result) > 1 && - !OP_SYMBOL (left)->remat && - (OP_SYMBOL (left)->liveTo > ic->seq || - ic->depth)) + if ((AOP_SIZE (result) > 1 && + !OP_SYMBOL (left)->remat && + (OP_SYMBOL (left)->liveTo > ic->seq || + ic->depth)) && + !pi) { int size = AOP_SIZE (result) - 1; while (size--) @@ -6787,8 +7034,9 @@ genNearPointerGet (operand * left, } /* done */ + freeAsmop (left, NULL, ic, TRUE); freeAsmop (result, NULL, ic, TRUE); - + if (pi) pi->generated = 1; } /*-----------------------------------------------------------------*/ @@ -6797,7 +7045,8 @@ genNearPointerGet (operand * left, static void genPagedPointerGet (operand * left, operand * result, - iCode * ic) + iCode * ic, + iCode *pi) { asmop *aop = NULL; regs *preg = NULL; @@ -6824,7 +7073,6 @@ genPagedPointerGet (operand * left, else rname = aopGet (AOP (left), 0, FALSE, FALSE); - freeAsmop (left, NULL, ic, TRUE); aopOp (result, ic, FALSE); /* if bitfield then unpack the bits */ @@ -6844,15 +7092,15 @@ genPagedPointerGet (operand * left, offset++; - if (size) + if (size || pi) emitcode ("inc", "%s", rname); } } /* now some housekeeping stuff */ - if (aop) + if (aop) /* we had to allocate for this iCode */ { - /* we had to allocate for this iCode */ + if (pi) aopPut ( AOP (left), rname, 0); freeAsmop (NULL, aop, ic, TRUE); } else @@ -6862,10 +7110,11 @@ genPagedPointerGet (operand * left, if size > 0 && this could be used again we have to point it back to where it belongs */ - if (AOP_SIZE (result) > 1 && - !OP_SYMBOL (left)->remat && - (OP_SYMBOL (left)->liveTo > ic->seq || - ic->depth)) + if ((AOP_SIZE (result) > 1 && + !OP_SYMBOL (left)->remat && + (OP_SYMBOL (left)->liveTo > ic->seq || + ic->depth)) && + !pi) { int size = AOP_SIZE (result) - 1; while (size--) @@ -6874,8 +7123,9 @@ genPagedPointerGet (operand * left, } /* done */ + freeAsmop (left, NULL, ic, TRUE); freeAsmop (result, NULL, ic, TRUE); - + if (pi) pi->generated = 1; } @@ -6884,7 +7134,7 @@ genPagedPointerGet (operand * left, /*-----------------------------------------------------------------*/ static void genFarPointerGet (operand * left, - operand * result, iCode * ic) + operand * result, iCode * ic, iCode * pi) { int size, offset; sym_link *retype = getSpec (operandType (result)); @@ -6905,7 +7155,6 @@ genFarPointerGet (operand * left, } } /* so dptr know contains the address */ - freeAsmop (left, NULL, ic, TRUE); aopOp (result, ic, FALSE); /* if bit then unpack */ @@ -6920,20 +7169,26 @@ genFarPointerGet (operand * left, { emitcode ("movx", "a,@dptr"); aopPut (AOP (result), "a", offset++); - if (size) + 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); + pi->generated = 1; + } + freeAsmop (left, NULL, ic, TRUE); freeAsmop (result, NULL, ic, TRUE); } /*-----------------------------------------------------------------*/ -/* emitcodePointerGet - gget value from code space */ +/* genCodePointerGet - gget value from code space */ /*-----------------------------------------------------------------*/ static void -emitcodePointerGet (operand * left, - operand * result, iCode * ic) +genCodePointerGet (operand * left, + operand * result, iCode * ic, iCode *pi) { int size, offset; sym_link *retype = getSpec (operandType (result)); @@ -6954,7 +7209,6 @@ emitcodePointerGet (operand * left, } } /* so dptr know contains the address */ - freeAsmop (left, NULL, ic, TRUE); aopOp (result, ic, FALSE); /* if bit then unpack */ @@ -6970,11 +7224,17 @@ emitcodePointerGet (operand * left, emitcode ("clr", "a"); emitcode ("movc", "a,@a+dptr"); aopPut (AOP (result), "a", offset++); - if (size) + 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); + pi->generated = 1; + } + freeAsmop (left, NULL, ic, TRUE); freeAsmop (result, NULL, ic, TRUE); } @@ -6983,7 +7243,7 @@ emitcodePointerGet (operand * left, /*-----------------------------------------------------------------*/ static void genGenPointerGet (operand * left, - operand * result, iCode * ic) + operand * result, iCode * ic, iCode *pi) { int size, offset; sym_link *retype = getSpec (operandType (result)); @@ -7008,7 +7268,6 @@ genGenPointerGet (operand * left, } } /* so dptr know contains the address */ - freeAsmop (left, NULL, ic, TRUE); aopOp (result, ic, FALSE); /* if bit then unpack */ @@ -7023,11 +7282,17 @@ genGenPointerGet (operand * left, { emitcode ("lcall", "__gptrget"); aopPut (AOP (result), "a", offset++); - if (size) + 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); + pi->generated = 1; + } + freeAsmop (left, NULL, ic, TRUE); freeAsmop (result, NULL, ic, TRUE); } @@ -7035,7 +7300,7 @@ genGenPointerGet (operand * left, /* genPointerGet - generate code for pointer get */ /*-----------------------------------------------------------------*/ static void -genPointerGet (iCode * ic) +genPointerGet (iCode * ic, iCode *pi) { operand *left, *result; sym_link *type, *etype; @@ -7055,21 +7320,6 @@ genPointerGet (iCode * ic) { /* we have to go by the storage class */ p_type = PTR_TYPE (SPEC_OCLS (etype)); - -/* if (SPEC_OCLS(etype)->codesp ) { */ -/* p_type = CPOINTER ; */ -/* } */ -/* else */ -/* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */ -/* p_type = FPOINTER ; */ -/* else */ -/* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */ -/* p_type = PPOINTER; */ -/* else */ -/* if (SPEC_OCLS(etype) == idata ) */ -/* p_type = IPOINTER; */ -/* else */ -/* p_type = POINTER ; */ } /* now that we have the pointer type we assign @@ -7079,23 +7329,23 @@ genPointerGet (iCode * ic) case POINTER: case IPOINTER: - genNearPointerGet (left, result, ic); + genNearPointerGet (left, result, ic, pi); break; case PPOINTER: - genPagedPointerGet (left, result, ic); + genPagedPointerGet (left, result, ic, pi); break; case FPOINTER: - genFarPointerGet (left, result, ic); + genFarPointerGet (left, result, ic, pi); break; case CPOINTER: - emitcodePointerGet (left, result, ic); + genCodePointerGet (left, result, ic, pi); break; case GPOINTER: - genGenPointerGet (left, result, ic); + genGenPointerGet (left, result, ic, pi); break; } @@ -7304,7 +7554,8 @@ genDataPointerSet (operand * right, static void genNearPointerSet (operand * right, operand * result, - iCode * ic) + iCode * ic, + iCode * pi) { asmop *aop = NULL; regs *preg = NULL; @@ -7326,25 +7577,47 @@ 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))) { - /* otherwise get a free pointer register */ - aop = newAsmop (0); - preg = getFreePtr (ic, &aop, FALSE); - emitcode ("mov", "%s,%s", - preg->name, - aopGet (AOP (result), 0, FALSE, TRUE)); - rname = preg->name; + if ( + //AOP_TYPE (result) == AOP_STK + IS_AOP_PREG(result) + ) + { + // Aha, it is a pointer, just in disguise. + rname = aopGet (AOP (result), 0, FALSE, FALSE); + if (*rname != '@') + { + fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n", + __FILE__, __LINE__); + } + else + { + // Expected case. + 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 (result), 0, FALSE, TRUE)); + rname = preg->name; + } + } + else + { + rname = aopGet (AOP (result), 0, FALSE, FALSE); } - else - rname = aopGet (AOP (result), 0, FALSE, FALSE); - freeAsmop (result, NULL, ic, TRUE); 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); @@ -7364,16 +7637,16 @@ genNearPointerSet (operand * right, } else emitcode ("mov", "@%s,%s", rname, l); - if (size) + if (size || pi) emitcode ("inc", "%s", rname); offset++; } } /* now some housekeeping stuff */ - if (aop) + if (aop) /* we had to allocate for this iCode */ { - /* we had to allocate for this iCode */ + if (pi) aopPut (AOP (result),rname,0); freeAsmop (NULL, aop, ic, TRUE); } else @@ -7383,10 +7656,11 @@ genNearPointerSet (operand * right, if size > 0 && this could be used again we have to point it back to where it belongs */ - if (AOP_SIZE (right) > 1 && - !OP_SYMBOL (result)->remat && - (OP_SYMBOL (result)->liveTo > ic->seq || - ic->depth)) + if ((AOP_SIZE (right) > 1 && + !OP_SYMBOL (result)->remat && + (OP_SYMBOL (result)->liveTo > ic->seq || + ic->depth)) && + !pi) { int size = AOP_SIZE (right) - 1; while (size--) @@ -7395,9 +7669,9 @@ genNearPointerSet (operand * right, } /* done */ + if (pi) pi->generated = 1; + freeAsmop (result, NULL, ic, TRUE); freeAsmop (right, NULL, ic, TRUE); - - } /*-----------------------------------------------------------------*/ @@ -7406,7 +7680,8 @@ genNearPointerSet (operand * right, static void genPagedPointerSet (operand * right, operand * result, - iCode * ic) + iCode * ic, + iCode * pi) { asmop *aop = NULL; regs *preg = NULL; @@ -7433,7 +7708,6 @@ genPagedPointerSet (operand * right, else rname = aopGet (AOP (result), 0, FALSE, FALSE); - freeAsmop (result, NULL, ic, TRUE); aopOp (right, ic, FALSE); /* if bitfield then unpack the bits */ @@ -7452,7 +7726,7 @@ genPagedPointerSet (operand * right, MOVA (l); emitcode ("movx", "@%s,a", rname); - if (size) + if (size || pi) emitcode ("inc", "%s", rname); offset++; @@ -7460,9 +7734,9 @@ genPagedPointerSet (operand * right, } /* now some housekeeping stuff */ - if (aop) + if (aop) /* we had to allocate for this iCode */ { - /* we had to allocate for this iCode */ + if (pi) aopPut (AOP (result),rname,0); freeAsmop (NULL, aop, ic, TRUE); } else @@ -7484,6 +7758,8 @@ genPagedPointerSet (operand * right, } /* done */ + if (pi) pi->generated = 1; + freeAsmop (result, NULL, ic, TRUE); freeAsmop (right, NULL, ic, TRUE); @@ -7494,7 +7770,7 @@ genPagedPointerSet (operand * right, /*-----------------------------------------------------------------*/ static void genFarPointerSet (operand * right, - operand * result, iCode * ic) + operand * result, iCode * ic, iCode * pi) { int size, offset; sym_link *retype = getSpec (operandType (right)); @@ -7515,7 +7791,6 @@ genFarPointerSet (operand * right, } } /* so dptr know contains the address */ - freeAsmop (result, NULL, ic, TRUE); aopOp (right, ic, FALSE); /* if bit then unpack */ @@ -7531,11 +7806,16 @@ genFarPointerSet (operand * right, char *l = aopGet (AOP (right), offset++, FALSE, FALSE); MOVA (l); emitcode ("movx", "@dptr,a"); - if (size) + if (size || pi) emitcode ("inc", "dptr"); } } - + if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) { + aopPut (AOP(result),"dpl",0); + aopPut (AOP(result),"dph",1); + pi->generated=1; + } + freeAsmop (result, NULL, ic, TRUE); freeAsmop (right, NULL, ic, TRUE); } @@ -7544,7 +7824,7 @@ genFarPointerSet (operand * right, /*-----------------------------------------------------------------*/ static void genGenPointerSet (operand * right, - operand * result, iCode * ic) + operand * result, iCode * ic, iCode * pi) { int size, offset; sym_link *retype = getSpec (operandType (right)); @@ -7570,7 +7850,6 @@ genGenPointerSet (operand * right, } } /* so dptr know contains the address */ - freeAsmop (result, NULL, ic, TRUE); aopOp (right, ic, FALSE); /* if bit then unpack */ @@ -7586,11 +7865,17 @@ genGenPointerSet (operand * right, char *l = aopGet (AOP (right), offset++, FALSE, FALSE); MOVA (l); emitcode ("lcall", "__gptrput"); - if (size) + if (size || pi) emitcode ("inc", "dptr"); } } + if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) { + aopPut (AOP(result),"dpl",0); + aopPut (AOP(result),"dph",1); + pi->generated=1; + } + freeAsmop (result, NULL, ic, TRUE); freeAsmop (right, NULL, ic, TRUE); } @@ -7598,7 +7883,7 @@ genGenPointerSet (operand * right, /* genPointerSet - stores the value into a pointer location */ /*-----------------------------------------------------------------*/ static void -genPointerSet (iCode * ic) +genPointerSet (iCode * ic, iCode *pi) { operand *right, *result; sym_link *type, *etype; @@ -7629,19 +7914,19 @@ genPointerSet (iCode * ic) case POINTER: case IPOINTER: - genNearPointerSet (right, result, ic); + genNearPointerSet (right, result, ic, pi); break; case PPOINTER: - genPagedPointerSet (right, result, ic); + genPagedPointerSet (right, result, ic, pi); break; case FPOINTER: - genFarPointerSet (right, result, ic); + genFarPointerSet (right, result, ic, pi); break; case GPOINTER: - genGenPointerSet (right, result, ic); + genGenPointerSet (right, result, ic, pi); break; } @@ -7784,6 +8069,8 @@ genAssign (iCode * ic) int size, offset; unsigned long lit = 0L; + D(emitcode(";","genAssign")); + result = IC_RESULT (ic); right = IC_RIGHT (ic); @@ -7794,8 +8081,7 @@ genAssign (iCode * ic) aopOp (right, ic, FALSE); /* special case both in far space */ - if ((AOP_TYPE (right) == AOP_DPTR || - AOP_TYPE (right) == AOP_DPTR2) && + if (AOP_TYPE (right) == AOP_DPTR && IS_TRUE_SYMOP (result) && isOperandInFarSpace (result)) { @@ -7919,6 +8205,8 @@ genCast (iCode * ic) operand *right = IC_RIGHT (ic); int size, offset; + D(emitcode(";", "genCast")); + /* if they are equivalent then do nothing */ if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic))) return; @@ -7927,7 +8215,8 @@ genCast (iCode * ic) aopOp (result, ic, FALSE); /* if the result is a bit */ - if (AOP_TYPE (result) == AOP_CRY) + // if (AOP_TYPE (result) == AOP_CRY /* works only for true symbols */ + if (IS_BITVAR(OP_SYMBOL(result)->type)) { /* if the right size is a literal then we know what the value is */ @@ -7994,8 +8283,13 @@ genCast (iCode * ic) p_type = DCL_TYPE (type); else { - /* we have to go by the storage class */ - p_type = PTR_TYPE (SPEC_OCLS (etype)); + if (SPEC_SCLS(etype)==S_REGISTER) { + // let's assume it is a generic pointer + p_type=GPOINTER; + } else { + /* we have to go by the storage class */ + p_type = PTR_TYPE (SPEC_OCLS (etype)); + } } /* the first two bytes are known */ @@ -8021,7 +8315,10 @@ genCast (iCode * ic) case CPOINTER: l = "#0x02"; break; - case PPOINTER: + case GPOINTER: + l = "0x03"; + break; + case PPOINTER: // what the fck is this? l = "#0x03"; break; @@ -8064,7 +8361,7 @@ genCast (iCode * ic) /* now depending on the sign of the source && destination */ size = AOP_SIZE (result) - AOP_SIZE (right); /* if unsigned or not an integral type */ - if (SPEC_USIGN (rtype) || !IS_SPEC (rtype)) + if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE(right)==AOP_CRY) { while (size--) aopPut (AOP (result), zero, offset++); @@ -8124,7 +8421,30 @@ genDjnz (iCode * ic, iCode * ifx) aopOp (IC_RESULT (ic), ic, FALSE); - if (IS_AOP_PREG (IC_RESULT (ic))) + if (AOP_NEEDSACC(IC_RESULT(ic))) + { + /* If the result is accessed indirectly via + * the accumulator, we must explicitly write + * it back after the decrement. + */ + char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE); + + 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))) { emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE)); @@ -8186,6 +8506,64 @@ genReceive (iCode * ic) freeAsmop (IC_RESULT (ic), NULL, ic, TRUE); } +/*-----------------------------------------------------------------*/ +/* gen51AggregateAssign - copy complete array's or structures */ +/*-----------------------------------------------------------------*/ +void gen51AggregateAssign(iCode *ic) { + operand *left=IC_LEFT(ic); + operand *right=IC_RIGHT(ic); + char *fromName=OP_SYMBOL(right)->rname; + char *toName=OP_SYMBOL(left)->rname; + int fromSize=getSize(OP_SYMBOL(right)->type); + int toSize=getSize(OP_SYMBOL(left)->type); + int count=toSize; + + if (SPEC_OCLS(OP_SYMBOL(left)->etype)!=xdata || + SPEC_OCLS(OP_SYMBOL(right)->etype)!=code) { + // well, this code isn't used yet from anywhere else as for initialising + fprintf (stderr, "*** error: %s:%d can only assign aggregates from cseg to xseg for now\n", ic->filename, ic->lineno); + exit (457); + } + + if (fromSize!=toSize) { + fprintf (stderr, "*** error: %s:%d aggregates have different size\n", + ic->filename, ic->lineno); + exit (821); + } + +#if 1 + // use the generic memcpy() for now + emitcode (";", "initialize %s", OP_SYMBOL(IC_LEFT(ic))->name); + emitcode ("mov", "dptr,#_memcpy_PARM_2"); + emitcode ("mov", "a,#%s", fromName); + emitcode ("movx", "@dptr,a"); + emitcode ("inc", "dptr"); + emitcode ("mov", "a,#(%s>>8)", fromName); + emitcode ("movx", "@dptr,a"); + emitcode ("inc", "dptr"); + emitcode ("mov", "a,#%02x; only from cseg for now", 2); + emitcode ("movx", "@dptr,a"); + emitcode ("mov", "dptr,#_memcpy_PARM_3"); + emitcode ("mov", "a,#(%d>>0); number of bytes", count); + emitcode ("movx", "@dptr,a"); + emitcode ("inc", "dptr"); + emitcode ("mov", "a,#(%d>>8)", count); + emitcode ("movx", "@dptr,a"); + emitcode ("mov", "dptr,#%s", toName); + emitcode ("mov", "b,#%02x; only to xseg for now", 1); + emitcode ("lcall", "_memcpy"); +#else + // more efficient, but will require the native_memcpy_cs2xs + emitcode ("mov", "r0,#%s", fromName); + emitcode ("mov", "r1,#(%s>>8)", fromName); + emitcode ("mov", "r2,#%s", toName); + emitcode ("mov", "r3,#(%s>>8)", toName); + emitcode ("mov", "r4,#%d", count); + emitcode ("mov", "r5,#(%d>>8)", count); + emitcode ("lcall", "_native_memcpy_cs2xs"); +#endif +} + /*-----------------------------------------------------------------*/ /* gen51Code - generate code for 8051 based controllers */ /*-----------------------------------------------------------------*/ @@ -8201,8 +8579,8 @@ gen51Code (iCode * lic) if (allocInfo) printAllocInfo (currFunc, codeOutFile); /* if debug information required */ -/* if (options.debug && currFunc) { */ - if (currFunc) + /* if (options.debug && currFunc) { */ + if (options.debug && currFunc) { cdbSymbol (currFunc, cdbFile, FALSE, TRUE); _G.debugLine = 1; @@ -8392,12 +8770,12 @@ gen51Code (iCode * lic) break; case GET_VALUE_AT_ADDRESS: - genPointerGet (ic); + genPointerGet (ic, hasInc(IC_LEFT(ic),ic)); break; case '=': if (POINTER_SET (ic)) - genPointerSet (ic); + genPointerSet (ic, hasInc (IC_RESULT(ic),ic)); else genAssign (ic); break; @@ -8426,10 +8804,12 @@ gen51Code (iCode * lic) addSet (&_G.sendSet, ic); break; + case ARRAYINIT: + gen51AggregateAssign(ic); + break; + default: ic = ic; - /* piCode(ic,stdout); */ - } }