X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Fmcs51%2Fgen.c;h=0757d80dcbd284ecb38568a82fb079b03d7eaf10;hb=a0df5f7e9b47a96bef4a94b8c96692f0156acec0;hp=23ac57d78e443298e6de456d2298e930b64cb224;hpb=69e754f12a02df9b381d11f0b7a1d31434e90ad5;p=fw%2Fsdcc diff --git a/src/mcs51/gen.c b/src/mcs51/gen.c index 23ac57d7..0757d80d 100644 --- a/src/mcs51/gen.c +++ b/src/mcs51/gen.c @@ -44,6 +44,7 @@ #include "gen.h" char *aopLiteral (value * val, int offset); +char *aopLiteralLong (value * val, int offset, int size); extern int allocInfo; /* this is the down and dirty file with all kinds of @@ -80,10 +81,10 @@ static unsigned short rbank = -1; #define SYM_BP(sym) (SPEC_OCLS (sym->etype)->paged ? "_bpx" : "_bp") -#define R0INB _G.bu.bs.r0InB -#define R1INB _G.bu.bs.r1InB -#define OPINB _G.bu.bs.OpInB -#define BINUSE _G.bu.BInUse +#define R0INB _G.bu.bs.r0InB +#define R1INB _G.bu.bs.r1InB +#define OPINB _G.bu.bs.OpInB +#define BINUSE _G.bu.BInUse static struct { @@ -110,7 +111,8 @@ static struct _G; static char *rb1regs[] = { - "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7" + "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7", + "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7" }; extern int mcs51_ptrRegReq; @@ -164,7 +166,7 @@ emitcode (char *inst, const char *fmt,...) else tvsprintf (lb, sizeof(lb), fmt, ap); - while (isspace (*lbp)) + while (isspace ((unsigned char)*lbp)) lbp++; if (lbp && *lbp) @@ -203,6 +205,24 @@ mova (const char *x) emitcode("mov","a,%s", x); } +/*-----------------------------------------------------------------*/ +/* movc - moves specified value into the carry */ +/*-----------------------------------------------------------------*/ +static void +movc (const char *s) +{ + if (s == zero) + CLRC; + else if (s == one) + SETC; + else if (strcmp (s, "c")) + {/* it's not in carry already */ + MOVA (s); + /* set C, if a >= 1 */ + emitcode ("add", "a,#0xff"); + } +} + /*-----------------------------------------------------------------*/ /* pushB - saves register B if necessary */ /*-----------------------------------------------------------------*/ @@ -240,6 +260,42 @@ popB (bool pushedB) } } +/*-----------------------------------------------------------------*/ +/* pushReg - saves register */ +/*-----------------------------------------------------------------*/ +static bool +pushReg (int index, bool bits_pushed) +{ + regs * reg = mcs51_regWithIdx (index); + if (reg->type == REG_BIT) + { + if (!bits_pushed) + emitcode ("push", "%s", reg->base); + return TRUE; + } + else + emitcode ("push", "%s", reg->dname); + return bits_pushed; +} + +/*-----------------------------------------------------------------*/ +/* popReg - restores register */ +/*-----------------------------------------------------------------*/ +static bool +popReg (int index, bool bits_popped) +{ + regs * reg = mcs51_regWithIdx (index); + if (reg->type == REG_BIT) + { + if (!bits_popped) + emitcode ("pop", "%s", reg->base); + return TRUE; + } + else + emitcode ("pop", "%s", reg->dname); + return bits_popped; +} + /*-----------------------------------------------------------------*/ /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */ /*-----------------------------------------------------------------*/ @@ -598,7 +654,7 @@ aopForSym (iCode * ic, symbol * sym, bool result) sym->aop = aop = newAsmop (AOP_IMMD); aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1); strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname); - aop->size = FPTRSIZE; + aop->size = getSize (sym->type); return aop; } @@ -637,7 +693,7 @@ aopForRemat (symbol * sym) aop->aopu.aop_immd.from_cast_remat = 1; ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode; ptr_type = pointerTypeToGPByte (DCL_TYPE(from_type), NULL, NULL); - continue ; + continue; } else break; ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode; @@ -727,8 +783,9 @@ operandsEqu (operand * op1, operand * op2) return TRUE; /* if they have the same rname */ - if (sym1->rname[0] && sym2->rname[0] - && strcmp (sym1->rname, sym2->rname) == 0) + if (sym1->rname[0] && sym2->rname[0] && + strcmp (sym1->rname, sym2->rname) == 0 && + !(IS_PARM (op2) && IS_ITEMP (op1))) return TRUE; /* if left is a tmp & right is not */ @@ -759,8 +816,10 @@ sameRegs (asmop * aop1, asmop * aop2) if (aop1 == aop2) return TRUE; - if (aop1->type != AOP_REG || - aop2->type != AOP_REG) + if (aop1->type != AOP_REG && aop1->type != AOP_CRY) + return FALSE; + + if (aop1->type != aop2->type) return FALSE; if (aop1->size != aop2->size) @@ -887,6 +946,16 @@ aopOp (operand * op, iCode * ic, bool result) return; } + /* if the type is a bit register */ + if (sym->regType == REG_BIT) + { + sym->aop = op->aop = aop = newAsmop (AOP_CRY); + aop->size = sym->nRegs;//1??? + aop->aopu.aop_reg[0] = sym->regs[0]; + aop->aopu.aop_dir = sym->regs[0]->name; + return; + } + /* must be in a register */ sym->aop = op->aop = aop = newAsmop (AOP_REG); aop->size = sym->nRegs; @@ -1448,7 +1517,7 @@ aopPut (operand * result, const char *s, int offset, bool bvolatile) emitcode ("setb", "%s", aop->aopu.aop_dir); else if (!strcmp (s, "c")) emitcode ("mov", "%s,c", aop->aopu.aop_dir); - else + else if (strcmp (s, aop->aopu.aop_dir)) { MOVA (s); /* set C, if a >= 1 */ @@ -1676,14 +1745,23 @@ genNot (iCode * ic) /* if in bit space then a special case */ if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) { - emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir); - emitcode ("cpl", "c"); - outBitC (IC_RESULT (ic)); + /* if left==result then cpl bit */ + if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic)))) + { + emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir); + } + else + { + emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir); + emitcode ("cpl", "c"); + outBitC (IC_RESULT (ic)); + } goto release; } toBoolean (IC_LEFT (ic)); + /* set C, if a == 0 */ tlbl = newiTempLabel (NULL); emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100); emitcode ("", "%05d$:", tlbl->key + 100); @@ -1725,7 +1803,6 @@ genCpl (iCode * ic) bit -> int -> ~int -> bit uchar -> int -> ~int -> bit */ - werror(W_COMPLEMENT); emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir); goto release; } @@ -1916,8 +1993,15 @@ saveRegisters (iCode * lic) if (count == 1) { - i = bitVectFirstBit (rsave); - emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name); + regs * reg = mcs51_regWithIdx (bitVectFirstBit (rsave)); + if (reg->type == REG_BIT) + { + emitcode ("mov", "a,%s", reg->base); + } + else + { + emitcode ("mov", "a,%s", reg->name); + } emitcode ("mov", "r0,%s", spname); emitcode ("inc", "%s", spname);// allocate before use emitcode ("movx", "@r0,a"); @@ -1926,6 +2010,17 @@ saveRegisters (iCode * lic) } else if (count != 0) { + bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave); + int nBits = bitVectnBitsOn (rsavebits); + + if (nBits != 0) + { + count = count - nBits + 1; + /* remove all but the first bits as they are pushed all at once */ + rsave = bitVectCplAnd (rsave, rsavebits); + rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits)); + } + if (bitVectBitValue (rsave, R0_IDX)) { emitcode ("push", "%s", mcs51_regWithIdx (R0_IDX)->dname); @@ -1938,14 +2033,19 @@ saveRegisters (iCode * lic) { if (bitVectBitValue (rsave, i)) { + regs * reg = mcs51_regWithIdx (i); if (i == R0_IDX) { emitcode ("pop", "acc"); emitcode ("push", "acc"); } + else if (reg->type == REG_BIT) + { + emitcode ("mov", "a,%s", reg->base); + } else { - emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name); + emitcode ("mov", "a,%s", reg->name); } emitcode ("movx", "@r0,a"); if (--count) @@ -1961,11 +2061,16 @@ saveRegisters (iCode * lic) } } else - for (i = 0; i < mcs51_nRegs; i++) - { - if (bitVectBitValue (rsave, i)) - emitcode ("push", "%s", mcs51_regWithIdx (i)->dname); - } + { + bool bits_pushed = FALSE; + for (i = 0; i < mcs51_nRegs; i++) + { + if (bitVectBitValue (rsave, i)) + { + bits_pushed = pushReg (i, bits_pushed); + } + } + } } /*-----------------------------------------------------------------*/ @@ -1988,26 +2093,53 @@ unsaveRegisters (iCode * ic) if (count == 1) { + regs * reg = mcs51_regWithIdx (bitVectFirstBit (rsave)); emitcode ("mov", "r0,%s", spname); emitcode ("dec", "r0"); emitcode ("movx", "a,@r0"); - i = bitVectFirstBit (rsave); - emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name); + if (reg->type == REG_BIT) + { + emitcode ("mov", "%s,a", reg->base); + } + else + { + emitcode ("mov", "%s,a", reg->name); + } emitcode ("dec", "%s", spname); } else if (count != 0) { + bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave); + int nBits = bitVectnBitsOn (rsavebits); + + if (nBits != 0) + { + count = count - nBits + 1; + /* remove all but the first bits as they are popped all at once */ + rsave = bitVectCplAnd (rsave, rsavebits); + rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits)); + } + emitcode ("mov", "r0,%s", spname); for (i = mcs51_nRegs; i >= 0; i--) { if (bitVectBitValue (rsave, i)) { + regs * reg = mcs51_regWithIdx (i); emitcode ("dec", "r0"); emitcode ("movx", "a,@r0"); - if (i != R0_IDX) - emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name); + if (i == R0_IDX) + { + emitcode ("push", "acc"); + } + else if (reg->type == REG_BIT) + { + emitcode ("mov", "%s,a", reg->base); + } else - emitcode ("push", "acc"); + { + emitcode ("mov", "%s,a", reg->name); + } } } emitcode ("mov", "%s,r0", spname); @@ -2018,16 +2150,21 @@ unsaveRegisters (iCode * ic) } } else - for (i = mcs51_nRegs; i >= 0; i--) - { - if (bitVectBitValue (rsave, i)) - emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname); - } + { + bool bits_popped = FALSE; + for (i = mcs51_nRegs; i >= 0; i--) + { + if (bitVectBitValue (rsave, i)) + { + bits_popped = popReg (i, bits_popped); + } + } + } } /*-----------------------------------------------------------------*/ -/* pushSide - */ +/* pushSide - */ /*-----------------------------------------------------------------*/ static void pushSide (operand * oper, int size) @@ -2044,20 +2181,28 @@ pushSide (operand * oper, int size) emitcode ("push", "acc"); } else + { emitcode ("push", "%s", l); } } +} /*-----------------------------------------------------------------*/ /* assignResultValue - also indicates if acc is in use afterwards */ /*-----------------------------------------------------------------*/ static bool -assignResultValue (operand * oper) +assignResultValue (operand * oper, operand * func) { int offset = 0; int size = AOP_SIZE (oper); bool accuse = FALSE; + if (func && IS_BIT (OP_SYM_ETYPE (func))) + { + outBitC (oper); + return FALSE; + } + while (size--) { accuse |= aopPut (oper, fReturn[offset], offset, isOperandVolatile (oper, FALSE)); @@ -2119,6 +2264,7 @@ genIpush (iCode * ic) { int size, offset = 0; char *l; + char *prev = ""; D(emitcode ("; genIpush","")); @@ -2147,7 +2293,7 @@ genIpush (iCode * ic) return; } - /* this is a paramter push: in this case we call + /* this is a parameter push: in this case we call the routine to find the call and save those registers that need to be saved */ saveRegisters (ic); @@ -2173,11 +2319,15 @@ genIpush (iCode * ic) AOP_TYPE (IC_LEFT (ic)) != AOP_DIR && strcmp (l, "a")) { - MOVA (l); + if (strcmp (l, prev) || *l == '@') + MOVA (l); emitcode ("push", "acc"); } else + { emitcode ("push", "%s", l); + } + prev = l; } freeAsmop (IC_LEFT (ic), NULL, ic, TRUE); @@ -2350,31 +2500,102 @@ unsaveRBank (int bank, iCode * ic, bool popPsw) /*-----------------------------------------------------------------*/ static void genSend(set *sendSet) { - iCode *sic; - int rb1_count = 0 ; - - for (sic = setFirstItem (sendSet); sic; - sic = setNextItem (sendSet)) { - int size, offset = 0; - aopOp (IC_LEFT (sic), sic, FALSE); - size = AOP_SIZE (IC_LEFT (sic)); - - if (sic->argreg == 1) { - while (size--) { - char *l = aopGet (IC_LEFT (sic), offset, - FALSE, FALSE); - if (strcmp (l, fReturn[offset])) - emitcode ("mov", "%s,%s", fReturn[offset], l); - offset++; - } - rb1_count = 0; - } else { - while (size--) { - emitcode ("mov","b1_%d,%s",rb1_count++, - aopGet (IC_LEFT (sic), offset++,FALSE, FALSE)); - } - } - freeAsmop (IC_LEFT (sic), NULL, sic, TRUE); + iCode *sic; + int bit_count = 0; + + /* first we do all bit parameters */ + for (sic = setFirstItem (sendSet); sic; + sic = setNextItem (sendSet)) + { + aopOp (IC_LEFT (sic), sic, FALSE); + + if (sic->argreg > 12) + { + int bit = sic->argreg-13; + + /* if left is a literal then + we know what the value is */ + if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT) + { + if (((int) operandLitValue (IC_LEFT (sic)))) + emitcode ("setb", "b[%d]", bit); + else + emitcode ("clr", "b[%d]", bit); + } + else if (AOP_TYPE (IC_LEFT (sic)) == AOP_CRY) + { + char *l = AOP (IC_LEFT (sic))->aopu.aop_dir; + if (strcmp (l, "c")) + emitcode ("mov", "c,%s", l); + emitcode ("mov", "b[%d],c", bit); + } + else + { + /* we need to or */ + toBoolean (IC_LEFT (sic)); + /* set C, if a >= 1 */ + emitcode ("add", "a,#0xff"); + emitcode ("mov", "b[%d],c", bit); + } + bit_count++; + BitBankUsed = 1; + } + freeAsmop (IC_LEFT (sic), NULL, sic, TRUE); + } + + if (bit_count) + { + saveRegisters (setFirstItem (sendSet)); + emitcode ("mov", "bits,b"); + } + + /* then we do all other parameters */ + for (sic = setFirstItem (sendSet); sic; + sic = setNextItem (sendSet)) + { + int size, offset = 0; + aopOp (IC_LEFT (sic), sic, FALSE); + size = AOP_SIZE (IC_LEFT (sic)); + + if (sic->argreg == 1) + { + while (size--) + { + char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE); + if (strcmp (l, fReturn[offset])) + emitcode ("mov", "%s,%s", fReturn[offset], l); + offset++; + } + } + else if (sic->argreg <= 12) + { + while (size--) + { + emitcode ("mov","%s,%s", rb1regs[sic->argreg+offset-5], + aopGet (IC_LEFT (sic), offset,FALSE, FALSE)); + offset++; + } + } + freeAsmop (IC_LEFT (sic), NULL, sic, TRUE); + } +} + +/*-----------------------------------------------------------------*/ +/* selectRegBank - emit code to select the register bank */ +/*-----------------------------------------------------------------*/ +static void +selectRegBank (short bank, bool keepFlags) +{ + /* if f.e. result is in carry */ + if (keepFlags) + { + emitcode ("anl", "psw,#0xE7"); + if (bank) + emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff); + } + else + { + emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff); } } @@ -2385,14 +2606,17 @@ static void genCall (iCode * ic) { sym_link *dtype; + sym_link *etype; // bool restoreBank = FALSE; bool swapBanks = FALSE; bool accuse = FALSE; bool accPushed = FALSE; + bool resultInF0 = FALSE; D(emitcode("; genCall","")); dtype = operandType (IC_LEFT (ic)); + etype = getSpec(dtype); /* if send set is not empty then assign */ if (_G.sendSet) { @@ -2408,37 +2632,57 @@ genCall (iCode * ic) /* 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 (currFunc && dtype && !IFFUNC_ISNAKED(dtype) && (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) && !IFFUNC_ISISR (dtype)) - { + { 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 (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype))) + { + if (IFFUNC_CALLEESAVES(dtype)) + { + werror (E_BANKED_WITH_CALLEESAVES); + } + else + { + char *l = (OP_SYMBOL (IC_LEFT (ic))->rname[0] ? + OP_SYMBOL (IC_LEFT (ic))->rname : + OP_SYMBOL (IC_LEFT (ic))->name); + + emitcode ("mov", "r0,#%s", l); + emitcode ("mov", "r1,#(%s >> 8)", l); + emitcode ("mov", "r2,#(%s >> 16)", l); + emitcode ("lcall", "__sdcc_banked_call"); + } + } + else + { + 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); - } + { + selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype)); + } /* if we need assign a result value */ if ((IS_ITEMP (IC_RESULT (ic)) && + !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) && (OP_SYMBOL (IC_RESULT (ic))->nRegs || OP_SYMBOL (IC_RESULT (ic))->accuse || OP_SYMBOL (IC_RESULT (ic))->spildir)) || @@ -2449,7 +2693,7 @@ genCall (iCode * ic) aopOp (IC_RESULT (ic), ic, FALSE); _G.accInUse--; - accuse = assignResultValue (IC_RESULT (ic)); + accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic)); freeAsmop (IC_RESULT (ic), NULL, ic, TRUE); } @@ -2465,6 +2709,12 @@ genCall (iCode * ic) emitcode ("push", "acc"); accPushed = TRUE; } + if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) && + IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic)))) + { + emitcode ("mov", "F0,c"); + resultInF0 = TRUE; + } emitcode ("mov", "a,%s", spname); emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff); @@ -2483,7 +2733,7 @@ genCall (iCode * ic) emitcode ("dec", "%s", spname); } - /* if we hade saved some registers then unsave them */ + /* if we had saved some registers then unsave them */ if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype)) { if (accuse && !accPushed && options.useXstack) @@ -2499,6 +2749,16 @@ genCall (iCode * ic) // if (restoreBank) // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE); + if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic)))) + { + if (resultInF0) + emitcode ("mov", "c,F0"); + + aopOp (IC_RESULT (ic), ic, FALSE); + assignResultValue (IC_RESULT (ic), IC_LEFT (ic)); + freeAsmop (IC_RESULT (ic), NULL, ic, TRUE); + } + if (accPushed) emitcode ("pop", "acc"); } @@ -2510,12 +2770,16 @@ static void genPcall (iCode * ic) { sym_link *dtype; + sym_link *etype; symbol *rlbl = newiTempLabel (NULL); // bool restoreBank=FALSE; bool swapBanks = FALSE; + bool resultInF0 = FALSE; D(emitcode("; genPCall","")); + dtype = operandType (IC_LEFT (ic))->next; + etype = getSpec(dtype); /* if caller saves & we have not saved then */ if (!ic->regsSaved) saveRegisters (ic); @@ -2523,56 +2787,138 @@ genPcall (iCode * ic) /* 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))->next; if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) && (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) && !IFFUNC_ISISR (dtype)) - { + { // saveRBank (FUNC_REGBANK (dtype), ic, TRUE); // restoreBank=TRUE; swapBanks = TRUE; // need caution message to user here - } - - /* push the return address on to the stack */ - emitcode ("mov", "a,#%05d$", (rlbl->key + 100)); - emitcode ("push", "acc"); - emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100)); - emitcode ("push", "acc"); + } - /* now push the calling address */ - aopOp (IC_LEFT (ic), ic, FALSE); + if (IS_LITERAL(etype)) + { + /* if send set is not empty then assign */ + if (_G.sendSet) + { + genSend(reverseSet(_G.sendSet)); + _G.sendSet = NULL; + } - pushSide (IC_LEFT (ic), FPTRSIZE); + if (swapBanks) + { + emitcode ("mov", "psw,#0x%02x", + ((FUNC_REGBANK(dtype)) << 3) & 0xff); + } - freeAsmop (IC_LEFT (ic), NULL, ic, TRUE); + if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype))) + { + if (IFFUNC_CALLEESAVES(dtype)) + { + werror (E_BANKED_WITH_CALLEESAVES); + } + else + { + char *l = aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2); - /* if send set is not empty the assign */ - if (_G.sendSet) - { - genSend(reverseSet(_G.sendSet)); - _G.sendSet = NULL; + emitcode ("mov", "r0,#%s", l); + emitcode ("mov", "r1,#(%s >> 8)", l); + emitcode ("mov", "r2,#(%s >> 16)", l); + emitcode ("lcall", "__sdcc_banked_call"); + } + } + else + { + emitcode ("lcall", "%s", aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2)); + } } + else + { + if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype))) + { + if (IFFUNC_CALLEESAVES(dtype)) + { + werror (E_BANKED_WITH_CALLEESAVES); + } + else + { + aopOp (IC_LEFT (ic), ic, FALSE); - if (swapBanks) - { - emitcode ("mov", "psw,#0x%02x", - ((FUNC_REGBANK(dtype)) << 3) & 0xff); - } + if (!swapBanks) + { + emitcode ("mov", "ar0,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE)); + emitcode ("mov", "ar1,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE)); + emitcode ("mov", "ar2,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE)); + } + else + { + int reg = ((FUNC_REGBANK(dtype)) << 3) & 0xff; + emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 0, FALSE, FALSE)); + emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 1, FALSE, FALSE)); + emitcode ("mov", "0x%02x,%s", reg, aopGet(IC_LEFT (ic), 2, FALSE, FALSE)); + } - /* make the call */ - emitcode ("ret", ""); - emitcode ("", "%05d$:", (rlbl->key + 100)); + freeAsmop (IC_LEFT (ic), NULL, ic, TRUE); + + /* if send set is not empty then assign */ + if (_G.sendSet) + { + genSend(reverseSet(_G.sendSet)); + _G.sendSet = NULL; + } + + if (swapBanks) + { + emitcode ("mov", "psw,#0x%02x", + ((FUNC_REGBANK(dtype)) << 3) & 0xff); + } + + /* make the call */ + emitcode ("lcall", "__sdcc_banked_call"); + } + } + else + { + /* push the return address on to the stack */ + emitcode ("mov", "a,#%05d$", (rlbl->key + 100)); + emitcode ("push", "acc"); + emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100)); + emitcode ("push", "acc"); + + /* now push the calling address */ + aopOp (IC_LEFT (ic), ic, FALSE); + + pushSide (IC_LEFT (ic), FPTRSIZE); + + freeAsmop (IC_LEFT (ic), NULL, ic, TRUE); + + /* if send set is not empty the assign */ + if (_G.sendSet) + { + genSend(reverseSet(_G.sendSet)); + _G.sendSet = NULL; + } + if (swapBanks) + { + emitcode ("mov", "psw,#0x%02x", + ((FUNC_REGBANK(dtype)) << 3) & 0xff); + } + /* make the call */ + emitcode ("ret", ""); + emitcode ("", "%05d$:", (rlbl->key + 100)); + } + } if (swapBanks) - { - emitcode ("mov", "psw,#0x%02x", - ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff); - } + { + selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype)); + } /* if we need assign a result value */ if ((IS_ITEMP (IC_RESULT (ic)) && + !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) && (OP_SYMBOL (IC_RESULT (ic))->nRegs || OP_SYMBOL (IC_RESULT (ic))->spildir)) || IS_TRUE_SYMOP (IC_RESULT (ic))) @@ -2582,18 +2928,24 @@ genPcall (iCode * ic) aopOp (IC_RESULT (ic), ic, FALSE); _G.accInUse--; - assignResultValue (IC_RESULT (ic)); + assignResultValue (IC_RESULT (ic), IC_LEFT (ic)); freeAsmop (IC_RESULT (ic), NULL, ic, TRUE); } - /* adjust the stack for parameters if - required */ + /* adjust the stack for parameters if required */ if (ic->parmBytes) { int i; if (ic->parmBytes > 3) { + if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) && + IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic)))) + { + emitcode ("mov", "F0,c"); + resultInF0 = TRUE; + } + emitcode ("mov", "a,%s", spname); emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff); emitcode ("mov", "%s,a", spname); @@ -2608,10 +2960,19 @@ genPcall (iCode * ic) // if (restoreBank) // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE); - /* if we hade saved some registers then - unsave them */ + /* if we had saved some registers then unsave them */ if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype)) unsaveRegisters (ic); + + if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic)))) + { + if (resultInF0) + emitcode ("mov", "c,F0"); + + aopOp (IC_RESULT (ic), ic, FALSE); + assignResultValue (IC_RESULT (ic), IC_LEFT (ic)); + freeAsmop (IC_RESULT (ic), NULL, ic, TRUE); + } } /*-----------------------------------------------------------------*/ @@ -2700,15 +3061,18 @@ genFunction (iCode * ic) rbank = FUNC_REGBANK (ftype); for (i = 0; i < mcs51_nRegs; i++) { - if (strcmp (regs8051[i].base, "0") == 0) - emitcode ("", "%s = 0x%02x", - regs8051[i].dname, - 8 * rbank + regs8051[i].offset); - else - emitcode ("", "%s = %s + 0x%02x", - regs8051[i].dname, - regs8051[i].base, - 8 * rbank + regs8051[i].offset); + if (regs8051[i].type != REG_BIT) + { + if (strcmp (regs8051[i].base, "0") == 0) + emitcode ("", "%s = 0x%02x", + regs8051[i].dname, + 8 * rbank + regs8051[i].offset); + else + emitcode ("", "%s = %s + 0x%02x", + regs8051[i].dname, + regs8051[i].base, + 8 * rbank + regs8051[i].offset); + } } } @@ -2741,11 +3105,12 @@ genFunction (iCode * ic) /* if any registers used */ if (sym->regsUsed) { + bool bits_pushed = FALSE; /* save the registers used */ for (i = 0; i < sym->regsUsed->size; i++) { if (bitVectBitValue (sym->regsUsed, i)) - emitcode ("push", "%s", mcs51_regWithIdx (i)->dname); + bits_pushed = pushReg (i, bits_pushed); } } } @@ -2877,6 +3242,7 @@ genFunction (iCode * ic) /* if any registers used */ if (sym->regsUsed) { + bool bits_pushed = FALSE; /* save the registers used */ for (i = 0; i < sym->regsUsed->size; i++) { @@ -2885,7 +3251,7 @@ genFunction (iCode * ic) /* remember one saved register for later usage */ if (calleesaves_saved_register < 0) calleesaves_saved_register = i; - emitcode ("push", "%s", mcs51_regWithIdx (i)->dname); + bits_pushed = pushReg (i, bits_pushed); _G.nRegsSaved++; } } @@ -3097,8 +3463,18 @@ genEndFunction (iCode * ic) if (IFFUNC_ISCRITICAL (sym->type)) { - emitcode ("pop", "psw"); /* restore ea via c in psw */ - emitcode ("mov", "ea,c"); + if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic)))) + { + emitcode ("rlc", "a"); /* save c in a */ + emitcode ("pop", "psw"); /* restore ea via c in psw */ + emitcode ("mov", "ea,c"); + emitcode ("rrc", "a"); /* restore c from a */ + } + else + { + emitcode ("pop", "psw"); /* restore ea via c in psw */ + emitcode ("mov", "ea,c"); + } } if ((IFFUNC_ISREENT (sym->type) || options.stackAuto)) @@ -3159,11 +3535,12 @@ genEndFunction (iCode * ic) /* if any registers used */ if (sym->regsUsed) { + bool bits_popped = FALSE; /* save the registers used */ for (i = sym->regsUsed->size; i >= 0; i--) { if (bitVectBitValue (sym->regsUsed, i)) - emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname); + bits_popped = popReg (i, bits_popped); } } } @@ -3256,7 +3633,14 @@ genEndFunction (iCode * ic) debugFile->writeEndFunction (currFunc, ic, 1); } - emitcode ("ret", ""); + if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type))) + { + emitcode ("ljmp", "__sdcc_banked_ret"); + } + else + { + emitcode ("ret", ""); + } } if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep) @@ -3374,6 +3758,13 @@ genRet (iCode * ic) aopOp (IC_LEFT (ic), ic, FALSE); size = AOP_SIZE (IC_LEFT (ic)); + + if (IS_BIT(_G.currentFunc->etype)) + { + movc (aopGet (IC_LEFT (ic), 0, FALSE, FALSE)); + size = 0; + } + while (size--) { char *l; @@ -3394,16 +3785,13 @@ genRet (iCode * ic) } } - if (pushed) + while (pushed) { - while (pushed) - { - pushed--; - if (strcmp (fReturn[pushed], "a")) - emitcode ("pop", fReturn[pushed]); - else - emitcode ("pop", "acc"); - } + pushed--; + if (strcmp (fReturn[pushed], "a")) + emitcode ("pop", fReturn[pushed]); + else + emitcode ("pop", "acc"); } freeAsmop (IC_LEFT (ic), NULL, ic, TRUE); @@ -3486,10 +3874,7 @@ genPlusIncr (iCode * ic) if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) return FALSE; - /* if the literal value of the right hand side - is greater than 4 then it is not worth it */ - if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4) - return FALSE; + icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit); D(emitcode ("; genPlusIncr","")); @@ -3596,6 +3981,11 @@ genPlusIncr (iCode * ic) return TRUE; } + /* if the literal value of the right hand side + is greater than 4 then it is not worth it */ + if (icount > 4) + return FALSE; + /* if the sizes are greater than 1 then we cannot */ if (AOP_SIZE (IC_RESULT (ic)) > 1 || AOP_SIZE (IC_LEFT (ic)) > 1) @@ -3923,7 +4313,7 @@ release: } /*-----------------------------------------------------------------*/ -/* genMinusDec :- does subtraction with deccrement if possible */ +/* genMinusDec :- does subtraction with decrement if possible */ /*-----------------------------------------------------------------*/ static bool genMinusDec (iCode * ic) @@ -4136,22 +4526,35 @@ genMinus (iCode * ic) while (size--) { - if (useCarry || ((lit >> (offset * 8)) & 0x0FFL)) { + if (useCarry || ((lit >> (offset * 8)) & 0x0FFL)) + { MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE)); - if (!offset && !size && lit== (unsigned long) -1) { - emitcode ("dec", "a"); - } else if (!useCarry) { - /* first add without previous c */ - emitcode ("add", "a,#0x%02x", - (unsigned int) ((lit >> (offset * 8)) & 0x0FFL)); - useCarry = TRUE; - } else { - emitcode ("addc", "a,#0x%02x", - (unsigned int) ((lit >> (offset * 8)) & 0x0FFL)); - } - aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE)); - } else { + if (!offset && !size && lit== (unsigned long) -1) + { + emitcode ("dec", "a"); + } + else if (!useCarry) + { + /* first add without previous c */ + emitcode ("add", "a,#0x%02x", + (unsigned int) ((lit >> (offset * 8)) & 0x0FFL)); + useCarry = TRUE; + } + else + { + emitcode ("addc", "a,#0x%02x", + (unsigned int) ((lit >> (offset * 8)) & 0x0FFL)); + } + aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE)); + } + else + { /* no need to add zeroes */ + if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)))) + { + aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), offset, FALSE, FALSE), + offset, isOperandVolatile (IC_RESULT (ic), FALSE)); + } offset++; } } @@ -4178,13 +4581,17 @@ genMinus (iCode * ic) emitcode ("subb", "a,b"); popB (pushedB); } else { + /* reverse subtraction with 2's complement */ + if (offset == 0) + emitcode( "setb", "c"); + else + emitcode( "cpl", "c"); wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash"); MOVA (aopGet(rightOp, offset, FALSE, TRUE)); - if (offset == 0) { - emitcode( "setb", "c"); - } emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE)); emitcode("cpl", "a"); + if (size) /* skip if last byte */ + emitcode( "cpl", "c"); } } else { MOVA (aopGet (leftOp, offset, FALSE, FALSE)); @@ -5246,7 +5653,7 @@ genCmpLt (iCode * ic, iCode * ifx) aopOp (right, ic, FALSE); aopOp (result, ic, TRUE); - genCmp (left, right, result, ifx, sign,ic); + genCmp (left, right, result, ifx, sign, ic); freeAsmop (result, NULL, ic, TRUE); } @@ -6030,12 +6437,12 @@ genAnd (iCode * ic, iCode * ifx) MOVA (aopGet (right, offset, FALSE, FALSE)); emitcode("anl", "a,b"); } - } else { + } else { MOVA (aopGet (right, offset, FALSE, FALSE)); - emitcode ("anl", "a,%s", + emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE)); + } } - } emitcode ("jnz", "%05d$", tlbl->key + 100); offset++; } @@ -6736,7 +7143,7 @@ genInline (iCode * ic) else { /* Add \n for labels, not dirs such as c:\mydir */ - if ( (*bp == ':') && (isspace(bp[1])) ) + if ( (*bp == ':') && (isspace((unsigned char)bp[1])) ) { bp++; *bp = '\0'; @@ -6893,6 +7300,140 @@ genGetHbit (iCode * ic) freeAsmop (result, NULL, ic, TRUE); } +/*-----------------------------------------------------------------*/ +/* genGetAbit - generates code get a single bit */ +/*-----------------------------------------------------------------*/ +static void +genGetAbit (iCode * ic) +{ + operand *left, *right, *result; + int shCount; + + D(emitcode ("; genGetAbit","")); + + left = IC_LEFT (ic); + right = IC_RIGHT (ic); + result = IC_RESULT (ic); + aopOp (left, ic, FALSE); + aopOp (right, ic, FALSE); + aopOp (result, ic, FALSE); + + shCount = (int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit); + + /* get the needed byte into a */ + MOVA (aopGet (left, shCount / 8, FALSE, FALSE)); + shCount %= 8; + if (AOP_TYPE (result) == AOP_CRY) + { + if ((shCount) == 7) + emitcode ("rlc", "a"); + else if ((shCount) == 0) + emitcode ("rrc", "a"); + else + emitcode ("mov", "c,acc[%d]", shCount); + outBitC (result); + } + else + { + switch (shCount) + { + case 2: + emitcode ("rr", "a"); + //fallthrough + case 1: + emitcode ("rr", "a"); + //fallthrough + case 0: + emitcode ("anl", "a,#0x01"); + break; + case 3: + case 5: + emitcode ("mov", "c,acc[%d]", shCount); + emitcode ("clr", "a"); + emitcode ("rlc", "a"); + break; + case 4: + emitcode ("swap", "a"); + emitcode ("anl", "a,#0x01"); + break; + case 6: + emitcode ("rl", "a"); + //fallthrough + case 7: + emitcode ("rl", "a"); + emitcode ("anl", "a,#0x01"); + break; + } + outAcc (result); + } + + freeAsmop (left, NULL, ic, TRUE); + freeAsmop (right, NULL, ic, TRUE); + freeAsmop (result, NULL, ic, TRUE); +} + +/*-----------------------------------------------------------------*/ +/* genGetByte - generates code get a single byte */ +/*-----------------------------------------------------------------*/ +static void +genGetByte (iCode * ic) +{ + operand *left, *right, *result; + int offset; + + D(emitcode ("; genGetByte","")); + + left = IC_LEFT (ic); + right = IC_RIGHT (ic); + result = IC_RESULT (ic); + aopOp (left, ic, FALSE); + aopOp (right, ic, FALSE); + aopOp (result, ic, FALSE); + + offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8; + aopPut (result, + aopGet (left, offset, FALSE, FALSE), + 0, + isOperandVolatile (result, FALSE)); + + freeAsmop (left, NULL, ic, TRUE); + freeAsmop (right, NULL, ic, TRUE); + freeAsmop (result, NULL, ic, TRUE); +} + +/*-----------------------------------------------------------------*/ +/* genGetWord - generates code get two bytes */ +/*-----------------------------------------------------------------*/ +static void +genGetWord (iCode * ic) +{ + operand *left, *right, *result; + int offset; + + D(emitcode ("; genGetWord","")); + + left = IC_LEFT (ic); + right = IC_RIGHT (ic); + result = IC_RESULT (ic); + aopOp (left, ic, FALSE); + aopOp (right, ic, FALSE); + aopOp (result, ic, FALSE); + + offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8; + aopPut (result, + aopGet (left, offset, FALSE, FALSE), + 0, + isOperandVolatile (result, FALSE)); + aopPut (result, + aopGet (left, offset+1, FALSE, FALSE), + 1, + isOperandVolatile (result, FALSE)); + + freeAsmop (left, NULL, ic, TRUE); + freeAsmop (right, NULL, ic, TRUE); + freeAsmop (result, NULL, ic, TRUE); +} + /*-----------------------------------------------------------------*/ /* genSwap - generates code to swap nibbles or bytes */ /*-----------------------------------------------------------------*/ @@ -9684,6 +10225,7 @@ genIfx (iCode * ic, iCode * popIc) { operand *cond = IC_COND (ic); int isbit = 0; + char *dup = NULL; D(emitcode ("; genIfx","")); @@ -9693,8 +10235,12 @@ genIfx (iCode * ic, iCode * popIc) if (AOP_TYPE (cond) != AOP_CRY) toBoolean (cond); else - isbit = 1; - /* the result is now in the accumulator */ + { + isbit = 1; + if (AOP(cond)->aopu.aop_dir) + dup = Safe_strdup(AOP(cond)->aopu.aop_dir); + } + /* the result is now in the accumulator or a directly addressable bit */ freeAsmop (cond, NULL, ic, TRUE); /* if there was something to be popped then do it */ @@ -9702,7 +10248,9 @@ genIfx (iCode * ic, iCode * popIc) genIpop (popIc); /* if the condition is a bit variable */ - if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond)) + if (isbit && dup) + genIfxJump(ic, dup, NULL, NULL, NULL); + else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond)) genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL); else if (isbit && !IS_ITEMP (cond)) genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL); @@ -10301,15 +10849,17 @@ genDjnz (iCode * ic, iCode * ifx) static void genReceive (iCode * ic) { - int size = getSize (operandType (IC_RESULT (ic))); - int offset = 0; + int size = getSize (operandType (IC_RESULT (ic))); + int offset = 0; + D(emitcode ("; genReceive","")); - if (ic->argreg == 1) { /* first parameter */ + if (ic->argreg == 1) + { /* first parameter */ if (isOperandInFarSpace (IC_RESULT (ic)) && (OP_SYMBOL (IC_RESULT (ic))->isspilt || - IS_TRUE_SYMOP (IC_RESULT (ic)))) { - + IS_TRUE_SYMOP (IC_RESULT (ic)))) + { regs *tempRegs[4]; int receivingA = 0; int roffset = 0; @@ -10351,33 +10901,48 @@ genReceive (iCode * ic) } offset = fReturnSizeMCS51 - size; - while (size--) { + while (size--) + { emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ? fReturn[fReturnSizeMCS51 - offset - 1] : "acc")); offset++; - } + } aopOp (IC_RESULT (ic), ic, FALSE); size = AOP_SIZE (IC_RESULT (ic)); offset = 0; - while (size--) { + while (size--) + { emitcode ("pop", "acc"); aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE)); - } - - } else { + } + } + else + { _G.accInUse++; aopOp (IC_RESULT (ic), ic, FALSE); _G.accInUse--; - assignResultValue (IC_RESULT (ic)); - } - } else { /* second receive onwards */ + assignResultValue (IC_RESULT (ic), NULL); + } + } + else if (ic->argreg > 12) + { /* bit parameters */ + if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5) + { + aopOp (IC_RESULT (ic), ic, FALSE); + emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]); + outBitC(IC_RESULT (ic)); + } + } + else + { /* other parameters */ int rb1off ; aopOp (IC_RESULT (ic), ic, FALSE); rb1off = ic->argreg; - while (size--) { + while (size--) + { aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE)); - } - } + } + } release: freeAsmop (IC_RESULT (ic), NULL, ic, TRUE); @@ -10714,6 +11279,18 @@ gen51Code (iCode * lic) genGetHbit (ic); break; + case GETABIT: + genGetAbit (ic); + break; + + case GETBYTE: + genGetByte (ic); + break; + + case GETWORD: + genGetWord (ic); + break; + case LEFT_OP: genLeftShift (ic); break;