X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Fmcs51%2Fgen.c;h=c9b86b9725967ccc04255d6728639214d3f45a9e;hb=44ea48587bdb833449a28658128fdaa58e7ad76f;hp=7ae3fa4edbb9078cf84aa7c4cdb2ef5e83cadb0d;hpb=195ee3f3ee25ce2c5f2a59fbd2779c4cb80527c3;p=fw%2Fsdcc diff --git a/src/mcs51/gen.c b/src/mcs51/gen.c index 7ae3fa4e..c9b86b97 100644 --- a/src/mcs51/gen.c +++ b/src/mcs51/gen.c @@ -458,7 +458,7 @@ getTempRegs(regs **tempRegs, int size, iCode *ic) } freeBitVect(freeRegs); - return 1; + return 0; } @@ -1350,6 +1350,50 @@ aopGet (operand * oper, int offset, bool bit16, bool dname) "aopget got unsupported aop->type"); exit (1); } + +/*-----------------------------------------------------------------*/ +/* aopPutUsesAcc - indicates ahead of time whether aopPut() will */ +/* clobber the accumulator */ +/*-----------------------------------------------------------------*/ +static bool +aopPutUsesAcc (operand * oper, const char *s, int offset) +{ + asmop * aop = AOP (oper); + + if (offset > (aop->size - 1)) + return FALSE; + + switch (aop->type) + { + case AOP_DUMMY: + return TRUE; + case AOP_DIR: + return FALSE; + case AOP_REG: + wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a")); + return FALSE; + case AOP_DPTR: + return TRUE; + case AOP_R0: + case AOP_R1: + return ((aop->paged) || (*s == '@')); + case AOP_STK: + return (*s == '@'); + case AOP_CRY: + return (!aop->aopu.aop_dir || strcmp(s, aop->aopu.aop_dir)); + case AOP_STR: + return FALSE; + case AOP_IMMD: + return FALSE; + case AOP_ACC: + return FALSE; + default: + /* Error case --- will have been caught already */ + wassert(0); + return FALSE; + } +} + /*-----------------------------------------------------------------*/ /* aopPut - puts a string for a aop and indicates if acc is in use */ /*-----------------------------------------------------------------*/ @@ -1378,16 +1422,13 @@ aopPut (operand * result, const char *s, int offset, bool bvolatile) case AOP_DIR: if (SPEC_SCLS (getSpec (operandType (result))) == S_SFR && offset) - sprintf (d, "(%s >> %d)", - aop->aopu.aop_dir, offset * 8); + sprintf (d, "(%s >> %d)", aop->aopu.aop_dir, offset * 8); else if (offset) - sprintf (d, "(%s + %d)", - aop->aopu.aop_dir, offset); + sprintf (d, "(%s + %d)", aop->aopu.aop_dir, offset); else sprintf (d, "%s", aop->aopu.aop_dir); - if (strcmp (d, s) || - bvolatile) + if (strcmp (d, s) || bvolatile) emitcode ("mov", "%s,%s", d, s); if (!strcmp (d, "acc")) accuse = TRUE; @@ -1461,7 +1502,6 @@ aopPut (operand * result, const char *s, int offset, bool bvolatile) { MOVA (s); emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name); - } else if (*s == '@') { @@ -1803,7 +1843,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; } @@ -2197,6 +2236,7 @@ assignResultValue (operand * oper, operand * func) int offset = 0; int size = AOP_SIZE (oper); bool accuse = FALSE; + bool pushedA = FALSE; if (func && IS_BIT (OP_SYM_ETYPE (func))) { @@ -2204,8 +2244,15 @@ assignResultValue (operand * oper, operand * func) return FALSE; } + if ((size > 3) && aopPutUsesAcc (oper, fReturn[offset], offset)) + { + emitcode ("push", "acc"); + pushedA = TRUE; + } while (size--) { + if ((offset == 3) && pushedA) + emitcode ("pop", "acc"); accuse |= aopPut (oper, fReturn[offset], offset, isOperandVolatile (oper, FALSE)); offset++; } @@ -2365,7 +2412,7 @@ static void saveRBank (int bank, iCode * ic, bool pushPsw) { int i; - int count = mcs51_nRegs + (pushPsw ? 1 : 0); + int count = 8 + ((mcs51_nRegs > 8) ? 1 : 0) + (pushPsw ? 1 : 0); asmop *aop = NULL; regs *r = NULL; @@ -2388,7 +2435,7 @@ saveRBank (int bank, iCode * ic, bool pushPsw) emitcode ("mov", "%s,a", spname); } - for (i = 0; i < mcs51_nRegs; i++) + for (i = 0; i < 8; i++) { if (options.useXstack) { @@ -2403,6 +2450,22 @@ saveRBank (int bank, iCode * ic, bool pushPsw) regs8051[i].base, 8 * bank + regs8051[i].offset); } + if (mcs51_nRegs > 8) + { + if (options.useXstack) + { + emitcode ("mov", "a,bits"); + emitcode ("movx", "@%s,a", r->name); + if (--count) + emitcode ("inc", "%s", r->name); + } + else + { + emitcode ("push", "bits"); + } + BitBankUsed = 1; + } + if (pushPsw) { if (options.useXstack) @@ -2469,7 +2532,21 @@ unsaveRBank (int bank, iCode * ic, bool popPsw) } } - for (i = (mcs51_nRegs - 1); i >= 0; i--) + if (mcs51_nRegs > 8) + { + if (options.useXstack) + { + emitcode ("dec", "%s", r->name); + emitcode ("movx", "a,@%s", r->name); + emitcode ("mov", "bits,a"); + } + else + { + emitcode ("pop", "bits"); + } + } + + for (i = 7; i >= 0; i--) { if (options.useXstack) { @@ -4314,7 +4391,7 @@ release: } /*-----------------------------------------------------------------*/ -/* genMinusDec :- does subtraction with deccrement if possible */ +/* genMinusDec :- does subtraction with decrement if possible */ /*-----------------------------------------------------------------*/ static bool genMinusDec (iCode * ic) @@ -4424,9 +4501,23 @@ genMinusDec (iCode * ic) same */ if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic)))) { + char *l; + + if (aopGetUsesAcc (IC_LEFT (ic), 0)) + { + MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE)); + l = "a"; + } + else + { + l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE); + } while (icount--) - emitcode ("dec", "%s", aopGet (IC_RESULT (ic), 0, FALSE, FALSE)); + emitcode ("dec", "%s", l); + + if (AOP_NEEDSACC (IC_RESULT (ic))) + aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE)); return TRUE; } @@ -4527,22 +4618,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)); + 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)); } - aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE)); - } else { + 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++; } } @@ -4569,13 +4673,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)); @@ -4829,7 +4937,7 @@ genMult (iCode * ic) D(emitcode ("; genMult","")); - /* assign the amsops */ + /* assign the asmops */ aopOp (left, ic, FALSE); aopOp (right, ic, FALSE); aopOp (result, ic, TRUE); @@ -4905,6 +5013,8 @@ genDivOneByte (operand * left, { bool lUnsigned, rUnsigned, pushedB; bool runtimeSign, compiletimeSign; + bool accuse = FALSE; + bool pushedA = FALSE; symbol *lbl; int size, offset; @@ -5068,20 +5178,32 @@ genDivOneByte (operand * left, emitcode ("inc", "a"); emitcode ("", "%05d$:", (lbl->key + 100)); - aopPut (result, "a", 0, isOperandVolatile (result, FALSE)); + accuse = aopPut (result, "a", 0, isOperandVolatile (result, FALSE)); if (size > 0) { /* msb is 0x00 or 0xff depending on the sign */ if (runtimeSign) { + if (accuse) + { + emitcode ("push", "acc"); + pushedA = TRUE; + } emitcode ("mov", "c,F0"); emitcode ("subb", "a,acc"); while (size--) aopPut (result, "a", offset++, isOperandVolatile (result, FALSE)); } else /* compiletimeSign */ - while (size--) - aopPut (result, "#0xff", offset++, isOperandVolatile (result, FALSE)); + { + if (aopPutUsesAcc (result, "#0xFF", offset)) + { + emitcode ("push", "acc"); + pushedA = TRUE; + } + while (size--) + aopPut (result, "#0xff", offset++, isOperandVolatile (result, FALSE)); + } } } else @@ -5091,6 +5213,8 @@ genDivOneByte (operand * left, aopPut (result, zero, offset++, isOperandVolatile (result, FALSE)); } + if (pushedA) + emitcode ("pop", "acc"); popB (pushedB); } @@ -6365,10 +6489,25 @@ genAnd (iCode * ic, iCode * ifx) } else { - if (AOP_TYPE (left) == AOP_ACC && offset == 0) + if (AOP_TYPE (left) == AOP_ACC) { + if (offset) + emitcode("mov", "a,b"); emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE)); } + else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset)) + { + emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE)); + MOVA (aopGet (right, offset, FALSE, FALSE)); + emitcode ("anl", "a,b"); + aopPut (result, "a", offset, isOperandVolatile (result, FALSE)); + } + else if (aopGetUsesAcc (left, offset)) + { + MOVA (aopGet (left, offset, FALSE, FALSE)); + emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE)); + aopPut (result, "a", offset, isOperandVolatile (result, FALSE)); + } else { MOVA (aopGet (right, offset, FALSE, FALSE)); @@ -6490,11 +6629,21 @@ genAnd (iCode * ic, iCode * ifx) emitcode("mov", "a,b"); emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE)); } + else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset)) + { + emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE)); + MOVA (aopGet (right, offset, FALSE, FALSE)); + emitcode ("anl", "a,b"); + } + else if (aopGetUsesAcc (left, offset)) + { + MOVA (aopGet (left, offset, FALSE, FALSE)); + emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE)); + } else { MOVA (aopGet (right, offset, FALSE, FALSE)); - emitcode ("anl", "a,%s", - aopGet (left, offset, FALSE, FALSE)); + emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE)); } aopPut (result, "a", offset, isOperandVolatile (result, FALSE)); } @@ -6710,6 +6859,19 @@ genOr (iCode * ic, iCode * ifx) emitcode("mov", "a,b"); emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE)); } + else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset)) + { + emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE)); + MOVA (aopGet (right, offset, FALSE, FALSE)); + emitcode ("orl", "a,b"); + aopPut (result, "a", offset, isOperandVolatile (result, FALSE)); + } + else if (aopGetUsesAcc (left, offset)) + { + MOVA (aopGet (left, offset, FALSE, FALSE)); + emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE)); + aopPut (result, "a", offset, isOperandVolatile (result, FALSE)); + } else { MOVA (aopGet (right, offset, FALSE, FALSE)); @@ -6799,11 +6961,21 @@ genOr (iCode * ic, iCode * ifx) emitcode("mov", "a,b"); emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE)); } + else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset)) + { + emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE)); + MOVA (aopGet (right, offset, FALSE, FALSE)); + emitcode ("orl", "a,b"); + } + else if (aopGetUsesAcc (left, offset)) + { + MOVA (aopGet (left, offset, FALSE, FALSE)); + emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE)); + } else { MOVA (aopGet (right, offset, FALSE, FALSE)); - emitcode ("orl", "a,%s", - aopGet (left, offset, FALSE, FALSE)); + emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE)); } aopPut (result, "a", offset, isOperandVolatile (result, FALSE)); } @@ -6998,6 +7170,19 @@ genXor (iCode * ic, iCode * ifx) emitcode("mov", "a,b"); emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE)); } + else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset)) + { + emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE)); + MOVA (aopGet (right, offset, FALSE, FALSE)); + emitcode ("xrl", "a,b"); + aopPut (result, "a", offset, isOperandVolatile (result, FALSE)); + } + else if (aopGetUsesAcc (left, offset)) + { + MOVA (aopGet (left, offset, FALSE, FALSE)); + emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE)); + aopPut (result, "a", offset, isOperandVolatile (result, FALSE)); + } else { MOVA (aopGet (right, offset, FALSE, FALSE)); @@ -7083,11 +7268,21 @@ genXor (iCode * ic, iCode * ifx) emitcode("mov", "a,b"); emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE)); } + else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset)) + { + emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE)); + MOVA (aopGet (right, offset, FALSE, FALSE)); + emitcode ("xrl", "a,b"); + } + else if (aopGetUsesAcc (left, offset)) + { + MOVA (aopGet (left, offset, FALSE, FALSE)); + emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE)); + } else { MOVA (aopGet (right, offset, FALSE, FALSE)); - emitcode ("xrl", "a,%s", - aopGet (left, offset, FALSE, TRUE)); + emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE)); } aopPut (result, "a", offset, isOperandVolatile (result, FALSE)); } @@ -7284,6 +7479,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 */ /*-----------------------------------------------------------------*/ @@ -7533,7 +7862,7 @@ movLeft2Result (operand * left, int offl, /* MSB sign in acc.7 ! */ if (getDataSize (left) == offl + 1) { - emitcode ("mov", "a,%s", l); + MOVA (l); aopPut (result, "a", offr, isOperandVolatile (result, FALSE)); } } @@ -7848,21 +8177,47 @@ static void shiftL2Left2Result (operand * left, int offl, operand * result, int offr, int shCount) { + char * x; + bool pushedB = FALSE; + bool usedB = FALSE; + if (sameRegs (AOP (result), AOP (left)) && ((offl + MSB16) == offr)) { /* don't crash result[offr] */ MOVA (aopGet (left, offl, FALSE, FALSE)); emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE)); + x = aopGet (result, offr, FALSE, FALSE); + } + else if (aopGetUsesAcc (result, offr)) + { + movLeft2Result (left, offl, result, offr, 0); + pushedB = pushB (); + usedB = TRUE; + emitcode ("mov", "b,%s", aopGet (left, offl + MSB16, FALSE, FALSE)); + MOVA (aopGet (result, offr, FALSE, FALSE)); + emitcode ("xch", "a,b"); + x = "b"; } else { movLeft2Result (left, offl, result, offr, 0); MOVA (aopGet (left, offl + MSB16, FALSE, FALSE)); + x = aopGet (result, offr, FALSE, FALSE); } /* ax << shCount (x = lsb(result)) */ - AccAXLsh (aopGet (result, offr, FALSE, FALSE), shCount); - aopPut (result, "a", offr + MSB16, isOperandVolatile (result, FALSE)); + AccAXLsh (x, shCount); + if (usedB) + { + emitcode ("xch", "a,b"); + aopPut (result, "a", offr, isOperandVolatile (result, FALSE)); + aopPut (result, "b", offr + MSB16, isOperandVolatile (result, FALSE)); + popB (pushedB); + } + else + { + aopPut (result, "a", offr + MSB16, isOperandVolatile (result, FALSE)); + } } @@ -7874,23 +8229,45 @@ shiftR2Left2Result (operand * left, int offl, operand * result, int offr, int shCount, int sign) { + char * x; + bool pushedB = FALSE; + bool usedB = FALSE; + if (sameRegs (AOP (result), AOP (left)) && ((offl + MSB16) == offr)) { /* don't crash result[offr] */ MOVA (aopGet (left, offl, FALSE, FALSE)); emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE)); + x = aopGet (result, offr, FALSE, FALSE); + } + else if (aopGetUsesAcc (result, offr)) + { + movLeft2Result (left, offl, result, offr, 0); + pushedB = pushB (); + usedB = TRUE; + emitcode ("mov", "b,%s", aopGet (result, offr, FALSE, FALSE)); + MOVA (aopGet (left, offl + MSB16, FALSE, FALSE)); + x = "b"; } else { movLeft2Result (left, offl, result, offr, 0); MOVA (aopGet (left, offl + MSB16, FALSE, FALSE)); + x = aopGet (result, offr, FALSE, FALSE); } /* a:x >> shCount (x = lsb(result)) */ if (sign) - AccAXRshS (aopGet (result, offr, FALSE, FALSE), shCount); + AccAXRshS (x, shCount); else - AccAXRsh (aopGet (result, offr, FALSE, FALSE), shCount); + AccAXRsh (x, shCount); + if (usedB) + { + emitcode ("xch", "a,b"); + aopPut (result, "a", offr, isOperandVolatile (result, FALSE)); + emitcode ("xch", "a,b"); + popB (pushedB); + } if (getDataSize (result) > 1) aopPut (result, "a", offr + MSB16, isOperandVolatile (result, FALSE)); } @@ -7906,7 +8283,16 @@ shiftLLeftOrResult (operand * left, int offl, /* shift left accumulator */ AccLsh (shCount); /* or with result */ - emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE)); + if (aopGetUsesAcc (result, offr)) + { + emitcode ("xch", "a,b"); + MOVA (aopGet (result, offr, FALSE, FALSE)); + emitcode ("orl", "a,b"); + } + else + { + emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE)); + } /* back to result */ aopPut (result, "a", offr, isOperandVolatile (result, FALSE)); } @@ -8358,7 +8744,7 @@ static void shiftRLong (operand * left, int offl, operand * result, int sign) { - int isSameRegs=sameRegs(AOP(left),AOP(result)); + int isSameRegs = sameRegs (AOP (left), AOP (result)); if (isSameRegs && offl>1) { // we are in big trouble, but this shouldn't happen @@ -8921,6 +9307,15 @@ genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx) emitPtrByteGet (rname, ptype, FALSE); AccRsh (bstr); emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen)); + if (!SPEC_USIGN (etype)) + { + /* signed bitfield */ + symbol *tlbl = newiTempLabel (NULL); + + emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100); + emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen)); + emitcode ("", "%05d$:", tlbl->key + 100); + } aopPut (result, "a", offset++, isOperandVolatile (result, FALSE)); goto finish; } @@ -8940,15 +9335,36 @@ genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx) { emitPtrByteGet (rname, ptype, FALSE); emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen)); + if (!SPEC_USIGN (etype)) + { + /* signed bitfield */ + symbol *tlbl = newiTempLabel (NULL); + + emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100); + emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen)); + emitcode ("", "%05d$:", tlbl->key + 100); + } aopPut (result, "a", offset++, isOperandVolatile (result, FALSE)); } finish: if (offset < rsize) { + char *source; + + if (SPEC_USIGN (etype)) + source = zero; + else + { + /* signed bitfield: sign extension with 0x00 or 0xff */ + emitcode ("rlc", "a"); + emitcode ("subb", "a,acc"); + + source = "a"; + } rsize -= offset; while (rsize--) - aopPut (result, zero, offset++, isOperandVolatile (result, FALSE)); + aopPut (result, source, offset++, isOperandVolatile (result, FALSE)); } } @@ -10706,7 +11122,8 @@ genReceive (iCode * ic) if (ic->argreg == 1) { /* first parameter */ - if (isOperandInFarSpace (IC_RESULT (ic)) && + if ((isOperandInFarSpace (IC_RESULT (ic)) || + isOperandInPagedSpace (IC_RESULT (ic))) && (OP_SYMBOL (IC_RESULT (ic))->isspilt || IS_TRUE_SYMOP (IC_RESULT (ic)))) { @@ -11129,6 +11546,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;