/*-------------------------------------------------------------------------
- gen.c - source file for code generation for 8051
+ gen.c - source file for code generation for DS80C390
Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
and - Jean-Louis VERN.jlvern@writeme.com (1999)
In other words, you are welcome to use, share and improve this program.
You are forbidden to forbid anyone else to use, share and improve
what you give them. Help stamp out software-hoarding!
-
- Notes:
- 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
- Made everything static
-------------------------------------------------------------------------*/
#include <stdio.h>
#endif
char *aopLiteral (value * val, int offset);
-#if 0
-//REMOVE ME!!!
-extern int allocInfo;
-#endif
/* this is the down and dirty file with all kinds of
kludgy & hacky stuff. This is what it is all about
#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;
return NULL;
}
- piCode (ic, stdout);
/* other wise this is true end of the world */
werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
"getFreePtr should never reach here");
/*------------------------------------------------------------------*/
/* 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");
aopPut (asmop * aop, char *s, int offset)
{
char *d = buffer;
- symbol *lbl;
if (aop->size && offset > (aop->size - 1))
{
emitcode ("mov", "%s,c", aop->aopu.aop_dir);
else
{
- lbl = newiTempLabel (NULL);
-
if (strcmp (s, "a"))
{
MOVA (s);
}
- emitcode ("clr", "c");
- emitcode ("jz", "%05d$", lbl->key + 100);
- emitcode ("cpl", "c");
- emitcode ("", "%05d$:", lbl->key + 100);
- emitcode ("mov", "%s,c", aop->aopu.aop_dir);
+ {
+ symbol *lbl = newiTempLabel (NULL);
+ emitcode ("clr", "c");
+ emitcode ("jz", "%05d$", lbl->key + 100);
+ emitcode ("cpl", "c");
+ emitcode ("", "%05d$:", lbl->key + 100);
+ emitcode ("mov", "%s,c", aop->aopu.aop_dir);
+ }
}
}
break;
static void
reAdjustPreg (asmop * aop)
{
- emitcode (";jwk","reAdjustPreg: %d", aop->coff);
if ((aop->coff==0) || (aop->size <= 1)) {
return;
}
offset++, FALSE, FALSE, FALSE));
}
_endLazyDPSEvaluation ();
- tlbl = newiTempLabel (NULL);
tlbl = newiTempLabel (NULL);
aopPut (res->aop, one, 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 ();
}
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);
int size=AOP_SIZE(result);
emitcode (";",__FUNCTION__);
- if (size<1 || size>=2) {
+ if (size<1 || size>2) {
// this should never happen
fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
AOP_SIZE(result), __FUNCTION__, lineno);
emitcode ("jnb", "F0,%05d$", lbl->key+100);
// only ONE op was negative, we have to do a 8/16-bit two's complement
emitcode ("cpl", "a"); // lsb
- emitcode ("inc", "a");
- if (size==2) {
+ if (size==1) {
+ emitcode ("inc", "a");
+ } else {
+ emitcode ("add", "a,#1");
emitcode ("xch", "a,b");
emitcode ("cpl", "a"); // msb
emitcode ("addc", "a,#0");
operand *right = IC_RIGHT (ic);
operand *result = IC_RESULT (ic);
- D (emitcode (";", "genMult ");
- );
+ D (emitcode (";", "genMult "););
/* assign the amsops */
AOP_OP_3 (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),
movLeft2Result (left, LSB, result, MSB32, 0);
aopPut (AOP (result), zero, LSB);
aopPut (AOP (result), zero, MSB16);
- aopPut (AOP (result), zero, MSB32);
+ aopPut (AOP (result), zero, MSB24);
return;
}
}
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);
default:
ic = ic;
- /* piCode(ic,stdout); */
-
}
}