#endif
#endif
+#define BETTER_LITERAL_SHIFT
+
char *aopLiteral (value * val, int offset);
/* this is the down and dirty file with all kinds of
#define CLRC emitcode("clr","c")
#define SETC emitcode("setb","c")
+// A scratch register which will be used to hold
+// result bytes from operands in far space via DPTR2.
+#define DP2_RESULT_REG "ap"
+
static lineNode *lineHead = NULL;
static lineNode *lineCurr = NULL;
{
_currentDPS = 0;
_desiredDPS = 0;
+#ifdef BETTER_LITERAL_SHIFT
+ _lazyDPS++;
+#else
_lazyDPS = 1;
+#endif
}
/*-----------------------------------------------------------------*/
static void
_endLazyDPSEvaluation (void)
{
- if (_currentDPS)
+#ifdef BETTER_LITERAL_SHIFT
+ _lazyDPS--;
+#else
+ _lazyDPS = 0;
+#endif
+ if (!_lazyDPS)
+ {
+ if (_currentDPS)
{
genSetDPTR (0);
_flushLazyDPS ();
}
- _lazyDPS = 0;
- _currentDPS = 0;
- _desiredDPS = 0;
+ _currentDPS = 0;
+ _desiredDPS = 0;
+ }
}
if (useDP2)
{
- /* genSetDPTR(1); */
emitcode ("mov", "dpx1,#0x40");
emitcode ("mov", "dph1,#0x00");
emitcode ("mov", "dpl1, a");
- /* genSetDPTR(0); */
}
else
{
/*------------------------------------------------------------------*/
/* aopGet - for fetching value of the aop */
/* */
-/* Set canClobberACC if you are aure it is OK to clobber the value */
+/* Set canClobberACC if you are sure it is OK to clobber the value */
/* in the accumulator. Set it FALSE otherwise; FALSE is always safe, */
/* just less efficient. */
/*------------------------------------------------------------------*/
genSetDPTR (1);
if (!canClobberACC)
{
- emitcode ("xch", "a, ap");
+ emitcode ("xch", "a, %s", DP2_RESULT_REG);
}
}
genSetDPTR (0);
if (!canClobberACC)
{
- emitcode ("xch", "a, ap");
- return "ap";
+ emitcode ("xch", "a, %s", DP2_RESULT_REG);
+ return DP2_RESULT_REG;
}
}
return (dname ? "acc" : "a");
static void
toBoolean (operand * oper)
{
- int size = AOP_SIZE (oper) - 1;
- int offset = 1;
+ int size = AOP_SIZE (oper) - 1;
+ int offset = 1;
+ bool usedB = FALSE;
/* The generic part of a generic pointer should
* not participate in it's truth value.
}
_startLazyDPSEvaluation ();
- if (AOP_NEEDSACC (oper))
+ if (AOP_NEEDSACC (oper) && size)
{
+ usedB = TRUE;
emitcode ("push", "b");
emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE));
}
}
while (size--)
{
- if (AOP_NEEDSACC (oper))
+ if (usedB)
{
emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
}
}
_endLazyDPSEvaluation ();
- if (AOP_NEEDSACC (oper))
+ if (usedB)
{
emitcode ("mov", "a,b");
emitcode ("pop", "b");
int size = getSize (operandType (IC_RESULT (ic)));
/* Special case for 1 or 2 byte return in far space. */
- emitcode (";", "Kevin function call abuse #1");
-
MOVA (fReturn[0]);
if (size > 1)
{
emitcode ("push", "dpl1");
emitcode ("push", "dph1");
emitcode ("push", "dpx1");
- emitcode ("push", "ap");
+ emitcode ("push", DP2_RESULT_REG);
}
}
/* if this isr has no bank i.e. is going to
{
if (options.stack10bit)
{
- emitcode ("pop", "ap");
+ emitcode ("pop", DP2_RESULT_REG);
emitcode ("pop", "dpx1");
emitcode ("pop", "dph1");
emitcode ("pop", "dpl1");
}
}
+// Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
+// (because all three operands are in far space).
#define AOP_OP_3(ic) \
aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
"Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
}
+// Macro to aopOp all three operands of an ic. If this cannot be done,
+// the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
+// will be set TRUE. The caller must then handle the case specially, noting
+// that the IC_RESULT operand is not aopOp'd.
#define AOP_OP_3_NOFATAL(ic, rc) \
aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
} \
}
+// aopOp the left & right operands of an ic.
#define AOP_OP_2(ic) \
aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
+// convienience macro.
#define AOP_SET_LOCALS(ic) \
left = IC_LEFT(ic); \
right = IC_RIGHT(ic); \
result = IC_RESULT(ic);
+
+// Given an integer value of pushedSize bytes on the stack,
+// adjust it to be resultSize bytes, either by discarding
+// the most significant bytes or by zero-padding.
+//
+// On exit from this macro, pushedSize will have been adjusted to
+// equal resultSize, and ACC may be trashed.
+#define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
+ /* If the pushed data is bigger than the result, \
+ * simply discard unused bytes. Icky, but works. \
+ */ \
+ while (pushedSize > resultSize) \
+ { \
+ D (emitcode (";", "discarding unused result byte."););\
+ emitcode ("pop", "acc"); \
+ pushedSize--; \
+ } \
+ if (pushedSize < resultSize) \
+ { \
+ emitcode ("clr", "a"); \
+ /* Conversly, we haven't pushed enough here. \
+ * just zero-pad, and all is well. \
+ */ \
+ while (pushedSize < resultSize) \
+ { \
+ emitcode("push", "acc"); \
+ pushedSize++; \
+ } \
+ } \
+ assert(pushedSize == resultSize);
+
/*-----------------------------------------------------------------*/
/* genPlus - generates code for addition */
/*-----------------------------------------------------------------*/
bool pushResult = FALSE;
int rSize;
- D (emitcode (";", "genPlus ");
- );
+ D (emitcode (";", "genPlus "););
/* special cases :- */
AOP_OP_3_NOFATAL (ic, pushResult);
if (pushResult)
{
- D (emitcode (";", "genPlus: must push result: 3 ops in far space");
- );
+ D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
}
if (!pushResult)
size = getDataSize (IC_LEFT (ic));
rSize = getDataSize (IC_RESULT (ic));
- /* If the pushed data is bigger than the result,
- * simply discard unused bytes. Icky, but works.
- *
- * Should we throw a warning here? We're losing data...
- */
- while (size > rSize)
- {
- D (emitcode (";", "discarding unused result byte.");
- );
- emitcode ("pop", "acc");
- size--;
- offset--;
- }
- if (size < rSize)
- {
- emitcode ("clr", "a");
- /* Conversly, we haven't pushed enough here.
- * just zero-pad, and all is well.
- */
- while (size < rSize)
- {
- emitcode ("push", "acc");
- size++;
- offset++;
- }
- }
+ ADJUST_PUSHED_RESULT(size, rSize);
_startLazyDPSEvaluation ();
while (size--)
{
emitcode ("pop", "acc");
- aopPut (AOP (IC_RESULT (ic)), "a", --offset);
+ aopPut (AOP (IC_RESULT (ic)), "a", size);
}
_endLazyDPSEvaluation ();
}
int size = (getDataSize (result) - offset);
if (size > 0)
{
+ _startLazyDPSEvaluation();
if (sign)
{
emitcode ("rlc", "a");
emitcode ("subb", "a,acc");
while (size--)
+ {
aopPut (AOP (result), "a", offset++);
+ }
}
else
+ {
while (size--)
+ {
aopPut (AOP (result), zero, offset++);
+ }
+ }
+ _endLazyDPSEvaluation();
}
}
{
symbol *lbl = newiTempLabel (NULL);
- D (emitcode (";", "genMinusBits ");
- );
+ D (emitcode (";", "genMinusBits "););
if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
{
unsigned long lit = 0L;
bool pushResult = FALSE;
- D (emitcode (";", "genMinus ");
- );
+ D (emitcode (";", "genMinus "););
aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
size = getDataSize (IC_LEFT (ic));
rSize = getDataSize (IC_RESULT (ic));
- /* If the pushed data is bigger than the result,
- * simply discard unused bytes. Icky, but works.
- *
- * Should we throw a warning here? We're losing data...
- */
- while (size > getDataSize (IC_RESULT (ic)))
- {
- emitcode (";", "discarding unused result byte.");
- emitcode ("pop", "acc");
- size--;
- offset--;
- }
- if (size < rSize)
- {
- emitcode ("clr", "a");
- /* Conversly, we haven't pushed enough here.
- * just zero-pad, and all is well.
- */
- while (size < rSize)
- {
- emitcode ("push", "acc");
- size++;
- offset++;
- }
- }
+ ADJUST_PUSHED_RESULT(size, rSize);
+ _startLazyDPSEvaluation ();
while (size--)
{
emitcode ("pop", "acc");
- aopPut (AOP (IC_RESULT (ic)), "a", --offset);
+ aopPut (AOP (IC_RESULT (ic)), "a", size);
}
+ _endLazyDPSEvaluation ();
}
adjustArithmeticResult (ic);
operand *right = IC_RIGHT (ic);
operand *result = IC_RESULT (ic);
- D (emitcode (";", "genMult ");
- );
+ D (emitcode (";", "genMult "););
/* assign the amsops */
AOP_OP_3 (ic);
sym_link *letype, *retype;
int sign;
- D (emitcode (";", "genCmpLt ");
- );
+ D (emitcode (";", "genCmpLt "););
left = IC_LEFT (ic);
right = IC_RIGHT (ic);
operand *left, *right, *result;
symbol *tlbl;
- D (emitcode (";", "genAndOp ");
- );
+ D (emitcode (";", "genAndOp "););
/* note here that && operations that are in an
if statement are taken away by backPatchLabels
only those used in arthmetic operations remain */
- AOP_OP_3 (ic);
+ AOP_OP_2 (ic);
AOP_SET_LOCALS (ic);
/* if both are bit variables */
{
emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
+ freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+ freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+
+ aopOp (result,ic,FALSE, FALSE);
outBitC (result);
}
else
emitcode ("jz", "%05d$", tlbl->key + 100);
toBoolean (right);
emitcode ("", "%05d$:", tlbl->key + 100);
+ freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+ freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+
+ aopOp (result,ic,FALSE, FALSE);
outBitAcc (result);
}
-
- freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
- freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
- freeAsmop (result, NULL, ic, TRUE);
+ freeAsmop (result, NULL, ic, TRUE);
}
operand *left, *right, *result;
symbol *tlbl;
- D (emitcode (";", "genOrOp ");
- );
+ D (emitcode (";", "genOrOp "););
/* note here that || operations that are in an
if statement are taken away by backPatchLabels
only those used in arthmetic operations remain */
- AOP_OP_3 (ic);
+ AOP_OP_2 (ic);
AOP_SET_LOCALS (ic);
/* if both are bit variables */
{
emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
+ freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+ freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+
+ aopOp (result,ic,FALSE, FALSE);
+
outBitC (result);
}
else
emitcode ("jnz", "%05d$", tlbl->key + 100);
toBoolean (right);
emitcode ("", "%05d$:", tlbl->key + 100);
+ freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+ freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+
+ aopOp (result,ic,FALSE, FALSE);
+
outBitAcc (result);
}
- freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
- freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
freeAsmop (result, NULL, ic, TRUE);
}
ic->generated = 1;
}
+// Generate code to perform a bit-wise logic operation
+// on two operands in far space (assumed to already have been
+// aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
+// in far space. This requires pushing the result on the stack
+// then popping it into the result.
+static void
+genFarFarLogicOp(iCode *ic, char *logicOp)
+{
+ int size, resultSize, compSize;
+ int offset = 0;
+
+ D(emitcode(";", "%s special case for 3 far operands.", logicOp););
+ compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
+ AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
+
+ _startLazyDPSEvaluation();
+ for (size = compSize; (size--); offset++)
+ {
+ MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
+ emitcode ("mov", "%s, acc", DP2_RESULT_REG);
+ MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
+
+ emitcode (logicOp, "a,%s", DP2_RESULT_REG);
+ emitcode ("push", "acc");
+ }
+ _endLazyDPSEvaluation();
+
+ freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
+ freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
+ aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
+
+ resultSize = AOP_SIZE(IC_RESULT(ic));
+
+ ADJUST_PUSHED_RESULT(compSize, resultSize);
+
+ _startLazyDPSEvaluation();
+ while (compSize--)
+ {
+ emitcode ("pop", "acc");
+ aopPut (AOP (IC_RESULT (ic)), "a", compSize);
+ }
+ _endLazyDPSEvaluation();
+ freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
+}
+
+
/*-----------------------------------------------------------------*/
/* genAnd - code for and */
/*-----------------------------------------------------------------*/
unsigned long lit = 0L;
int bytelit = 0;
char buffer[10];
+ bool pushResult;
- D (emitcode (";", "genAnd ");
- );
+ D (emitcode (";", "genAnd "););
- AOP_OP_3 (ic);
+ AOP_OP_3_NOFATAL (ic, pushResult);
AOP_SET_LOCALS (ic);
+ if (pushResult)
+ {
+ genFarFarLogicOp(ic, "anl");
+ return;
+ }
+
#ifdef DEBUG_TYPE
emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
AOP_TYPE (result),
freeAsmop (result, NULL, ic, TRUE);
}
+
/*-----------------------------------------------------------------*/
/* genOr - code for or */
/*-----------------------------------------------------------------*/
operand *left, *right, *result;
int size, offset = 0;
unsigned long lit = 0L;
+ bool pushResult;
- D (emitcode (";", "genOr ");
- );
+ D (emitcode (";", "genOr "););
- AOP_OP_3 (ic);
+ AOP_OP_3_NOFATAL (ic, pushResult);
AOP_SET_LOCALS (ic);
+ if (pushResult)
+ {
+ genFarFarLogicOp(ic, "orl");
+ return;
+ }
+
+
#ifdef DEBUG_TYPE
emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
AOP_TYPE (result),
operand *left, *right, *result;
int size, offset = 0;
unsigned long lit = 0L;
+ bool pushResult;
- D (emitcode (";", "genXor ");
- );
+ D (emitcode (";", "genXor "););
- AOP_OP_3 (ic);
+ AOP_OP_3_NOFATAL (ic, pushResult);
AOP_SET_LOCALS (ic);
+ if (pushResult)
+ {
+ genFarFarLogicOp(ic, "xrl");
+ return;
+ }
+
#ifdef DEBUG_TYPE
emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
AOP_TYPE (result),
}
}
-#if 0
-//REMOVE ME!!!
+#ifdef BETTER_LITERAL_SHIFT
/*-----------------------------------------------------------------*/
/* AccSRsh - signed right shift accumulator by known count */
/*-----------------------------------------------------------------*/
}
#endif
-#if 0
-//REMOVE ME!!!
+#ifdef BETTER_LITERAL_SHIFT
/*-----------------------------------------------------------------*/
/* shiftR1Left2Result - shift right one byte from left to result */
/*-----------------------------------------------------------------*/
}
#endif
-#if 0
-//REMOVE ME!!!
+#ifdef BETTER_LITERAL_SHIFT
/*-----------------------------------------------------------------*/
/* shiftL1Left2Result - shift left one byte from left to result */
/*-----------------------------------------------------------------*/
shiftL1Left2Result (operand * left, int offl,
operand * result, int offr, int shCount)
{
- char *l;
- l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
- MOVA (l);
+ MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
/* shift left accumulator */
AccLsh (shCount);
aopPut (AOP (result), "a", offr);
}
#endif
-#if 0
-//REMOVE ME!!!
+#ifdef BETTER_LITERAL_SHIFT
/*-----------------------------------------------------------------*/
/* movLeft2Result - move byte from left to result */
/*-----------------------------------------------------------------*/
{
char *l;
if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
- {
- l = aopGet (AOP (left), offl, FALSE, FALSE, FALSE);
+ {
+ l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
if (*l == '@' && (IS_AOP_PREG (result)))
- {
+ {
emitcode ("mov", "a,%s", l);
aopPut (AOP (result), "a", offr);
- }
+ }
else
- {
+ {
if (!sign)
+ {
aopPut (AOP (result), l, offr);
+ }
else
{
/* MSB sign in acc.7 ! */
aopPut (AOP (result), "a", offr);
}
}
- }
- }
+ }
+ }
}
#endif
-#if 0
-//REMOVE ME!!!
+#ifdef BETTER_LITERAL_SHIFT
/*-----------------------------------------------------------------*/
/* AccAXRrl1 - right rotate c->a:x->c by 1 */
/*-----------------------------------------------------------------*/
}
#endif
-#if 0
+#ifdef BETTER_LITERAL_SHIFT
//REMOVE ME!!!
/*-----------------------------------------------------------------*/
/* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
}
#endif
-#if 0
-//REMOVE ME!!!
+#ifdef BETTER_LITERAL_SHIFT
/*-----------------------------------------------------------------*/
/* AccAXLsh1 - left shift a:x<-0 by 1 */
/*-----------------------------------------------------------------*/
}
#endif
-#if 0
-//REMOVE ME!!!
+#ifdef BETTER_LITERAL_SHIFT
/*-----------------------------------------------------------------*/
/* AccAXLsh - left shift a:x by known count (0..7) */
/*-----------------------------------------------------------------*/
}
#endif
-#if 0
+#ifdef BETTER_LITERAL_SHIFT
//REMOVE ME!!!
/*-----------------------------------------------------------------*/
/* AccAXRsh - right shift a:x known count (0..7) */
}
#endif
-#if 0
+#ifdef BETTER_LITERAL_SHIFT
//REMOVE ME!!!
/*-----------------------------------------------------------------*/
/* AccAXRshS - right shift signed a:x known count (0..7) */
}
#endif
-#if 0
-//REMOVE ME!!!
+#ifdef BETTER_LITERAL_SHIFT
+static void
+_loadLeftIntoAx(char **lsb,
+ operand *left,
+ operand *result,
+ int offl,
+ int offr)
+{
+ // Get the initial value from left into a pair of registers.
+ // MSB must be in A, LSB can be any register.
+ //
+ // If the result is held in registers, it is an optimization
+ // if the LSB can be held in the register which will hold the,
+ // result LSB since this saves us from having to copy it into
+ // the result following AccAXLsh.
+ //
+ // If the result is addressed indirectly, this is not a gain.
+ if (AOP_NEEDSACC(result))
+ {
+ char *leftByte;
+
+ _startLazyDPSEvaluation();
+ if (AOP_TYPE(left) == AOP_DPTR2)
+ {
+ // Get MSB in A.
+ MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
+ // get LSB in DP2_RESULT_REG.
+ leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
+ assert(!strcmp(leftByte, DP2_RESULT_REG));
+ }
+ else
+ {
+ // get LSB into DP2_RESULT_REG
+ leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
+ if (strcmp(leftByte, DP2_RESULT_REG))
+ {
+ emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
+ }
+ // And MSB in A.
+ leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
+ assert(strcmp(leftByte, DP2_RESULT_REG));
+ MOVA(leftByte);
+ }
+ _endLazyDPSEvaluation();
+ *lsb = DP2_RESULT_REG;
+ }
+ else
+ {
+ if (sameRegs (AOP (result), AOP (left)) &&
+ ((offl + MSB16) == offr))
+ {
+ /* don't crash result[offr] */
+ MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
+ emitcode ("xch", "a,%s",
+ aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
+ }
+ else
+ {
+ movLeft2Result (left, offl, result, offr, 0);
+ MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
+ }
+ *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
+ assert(strcmp(*lsb,"a"));
+ }
+}
+
+static void
+_storeAxResults(char *lsb,
+ operand *result,
+ int offr)
+{
+ _startLazyDPSEvaluation();
+ if (AOP_NEEDSACC(result))
+ {
+ /* We have to explicitly update the result LSB.
+ */
+ emitcode("xch","a,%s", lsb);
+ aopPut(AOP(result), "a", offr);
+ emitcode("mov","a,%s", lsb);
+ }
+ if (getDataSize (result) > 1)
+ {
+ aopPut (AOP (result), "a", offr + MSB16);
+ }
+ _endLazyDPSEvaluation();
+}
+
/*-----------------------------------------------------------------*/
/* shiftL2Left2Result - shift left two bytes from left to result */
/*-----------------------------------------------------------------*/
shiftL2Left2Result (operand * left, int offl,
operand * result, int offr, int shCount)
{
- if (sameRegs (AOP (result), AOP (left)) &&
- ((offl + MSB16) == offr))
- {
- /* don't crash result[offr] */
- MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
- emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE, FALSE));
- }
- else
- {
- movLeft2Result (left, offl, result, offr, 0);
- MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
- }
- /* ax << shCount (x = lsb(result)) */
- AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount);
- aopPut (AOP (result), "a", offr + MSB16);
+ char *lsb;
+
+ _loadLeftIntoAx(&lsb, left, result, offl, offr);
+
+ AccAXLsh (lsb, shCount);
+
+ _storeAxResults(lsb, result, offr);
}
#endif
-#if 0
-//REMOVE ME!!!
+#ifdef BETTER_LITERAL_SHIFT
/*-----------------------------------------------------------------*/
/* shiftR2Left2Result - shift right two bytes from left to result */
/*-----------------------------------------------------------------*/
operand * result, int offr,
int shCount, int sign)
{
- if (sameRegs (AOP (result), AOP (left)) &&
- ((offl + MSB16) == offr))
- {
- /* don't crash result[offr] */
- MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
- emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE, FALSE));
- }
- else
- {
- movLeft2Result (left, offl, result, offr, 0);
- MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
- }
+ char *lsb;
+
+ _loadLeftIntoAx(&lsb, left, result, offl, offr);
+
/* a:x >> shCount (x = lsb(result)) */
if (sign)
- AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount);
+ {
+ AccAXRshS(aopGet(AOP(result), offr, FALSE, FALSE, FALSE), shCount);
+ }
else
- AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount);
- if (getDataSize (result) > 1)
- aopPut (AOP (result), "a", offr + MSB16);
+ {
+ AccAXRsh(aopGet(AOP(result), offr, FALSE, FALSE, FALSE), shCount);
+ }
+
+ _storeAxResults(lsb, result, offr);
}
#endif
}
#endif
-#if 0
-//REMOVE ME!!!
+#ifdef BETTER_LITERAL_SHIFT
/*-----------------------------------------------------------------*/
/* genlshOne - left shift a one byte quantity by known count */
/*-----------------------------------------------------------------*/
static void
genlshOne (operand * result, operand * left, int shCount)
{
- D (emitcode (";", "genlshOne ");
- );
+ D (emitcode (";", "genlshOne "););
shiftL1Left2Result (left, LSB, result, LSB, shCount);
}
#endif
-#if 0
-//REMOVE ME!!!
+#ifdef BETTER_LITERAL_SHIFT
/*-----------------------------------------------------------------*/
/* genlshTwo - left shift two bytes by known amount != 0 */
/*-----------------------------------------------------------------*/
{
int size;
- D (emitcode (";", "genlshTwo ");
- );
+ D (emitcode (";", "genlshTwo "););
size = getDataSize (result);
/* if shCount >= 8 */
if (shCount >= 8)
- {
+ {
shCount -= 8;
+ _startLazyDPSEvaluation();
+
if (size > 1)
{
if (shCount)
+ {
+ _endLazyDPSEvaluation();
shiftL1Left2Result (left, LSB, result, MSB16, shCount);
+ aopPut (AOP (result), zero, LSB);
+ }
else
+ {
movLeft2Result (left, LSB, result, MSB16, 0);
+ aopPut (AOP (result), zero, LSB);
+ _endLazyDPSEvaluation();
+ }
}
- aopPut (AOP (result), zero, LSB);
- }
+ else
+ {
+ aopPut (AOP (result), zero, LSB);
+ _endLazyDPSEvaluation();
+ }
+ }
/* 1 <= shCount <= 7 */
else
{
if (size == 1)
+ {
shiftL1Left2Result (left, LSB, result, LSB, shCount);
+ }
else
+ {
shiftL2Left2Result (left, LSB, result, LSB, shCount);
+ }
}
}
#endif
}
#endif
-#if 0
-//REMOVE ME!!!
+#ifdef BETTER_LITERAL_SHIFT
/*-----------------------------------------------------------------*/
/* genLeftShiftLiteral - left shifting by known count */
/*-----------------------------------------------------------------*/
-static void
+static bool
genLeftShiftLiteral (operand * left,
operand * right,
operand * result,
int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
int size;
- D (emitcode (";", "genLeftShiftLiteral (%d)", shCount);
- );
+ size = getSize (operandType (result));
- freeAsmop (right, NULL, ic, TRUE);
+ D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
- aopOp (left, ic, FALSE, FALSE);
- aopOp (result, ic, FALSE, TRUE);
+ /* We only handle certain easy cases so far. */
+ if ((shCount != 0)
+ && (shCount < (size * 8))
+ && (size != 1)
+ && (size != 2))
+ {
+ D(emitcode (";", "genLeftShiftLiteral wimping out"););
+ return FALSE;
+ }
- size = getSize (operandType (result));
+ freeAsmop (right, NULL, ic, TRUE);
+
+ aopOp(left, ic, FALSE, FALSE);
+ aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
+#if 1 // debug spew
+ if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
+ {
+ emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
+ if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
+ {
+ emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
+ }
+ }
+ if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
+ {
+ emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
+ if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
+ {
+ emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
+ }
+ }
+#endif
+
#if VIEW_SIZE
emitcode ("; shift left ", "result %d, left %d", size,
AOP_SIZE (left));
/* I suppose that the left size >= result size */
if (shCount == 0)
- {
- while (size--)
+ {
+ _startLazyDPSEvaluation();
+ while (size--)
{
movLeft2Result (left, size, result, size, 0);
}
- }
-
+ _endLazyDPSEvaluation();
+ }
else if (shCount >= (size * 8))
+ {
+ _startLazyDPSEvaluation();
while (size--)
+ {
aopPut (AOP (result), zero, size);
+ }
+ _endLazyDPSEvaluation();
+ }
else
- {
+ {
switch (size)
{
case 1:
break;
case 2:
- case 3: /* bug: this is for generic pointers, I bet. */
genlshTwo (result, left, shCount);
break;
-
+#if 0
case 4:
genlshFour (result, left, shCount);
break;
+#endif
+ default:
+ fprintf(stderr, "*** ack! mystery literal shift!\n");
+ break;
}
}
freeAsmop (left, NULL, ic, TRUE);
freeAsmop (result, NULL, ic, TRUE);
+ return TRUE;
}
#endif
char *l;
symbol *tlbl, *tlbl1;
- D (emitcode (";", "genLeftShift ");
- );
+ D (emitcode (";", "genLeftShift "););
right = IC_RIGHT (ic);
left = IC_LEFT (ic);
aopOp (right, ic, FALSE, FALSE);
-#if 0
+
+#ifdef BETTER_LITERAL_SHIFT
/* if the shift count is known then do it
as efficiently as possible */
if (AOP_TYPE (right) == AOP_LIT)
{
- genLeftShiftLiteral (left, right, result, ic);
- return;
+ if (genLeftShiftLiteral (left, right, result, ic))
+ {
+ return;
+ }
}
#endif
more that 32 bits make no sense anyway, ( the
largest size of an object can be only 32 bits ) */
- emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
- emitcode ("inc", "b");
+ if (AOP_TYPE (right) == AOP_LIT)
+ {
+ /* Really should be handled by genLeftShiftLiteral,
+ * but since I'm too lazy to fix that today, at least we can make
+ * some small improvement.
+ */
+ emitcode("mov", "b,#0x%02x",
+ ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
+ }
+ else
+ {
+ emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
+ emitcode ("inc", "b");
+ }
freeAsmop (right, NULL, ic, TRUE);
aopOp (left, ic, FALSE, FALSE);
aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
freeAsmop (result, NULL, ic, TRUE);
}
-#if 0
-//REMOVE ME!!!
+#ifdef BETTER_LITERAL_SHIFT
/*-----------------------------------------------------------------*/
/* genrshOne - right shift a one byte quantity by known count */
/*-----------------------------------------------------------------*/
genrshOne (operand * result, operand * left,
int shCount, int sign)
{
- D (emitcode (";", "genrshOne");
- );
+ D (emitcode (";", "genrshOne"););
shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
}
#endif
-#if 0
-//REMOVE ME!!!
+#ifdef BETTER_LITERAL_SHIFT
/*-----------------------------------------------------------------*/
/* genrshTwo - right shift two bytes by known amount != 0 */
/*-----------------------------------------------------------------*/
genrshTwo (operand * result, operand * left,
int shCount, int sign)
{
- D (emitcode (";", "genrshTwo");
- );
+ D (emitcode (";", "genrshTwo"););
/* if shCount >= 8 */
if (shCount >= 8)
{
shCount -= 8;
+ _startLazyDPSEvaluation();
if (shCount)
+ {
shiftR1Left2Result (left, MSB16, result, LSB,
shCount, sign);
+ }
else
+ {
movLeft2Result (left, MSB16, result, LSB, sign);
+ }
addSign (result, MSB16, sign);
+ _endLazyDPSEvaluation();
}
/* 1 <= shCount <= 7 */
else
+ {
shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
+ }
}
#endif
}
#endif
-#if 0
-//REMOVE ME!!!
+#ifdef BETTER_LITERAL_SHIFT
/*-----------------------------------------------------------------*/
/* genRightShiftLiteral - right shifting by known count */
/*-----------------------------------------------------------------*/
-static void
+static bool
genRightShiftLiteral (operand * left,
operand * right,
operand * result,
int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
int size;
- D (emitcode (";", "genRightShiftLiteral");
- );
+ size = getSize (operandType (result));
+
+ D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
+
+ /* We only handle certain easy cases so far. */
+ if ((shCount != 0)
+ && (shCount < (size * 8))
+ && (size != 1)
+ && (size != 2))
+ {
+ D(emitcode (";", "genRightShiftLiteral wimping out"););
+ return FALSE;
+ }
freeAsmop (right, NULL, ic, TRUE);
AOP_SIZE (left));
#endif
- size = getDataSize (left);
/* test the LEFT size !!! */
/* I suppose that the left size >= result size */
if (shCount == 0)
- {
+ {
size = getDataSize (result);
+ _startLazyDPSEvaluation();
while (size--)
+ {
movLeft2Result (left, size, result, size, 0);
- }
-
+ }
+ _endLazyDPSEvaluation();
+ }
else if (shCount >= (size * 8))
{
if (sign)
+ {
/* get sign in acc.7 */
MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
+ }
addSign (result, LSB, sign);
}
else
case 2:
genrshTwo (result, left, shCount, sign);
break;
-
+#if 0
case 4:
genrshFour (result, left, shCount, sign);
break;
+#endif
default:
break;
}
freeAsmop (left, NULL, ic, TRUE);
freeAsmop (result, NULL, ic, TRUE);
}
+ return TRUE;
}
#endif
char *l;
symbol *tlbl, *tlbl1;
- D (emitcode (";", "genSignedRightShift ");
- );
+ D (emitcode (";", "genSignedRightShift "););
/* we do it the hard way put the shift count in b
and loop thru preserving the sign */
aopOp (right, ic, FALSE, FALSE);
-#if 0
+#ifdef BETTER_LITERAL_SHIFT
if (AOP_TYPE (right) == AOP_LIT)
{
- genRightShiftLiteral (left, right, result, ic, 1);
- return;
+ if (genRightShiftLiteral (left, right, result, ic, 1))
+ {
+ return;
+ }
}
#endif
/* shift count is unknown then we have to form
more that 32 bits make no sense anyway, ( the
largest size of an object can be only 32 bits ) */
- emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
- emitcode ("inc", "b");
+ if (AOP_TYPE (right) == AOP_LIT)
+ {
+ /* Really should be handled by genRightShiftLiteral,
+ * but since I'm too lazy to fix that today, at least we can make
+ * some small improvement.
+ */
+ emitcode("mov", "b,#0x%02x",
+ ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
+ }
+ else
+ {
+ emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
+ emitcode ("inc", "b");
+ }
freeAsmop (right, NULL, ic, TRUE);
aopOp (left, ic, FALSE, FALSE);
aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
char *l;
symbol *tlbl, *tlbl1;
- D (emitcode (";", "genRightShift ");
- );
+ D (emitcode (";", "genRightShift "););
/* if signed then we do it the hard way preserve the
sign bit moving it inwards */
aopOp (right, ic, FALSE, FALSE);
-#if 0
+#ifdef BETTER_LITERAL_SHIFT
/* if the shift count is known then do it
as efficiently as possible */
if (AOP_TYPE (right) == AOP_LIT)
{
- genRightShiftLiteral (left, right, result, ic, 0);
- return;
+ if (genRightShiftLiteral (left, right, result, ic, 0))
+ {
+ return;
+ }
}
#endif
only the lower order byte since shifting
more that 32 bits make no sense anyway, ( the
largest size of an object can be only 32 bits ) */
-
- emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
- emitcode ("inc", "b");
+
+ if (AOP_TYPE (right) == AOP_LIT)
+ {
+ /* Really should be handled by genRightShiftLiteral,
+ * but since I'm too lazy to fix that today, at least we can make
+ * some small improvement.
+ */
+ emitcode("mov", "b,#0x%02x",
+ ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
+ }
+ else
+ {
+ emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
+ emitcode ("inc", "b");
+ }
freeAsmop (right, NULL, ic, TRUE);
aopOp (left, ic, FALSE, FALSE);
aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
operand *cond = IC_COND (ic);
int isbit = 0;
- D (emitcode (";", "genIfx ");
- );
+ D (emitcode (";", "genIfx "););
aopOp (cond, ic, FALSE, FALSE);
{
int size = AOP_SIZE (right);
int offset = 0;
- char *l;
-
- if (size > 1)
- {
- /* This is a net loss for size == 1, but a big gain
- * otherwise.
- */
- D (emitcode (";", "genFarFarAssign (improved)");
- );
+ symbol *rSym = NULL;
+ if (size == 1)
+ {
+ /* quick & easy case. */
+ D(emitcode(";","genFarFarAssign (1 byte case)"););
+ MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
+ freeAsmop (right, NULL, ic, FALSE);
+ /* now assign DPTR to result */
+ _G.accInUse++;
+ aopOp(result, ic, FALSE, FALSE);
+ _G.accInUse--;
+ aopPut(AOP(result), "a", 0);
+ freeAsmop(result, NULL, ic, FALSE);
+ return;
+ }
+
+ /* See if we've got an underlying symbol to abuse. */
+ if (IS_SYMOP(result) && OP_SYMBOL(result))
+ {
+ if (IS_TRUE_SYMOP(result))
+ {
+ rSym = OP_SYMBOL(result);
+ }
+ else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
+ {
+ rSym = OP_SYMBOL(result)->usl.spillLoc;
+ }
+ }
+
+ if (size > 1 && rSym && rSym->rname && !rSym->onStack)
+ {
+ /* We can use the '390 auto-toggle feature to good effect here. */
+
+ D(emitcode(";","genFarFarAssign ('390 auto-toggle fun)"););
+ emitcode("mov", "dps, #0x21"); /* Select DPTR2 & auto-toggle. */
+ emitcode ("mov", "dptr,#%s", rSym->rname);
+ /* DP2 = result, DP1 = right, DP1 is current. */
+ while (size)
+ {
+ emitcode("movx", "a,@dptr");
+ emitcode("movx", "@dptr,a");
+ if (--size)
+ {
+ emitcode("inc", "dptr");
+ emitcode("inc", "dptr");
+ }
+ }
+ emitcode("mov", "dps, #0");
+ freeAsmop (right, NULL, ic, FALSE);
+ }
+ else
+ {
+ D (emitcode (";", "genFarFarAssign"););
aopOp (result, ic, TRUE, TRUE);
_startLazyDPSEvaluation ();
+
while (size--)
{
aopPut (AOP (result),
_endLazyDPSEvaluation ();
freeAsmop (result, NULL, ic, FALSE);
freeAsmop (right, NULL, ic, FALSE);
- }
- else
- {
- D (emitcode (";", "genFarFarAssign ");
- );
-
- /* first push the right side on to the stack */
- _startLazyDPSEvaluation ();
- while (size--)
- {
- l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
- MOVA (l);
- emitcode ("push", "acc");
- }
-
- freeAsmop (right, NULL, ic, FALSE);
- /* now assign DPTR to result */
- aopOp (result, ic, FALSE, FALSE);
- size = AOP_SIZE (result);
- while (size--)
- {
- emitcode ("pop", "acc");
- aopPut (AOP (result), "a", --offset);
- }
- freeAsmop (result, NULL, ic, FALSE);
- _endLazyDPSEvaluation ();
- }
+ }
}
/*-----------------------------------------------------------------*/
(AOP_TYPE (right) == AOP_LIT) &&
!IS_FLOAT (operandType (right)))
{
- D (emitcode (";", "Kevin's better literal load code");
- );
_startLazyDPSEvaluation ();
while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
{
return 0;
/* otherwise we can save BIG */
+ D(emitcode(";", "genDjnz"););
+
lbl = newiTempLabel (NULL);
lbl1 = newiTempLabel (NULL);
aopOp (IC_RESULT (ic), ic, FALSE, 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, TRUE);
+
+ if (strcmp(rByte, "a"))
+ {
+ /* Something is hopelessly wrong */
+ fprintf(stderr, "*** warning: internal error at %s:%d\n",
+ __FILE__, __LINE__);
+ /* We can just give up; the generated code will be inefficient,
+ * but what the hey.
+ */
+ freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
+ return 0;
+ }
+ emitcode ("dec", "%s", rByte);
+ aopPut(AOP(IC_RESULT(ic)), rByte, 0);
+ emitcode ("jnz", "%05d$", lbl->key + 100);
+ }
+ else if (IS_AOP_PREG (IC_RESULT (ic)))
{
emitcode ("dec", "%s",
aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
}
else
{
- emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE),
+ emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
lbl->key + 100);
}
emitcode ("sjmp", "%05d$", lbl1->key + 100);