#include <ctype.h>
#include "common.h"
+#include "main.h"
#include "ralloc.h"
#include "gen.h"
#include "SDCCglobl.h"
short dptrInUse;
short dptr1InUse;
set *sendSet;
+ iCode *current_iCode;
}
_G;
emitcode ("","!tlabeldef",lbl->key+100); \
}}
+static int _currentDPS; /* Current processor DPS. */
+static int _desiredDPS; /* DPS value compiler thinks we should be using. */
+static int _lazyDPS = 0; /* if non-zero, we are doing lazy evaluation of DPS changes. */
/*-----------------------------------------------------------------*/
/* emitcode - writes the code into a file : for now it is simple */
lineCurr->isInline = _G.inLine;
lineCurr->isDebug = _G.debugLine;
+ lineCurr->ic = _G.current_iCode;
+ lineCurr->aln = ds390newAsmLineNode(_currentDPS);
va_end (ap);
}
return aop;
}
-static int _currentDPS; /* Current processor DPS. */
-static int _desiredDPS; /* DPS value compiler thinks we should be using. */
-static int _lazyDPS = 0; /* if non-zero, we are doing lazy evaluation of DPS changes. */
/*-----------------------------------------------------------------*/
/* genSetDPTR: generate code to select which DPTR is in use (zero */
/* if already has one */
if (sym->aop)
- return sym->aop;
+ {
+ if ((sym->aop->type == AOP_DPTR && useDP2)
+ || (sym->aop->type == AOP_DPTR2 && !useDP2))
+ sym->aop = NULL;
+ else
+ return sym->aop;
+ }
/* assign depending on the storage class */
/* if it is on the stack or indirectly addressable */
(sym2->usl.spillLoc == sym1))
return TRUE;
+ /* are they spilt to the same location */
+ if (IS_ITEMP (op2) &&
+ IS_ITEMP (op1) &&
+ sym2->isspilt &&
+ sym1->isspilt &&
+ (sym1->usl.spillLoc == sym2->usl.spillLoc))
+ return TRUE;
+
return FALSE;
}
/* if already has a asmop then continue */
if (op->aop)
- return;
+ {
+ if ((op->aop->type == AOP_DPTR && useDP2)
+ || (op->aop->type == AOP_DPTR2 && !useDP2))
+ op->aop = NULL;
+ else
+ return;
+ }
/* if the underlying symbol has a aop */
if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
{
op->aop = OP_SYMBOL (op)->aop;
- return;
+ if ((op->aop->type == AOP_DPTR && useDP2)
+ || (op->aop->type == AOP_DPTR2 && !useDP2))
+ op->aop = NULL;
+ else
+ return;
}
/* if this is a true symbol */
if (size > 1)
{
emitcode ("mov", "b,%s", fReturn[1]);
+ _G.bInUse++;
}
+ _G.accInUse++;
aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
+ _G.accInUse--;
+
+ if (size > 1)
+ _G.bInUse--;
+
aopPut (AOP (IC_RESULT (ic)), "a", 0);
if (size > 1)
/* save the registers used */
for (i = 0; i < sym->regsUsed->size; i++)
{
- if (bitVectBitValue (sym->regsUsed, i) ||
- (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
+ if (bitVectBitValue (sym->regsUsed, i))
emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
}
}
-
}
else
{
/* save the registers used */
for (i = 0; i < sym->regsUsed->size; i++)
{
- if (bitVectBitValue (sym->regsUsed, i) ||
- (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
+ if (bitVectBitValue (sym->regsUsed, i))
{
emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
_G.nRegsSaved++;
genEndFunction (iCode * ic)
{
symbol *sym = OP_SYMBOL (IC_LEFT (ic));
+ lineNode *lnp = lineCurr;
+ bitVect *regsUsed;
+ bitVect *regsUsedPrologue;
+ bitVect *regsUnneeded;
+ int idx;
D (emitcode (";", "genEndFunction "););
/* save the registers used */
for (i = sym->regsUsed->size; i >= 0; i--)
{
- if (bitVectBitValue (sym->regsUsed, i) ||
- (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
+ if (bitVectBitValue (sym->regsUsed, i))
emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
}
}
-
}
else
{
/* save the registers used */
for (i = sym->regsUsed->size; i >= 0; i--)
{
- if (bitVectBitValue (sym->regsUsed, i) ||
- (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
+ if (bitVectBitValue (sym->regsUsed, i))
emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
}
}
-
}
/* if debug then send end of function */
emitcode ("ret", "");
}
+ if (!port->peep.getRegsRead || !port->peep.getRegsWritten)
+ return;
+
+ /* If this was an interrupt handler using bank 0 that called another */
+ /* function, then all registers must be saved; nothing to optimized. */
+ if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
+ && !FUNC_REGBANK(sym->type))
+ return;
+
+ /* There are no push/pops to optimize if not callee-saves or ISR */
+ if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
+ return;
+
+ /* If there were stack parameters, we cannot optimize without also */
+ /* fixing all of the stack offsets; this is too dificult to consider. */
+ if (FUNC_HASSTACKPARM(sym->type))
+ return;
+
+ /* Compute the registers actually used */
+ regsUsed = newBitVect (ds390_nRegs);
+ regsUsedPrologue = newBitVect (ds390_nRegs);
+ while (lnp)
+ {
+ if (lnp->ic && lnp->ic->op == FUNCTION)
+ regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
+ else
+ regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
+
+ if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
+ && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
+ break;
+ if (!lnp->prev)
+ break;
+ lnp = lnp->prev;
+ }
+
+ if (bitVectBitValue (regsUsedPrologue, DPS_IDX)
+ && !bitVectBitValue (regsUsed, DPS_IDX))
+ {
+ bitVectUnSetBit (regsUsedPrologue, DPS_IDX);
+ }
+
+ if (bitVectBitValue (regsUsedPrologue, CND_IDX)
+ && !bitVectBitValue (regsUsed, CND_IDX))
+ {
+ regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
+ if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK(sym->type)
+ && !sym->stack)
+ bitVectUnSetBit (regsUsed, CND_IDX);
+ }
+ else
+ regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
+
+ /* If this was an interrupt handler that called another function */
+ /* function, then assume working registers may be modified by it. */
+ if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
+ {
+ regsUsed = bitVectSetBit (regsUsed, AP_IDX);
+ regsUsed = bitVectSetBit (regsUsed, DPX1_IDX);
+ regsUsed = bitVectSetBit (regsUsed, DPL1_IDX);
+ regsUsed = bitVectSetBit (regsUsed, DPH1_IDX);
+ regsUsed = bitVectSetBit (regsUsed, DPX_IDX);
+ regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
+ regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
+ regsUsed = bitVectSetBit (regsUsed, DPS_IDX);
+ regsUsed = bitVectSetBit (regsUsed, B_IDX);
+ regsUsed = bitVectSetBit (regsUsed, A_IDX);
+ regsUsed = bitVectSetBit (regsUsed, CND_IDX);
+ }
+
+ /* Remove the unneeded push/pops */
+ regsUnneeded = newBitVect (ds390_nRegs);
+ while (lnp)
+ {
+ if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
+ {
+ if (!strncmp(lnp->line, "push", 4))
+ {
+ idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
+ if (idx>=0 && !bitVectBitValue (regsUsed, idx))
+ {
+ connectLine (lnp->prev, lnp->next);
+ regsUnneeded = bitVectSetBit (regsUnneeded, idx);
+ }
+ }
+ if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
+ {
+ idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
+ if (idx>=0 && !bitVectBitValue (regsUsed, idx))
+ {
+ connectLine (lnp->prev, lnp->next);
+ regsUnneeded = bitVectSetBit (regsUnneeded, idx);
+ }
+ }
+ }
+ lnp = lnp->next;
+ }
+
+ for (idx = 0; idx < regsUnneeded->size; idx++)
+ if (bitVectBitValue (regsUnneeded, idx))
+ emitcode ("", ";\teliminated unneeded push/pop %s", ds390_regWithIdx (idx)->dname);
+
+ freeBitVect (regsUnneeded);
+ freeBitVect (regsUsed);
+ freeBitVect (regsUsedPrologue);
}
/*-----------------------------------------------------------------*/
{
bool dp1InUse, dp2InUse;
bool useDp2;
-
+
// First, generate the right opcode. DPTR may be used if neither left nor result are
// of type AOP_STR.
}
aopOp(IC_LEFT(ic), ic, FALSE, useDp2);
-
+
+
// We've op'd the left & right. So, if left or right are the same operand as result,
// we know aopOp will succeed, and we can just do it & bail.
- if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)) ||
- isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
- {
+ if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)))
+ {
+ aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
+ return TRUE;
+ }
+ if (isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
+ {
// D(emitcode(";", "aopOp3: (left | right) & result equal"););
- aopOp(IC_RESULT(ic),ic,TRUE, FALSE);
+ aopOp(IC_RESULT(ic),ic,TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
return TRUE;
- }
+ }
+
+ // Operands may be equivalent (but not equal) if they share a spill location. If
+ // so, use the same DPTR or DPTR2.
+ if (operandsEqu (IC_LEFT(ic), IC_RESULT(ic)))
+ {
+ aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
+ return TRUE;
+ }
+ if (operandsEqu (IC_RIGHT(ic), IC_RESULT(ic)))
+ {
+ aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
+ return TRUE;
+ }
// Note which dptrs are currently in use.
dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
operand * result,
iCode * ic)
{
- sym_link *opetype = operandType (result);
+ int size;
symbol *lbl;
-
+ bool runtimeSign, compiletimeSign;
+ bool lUnsigned, rUnsigned;
+
/* (if two literals: the value is computed before) */
/* if one literal, literal on the right */
emitcode (";", "swapped left and right");
}
- if (SPEC_USIGN(opetype)
- // ignore the sign of left and right, what else can we do?
- || (SPEC_USIGN(operandType(left)) &&
- SPEC_USIGN(operandType(right)))) {
- // just an unsigned 8*8=8/16 multiply
- //emitcode (";","unsigned");
- emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
- MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
- emitcode ("mul", "ab");
-
- _G.accInUse++; _G.bInUse++;
- aopOp(result, ic, TRUE, FALSE);
-
- if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
- {
- // this should never happen
- fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
- AOP_SIZE(result), __FILE__, lineno);
- exit (1);
- }
-
- aopPut (AOP (result), "a", 0);
- _G.accInUse--; _G.bInUse--;
- if (AOP_SIZE(result)==2)
+ /* (if two literals: the value is computed before) */
+ /* if one literal, literal on the right */
+ if (AOP_TYPE (left) == AOP_LIT)
{
- aopPut (AOP (result), "b", 1);
+ operand *t = right;
+ right = left;
+ left = t;
+ /* emitcode (";", "swapped left and right"); */
+ }
+ /* if no literal, unsigned on the right: shorter code */
+ if ( AOP_TYPE (right) != AOP_LIT
+ && SPEC_USIGN (getSpec (operandType (left))))
+ {
+ operand *t = right;
+ right = left;
+ left = t;
}
- return;
- }
- // we have to do a signed multiply
+ lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
+ rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
- emitcode (";", "signed");
- emitcode ("clr", "F0"); // reset sign flag
- MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
+ if ((lUnsigned && rUnsigned)
+/* sorry, I don't know how to get size
+ without calling aopOp (result,...);
+ see Feature Request */
+ /* || size == 1 */ ) /* no, this is not a bug; with a 1 byte result there's
+ no need to take care about the signedness! */
+ {
+ /* just an unsigned 8 * 8 = 8 multiply
+ or 8u * 8u = 16u */
+ /* emitcode (";","unsigned"); */
+ emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
+ MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
+ emitcode ("mul", "ab");
+
+ _G.accInUse++; _G.bInUse++;
+ aopOp (result, ic, TRUE, FALSE);
+ size = AOP_SIZE (result);
+
+ if (size < 1 || size > 2)
+ {
+ /* this should never happen */
+ fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
+ size, __FILE__, lineno);
+ exit (1);
+ }
+
+ aopPut (AOP (result), "a", 0);
+ _G.accInUse--; _G.bInUse--;
+ if (size == 2)
+ aopPut (AOP (result), "b", 1);
+ return;
+ }
- lbl=newiTempLabel(NULL);
- emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
- // left side is negative, 8-bit two's complement, this fails for -128
- emitcode ("setb", "F0"); // set sign flag
- emitcode ("cpl", "a");
- emitcode ("inc", "a");
+ /* we have to do a signed multiply */
+ /* emitcode (";", "signed"); */
+
+ /* now sign adjust for both left & right */
- emitcode ("", "!tlabeldef", lbl->key+100);
+ /* let's see what's needed: */
+ /* apply negative sign during runtime */
+ runtimeSign = FALSE;
+ /* negative sign from literals */
+ compiletimeSign = FALSE;
- /* if literal */
- if (AOP_TYPE(right)==AOP_LIT) {
- signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
- /* AND literal negative */
- if ((int) val < 0) {
- emitcode ("cpl", "F0"); // complement sign flag
- emitcode ("mov", "b,#!constbyte", -val);
- } else {
- emitcode ("mov", "b,#!constbyte", val);
+ if (!lUnsigned)
+ {
+ if (AOP_TYPE(left) == AOP_LIT)
+ {
+ /* signed literal */
+ signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
+ if (val < 0)
+ compiletimeSign = TRUE;
+ }
+ else
+ /* signed but not literal */
+ runtimeSign = TRUE;
}
- } else {
- lbl=newiTempLabel(NULL);
- emitcode ("mov", "b,a");
- emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
- emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
- // right side is negative, 8-bit two's complement
- emitcode ("cpl", "F0"); // complement sign flag
- emitcode ("cpl", "a");
- emitcode ("inc", "a");
- emitcode ("", "!tlabeldef", lbl->key+100);
- }
+
+ if (!rUnsigned)
+ {
+ if (AOP_TYPE(right) == AOP_LIT)
+ {
+ /* signed literal */
+ signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
+ if (val < 0)
+ compiletimeSign ^= TRUE;
+ }
+ else
+ /* signed but not literal */
+ runtimeSign = TRUE;
+ }
+
+ /* initialize F0, which stores the runtime sign */
+ if (runtimeSign)
+ {
+ if (compiletimeSign)
+ emitcode ("setb", "F0"); /* set sign flag */
+ else
+ emitcode ("clr", "F0"); /* reset sign flag */
+ }
+
+ /* save the signs of the operands */
+ if (AOP_TYPE(right) == AOP_LIT)
+ {
+ signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
+
+ if (!rUnsigned && val < 0)
+ emitcode ("mov", "b,#!constbyte", -val);
+ else
+ emitcode ("mov", "b,#!constbyte", (unsigned char) val);
+ }
+ else /* ! literal */
+ {
+ if (rUnsigned) /* emitcode (";", "signed"); */
+ emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
+ else
+ {
+ MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
+ lbl = newiTempLabel (NULL);
+ emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
+ emitcode ("cpl", "F0"); /* complement sign flag */
+ emitcode ("cpl", "a"); /* 2's complement */
+ emitcode ("inc", "a");
+ emitcode ("", "!tlabeldef", lbl->key + 100);
+ emitcode ("mov", "b,a");
+ }
+ }
+
+ if (AOP_TYPE(left) == AOP_LIT)
+ {
+ signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
+
+ if (!lUnsigned && val < 0)
+ emitcode ("mov", "a,#!constbyte", -val);
+ else
+ emitcode ("mov", "a,#!constbyte", (unsigned char) val);
+ }
+ else /* ! literal */
+ {
+ if (lUnsigned) /* emitcode (";", "signed"); */
+
+ emitcode ("mov", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
+ else
+ {
+ MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
+ lbl = newiTempLabel (NULL);
+ emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
+ emitcode ("cpl", "F0"); /* complement sign flag */
+ emitcode ("cpl", "a"); /* 2's complement */
+ emitcode ("inc", "a");
+ emitcode ("", "!tlabeldef", lbl->key + 100);
+ }
+ }
+
+ /* now the multiplication */
emitcode ("mul", "ab");
-
_G.accInUse++;_G.bInUse++;
aopOp(result, ic, TRUE, FALSE);
-
- if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
- {
- // this should never happen
+ size = AOP_SIZE (result);
+
+ if (size < 1 || size > 2)
+ {
+ /* this should never happen */
fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
- AOP_SIZE(result), __FILE__, lineno);
+ size, __FILE__, lineno);
exit (1);
- }
+ }
- lbl=newiTempLabel(NULL);
- emitcode ("jnb", "F0,!tlabel", lbl->key+100);
- // only ONE op was negative, we have to do a 8/16-bit two's complement
- emitcode ("cpl", "a"); // lsb
- if (AOP_SIZE(result)==1) {
- emitcode ("inc", "a");
- } else {
- emitcode ("add", "a,#1");
- emitcode ("xch", "a,b");
- emitcode ("cpl", "a"); // msb
- emitcode ("addc", "a,#0");
- emitcode ("xch", "a,b");
- }
-
- emitcode ("", "!tlabeldef", lbl->key+100);
+ if (runtimeSign || compiletimeSign)
+ {
+ lbl = newiTempLabel (NULL);
+ if (runtimeSign)
+ emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
+ emitcode ("cpl", "a"); /* lsb 2's complement */
+ if (size != 2)
+ emitcode ("inc", "a"); /* inc doesn't set carry flag */
+ else
+ {
+ emitcode ("add", "a,#1"); /* this sets carry flag */
+ emitcode ("xch", "a,b");
+ emitcode ("cpl", "a"); /* msb 2's complement */
+ emitcode ("addc", "a,#0");
+ emitcode ("xch", "a,b");
+ }
+ emitcode ("", "!tlabeldef", lbl->key + 100);
+ }
aopPut (AOP (result), "a", 0);
_G.accInUse--;_G.bInUse--;
- if (AOP_SIZE(result)==2) {
+ if (size == 2)
aopPut (AOP (result), "b", 1);
- }
}
/*-----------------------------------------------------------------*/
operand * result,
iCode * ic)
{
- sym_link *opetype = operandType (result);
+ bool lUnsigned, rUnsigned;
+ bool runtimeSign, compiletimeSign;
char *l;
symbol *lbl;
int size, offset;
offset = 1;
+ lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
+ rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
+
/* signed or unsigned */
- if (SPEC_USIGN (opetype))
+ if (lUnsigned && rUnsigned)
{
- /* unsigned is easy */
- LOAD_AB_FOR_DIV (left, right, l);
- emitcode ("div", "ab");
+ /* unsigned is easy */
+ LOAD_AB_FOR_DIV (left, right, l);
+ emitcode ("div", "ab");
- _G.accInUse++;
- aopOp(result, ic, TRUE, FALSE);
- aopPut (AOP (result), "a", 0);
- _G.accInUse--;
+ _G.accInUse++;
+ aopOp (result, ic, TRUE, FALSE);
+ aopPut (AOP (result), "a", 0);
+ _G.accInUse--;
- size = AOP_SIZE (result) - 1;
-
- while (size--)
- {
- aopPut (AOP (result), zero, offset++);
- }
+ size = AOP_SIZE (result) - 1;
+
+ while (size--)
+ aopPut (AOP (result), zero, offset++);
return;
}
/* signed is a little bit more difficult */
- /* save the signs of the operands */
- MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
- emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
- emitcode ("push", "acc"); /* save it on the stack */
-
/* now sign adjust for both left & right */
- MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
- lbl = newiTempLabel (NULL);
- emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
- emitcode ("cpl", "a");
- emitcode ("inc", "a");
- emitcode ("", "!tlabeldef", (lbl->key + 100));
- emitcode ("mov", "b,a");
- /* sign adjust left side */
- MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
+ /* let's see what's needed: */
+ /* apply negative sign during runtime */
+ runtimeSign = FALSE;
+ /* negative sign from literals */
+ compiletimeSign = FALSE;
- lbl = newiTempLabel (NULL);
- emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
- emitcode ("cpl", "a");
- emitcode ("inc", "a");
- emitcode ("", "!tlabeldef", (lbl->key + 100));
+ if (!lUnsigned)
+ {
+ if (AOP_TYPE(left) == AOP_LIT)
+ {
+ /* signed literal */
+ signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
+ if (val < 0)
+ compiletimeSign = TRUE;
+ }
+ else
+ /* signed but not literal */
+ runtimeSign = TRUE;
+ }
+
+ if (!rUnsigned)
+ {
+ if (AOP_TYPE(right) == AOP_LIT)
+ {
+ /* signed literal */
+ signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
+ if (val < 0)
+ compiletimeSign ^= TRUE;
+ }
+ else
+ /* signed but not literal */
+ runtimeSign = TRUE;
+ }
+
+ /* initialize F0, which stores the runtime sign */
+ if (runtimeSign)
+ {
+ if (compiletimeSign)
+ emitcode ("setb", "F0"); /* set sign flag */
+ else
+ emitcode ("clr", "F0"); /* reset sign flag */
+ }
+
+ /* save the signs of the operands */
+ if (AOP_TYPE(right) == AOP_LIT)
+ {
+ signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
+
+ if (!rUnsigned && val < 0)
+ emitcode ("mov", "b,#0x%02x", -val);
+ else
+ emitcode ("mov", "b,#0x%02x", (unsigned char) val);
+ }
+ else /* ! literal */
+ {
+ if (rUnsigned)
+ emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
+ else
+ {
+ MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
+ lbl = newiTempLabel (NULL);
+ emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
+ emitcode ("cpl", "F0"); /* complement sign flag */
+ emitcode ("cpl", "a"); /* 2's complement */
+ emitcode ("inc", "a");
+ emitcode ("", "!tlabeldef", lbl->key + 100);
+ emitcode ("mov", "b,a");
+ }
+ }
+
+ if (AOP_TYPE(left) == AOP_LIT)
+ {
+ signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
+ if (!lUnsigned && val < 0)
+ emitcode ("mov", "a,#0x%02x", -val);
+ else
+ emitcode ("mov", "a,#0x%02x", (unsigned char) val);
+ }
+ else /* ! literal */
+ {
+ if (lUnsigned)
+ emitcode ("mov", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
+ else
+ {
+ MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
+ lbl = newiTempLabel (NULL);
+ emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
+ emitcode ("cpl", "F0"); /* complement sign flag */
+ emitcode ("cpl", "a"); /* 2's complement */
+ emitcode ("inc", "a");
+ emitcode ("", "!tlabeldef", lbl->key + 100);
+ }
+ }
+
/* now the division */
emitcode ("nop", "; workaround for DS80C390 div bug.");
emitcode ("div", "ab");
- /* we are interested in the lower order
- only */
- emitcode ("mov", "b,a");
- lbl = newiTempLabel (NULL);
- emitcode ("pop", "acc");
- /* if there was an over flow we don't
- adjust the sign of the result */
- emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
- emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
- CLRC;
- emitcode ("clr", "a");
- emitcode ("subb", "a,b");
- emitcode ("mov", "b,a");
- emitcode ("", "!tlabeldef", (lbl->key + 100));
-
- /* now we are done */
- _G.accInUse++; _G.bInUse++;
- aopOp(result, ic, TRUE, FALSE);
-
- aopPut (AOP (result), "b", 0);
-
- size = AOP_SIZE (result) - 1;
-
- if (size > 0)
+
+ if (runtimeSign || compiletimeSign)
{
- emitcode ("mov", "c,b.7");
- emitcode ("subb", "a,acc");
+ lbl = newiTempLabel (NULL);
+ if (runtimeSign)
+ emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
+ emitcode ("cpl", "a"); /* lsb 2's complement */
+ emitcode ("inc", "a");
+ emitcode ("", "!tlabeldef", lbl->key + 100);
+
+ _G.accInUse++; _G.bInUse++;
+ aopOp (result, ic, TRUE, FALSE);
+ size = AOP_SIZE (result) - 1;
+
+ if (size > 0)
+ {
+ /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
+ then the result will be in b, a */
+ emitcode ("mov", "b,a"); /* 1 */
+ /* msb is 0x00 or 0xff depending on the sign */
+ if (runtimeSign)
+ {
+ emitcode ("mov", "c,F0");
+ emitcode ("subb", "a,acc");
+ emitcode ("xch", "a,b"); /* 2 */
+ while (size--)
+ aopPut (AOP (result), "b", offset++); /* write msb's */
+ }
+ else /* compiletimeSign */
+ while (size--)
+ aopPut (AOP (result), "#0xff", offset++); /* write msb's */
+ }
+ aopPut (AOP (result), "a", 0); /* 3: write lsb */
}
- while (size--)
+ else
{
- aopPut (AOP (result), "a", offset++);
+ _G.accInUse++; _G.bInUse++;
+ aopOp(result, ic, TRUE, FALSE);
+ size = AOP_SIZE (result) - 1;
+
+ aopPut (AOP (result), "a", 0);
+ while (size--)
+ aopPut (AOP (result), zero, offset++);
}
- _G.accInUse--; _G.bInUse--;
+ _G.accInUse--; _G.bInUse--;
}
operand * result,
iCode * ic)
{
- sym_link *opetype = operandType (result);
+ bool lUnsigned, rUnsigned;
+ bool runtimeSign, compiletimeSign;
char *l;
symbol *lbl;
+ int size, offset;
+ offset = 1;
+ lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
+ rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
+
/* signed or unsigned */
- if (SPEC_USIGN (opetype))
+ if (lUnsigned && rUnsigned)
{
/* unsigned is easy */
LOAD_AB_FOR_DIV (left, right, l);
emitcode ("div", "ab");
- aopOp(result, ic, TRUE, FALSE);
+ aopOp (result, ic, TRUE, FALSE);
aopPut (AOP (result), "b", 0);
+
+ for (size = AOP_SIZE (result) - 1; size--;)
+ aopPut (AOP (result), zero, offset++);
return;
}
/* signed is a little bit more difficult */
- /* save the signs of the operands */
- MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
-
- emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
- emitcode ("push", "acc"); /* save it on the stack */
-
/* now sign adjust for both left & right */
- MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
- lbl = newiTempLabel (NULL);
- emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
- emitcode ("cpl", "a");
- emitcode ("inc", "a");
- emitcode ("", "!tlabeldef", (lbl->key + 100));
- emitcode ("mov", "b,a");
+ /* modulus: sign of the right operand has no influence on the result! */
+ if (AOP_TYPE(right) == AOP_LIT)
+ {
+ signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
- /* sign adjust left side */
- MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
+ if (!rUnsigned && val < 0)
+ emitcode ("mov", "b,#0x%02x", -val);
+ else
+ emitcode ("mov", "b,#0x%02x", (unsigned char) val);
+ }
+ else /* ! literal */
+ {
+ if (rUnsigned)
+ emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
+ else
+ {
+ MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
+ lbl = newiTempLabel (NULL);
+ emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
+ emitcode ("cpl", "a"); /* 2's complement */
+ emitcode ("inc", "a");
+ emitcode ("", "!tlabeldef", lbl->key + 100);
+ emitcode ("mov", "b,a");
+ }
+ }
+
+ /* let's see what's needed: */
+ /* apply negative sign during runtime */
+ runtimeSign = FALSE;
+ /* negative sign from literals */
+ compiletimeSign = FALSE;
- lbl = newiTempLabel (NULL);
- emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
- emitcode ("cpl", "a");
- emitcode ("inc", "a");
- emitcode ("", "!tlabeldef", (lbl->key + 100));
+ /* sign adjust left side */
+ if (AOP_TYPE(left) == AOP_LIT)
+ {
+ signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
- /* now the multiplication */
+ if (!lUnsigned && val < 0)
+ {
+ compiletimeSign = TRUE; /* set sign flag */
+ emitcode ("mov", "a,#0x%02x", -val);
+ }
+ else
+ emitcode ("mov", "a,#0x%02x", (unsigned char) val);
+ }
+ else /* ! literal */
+ {
+ MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
+
+ if (!lUnsigned)
+ {
+ runtimeSign = TRUE;
+ emitcode ("clr", "F0"); /* clear sign flag */
+
+ lbl = newiTempLabel (NULL);
+ emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
+ emitcode ("setb", "F0"); /* set sign flag */
+ emitcode ("cpl", "a"); /* 2's complement */
+ emitcode ("inc", "a");
+ emitcode ("", "!tlabeldef", lbl->key + 100);
+ }
+ }
+
+ /* now the modulus */
emitcode ("nop", "; workaround for DS80C390 div bug.");
emitcode ("div", "ab");
- /* we are interested in the lower order
- only */
- lbl = newiTempLabel (NULL);
- emitcode ("pop", "acc");
- /* if there was an over flow we don't
- adjust the sign of the result */
- emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
- emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
- CLRC;
- emitcode ("clr", "a");
- emitcode ("subb", "a,b");
- emitcode ("mov", "b,a");
- emitcode ("", "!tlabeldef", (lbl->key + 100));
- _G.bInUse++;
- /* now we are done */
- aopOp(result, ic, TRUE, FALSE);
- aopPut (AOP (result), "b", 0);
- _G.bInUse--;
+ if (runtimeSign || compiletimeSign)
+ {
+ emitcode ("mov", "a,b");
+ lbl = newiTempLabel (NULL);
+ if (runtimeSign)
+ emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
+ emitcode ("cpl", "a"); /* lsb 2's complement */
+ emitcode ("inc", "a");
+ emitcode ("", "!tlabeldef", lbl->key + 100);
+
+ _G.accInUse++; _G.bInUse++;
+ aopOp (result, ic, TRUE, FALSE);
+ size = AOP_SIZE (result) - 1;
+
+ if (size > 0)
+ {
+ /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
+ then the result will be in b, a */
+ emitcode ("mov", "b,a"); /* 1 */
+ /* msb is 0x00 or 0xff depending on the sign */
+ if (runtimeSign)
+ {
+ emitcode ("mov", "c,F0");
+ emitcode ("subb", "a,acc");
+ emitcode ("xch", "a,b"); /* 2 */
+ while (size--)
+ aopPut (AOP (result), "b", offset++); /* write msb's */
+ }
+ else /* compiletimeSign */
+ while (size--)
+ aopPut (AOP (result), "#0xff", offset++); /* write msb's */
+ }
+ aopPut (AOP (result), "a", 0); /* 3: write lsb */
+ }
+ else
+ {
+ _G.accInUse++; _G.bInUse++;
+ aopOp(result, ic, TRUE, FALSE);
+ size = AOP_SIZE (result) - 1;
+
+ aopPut (AOP (result), "b", 0);
+ while (size--)
+ aopPut (AOP (result), zero, offset++);
+ }
+ _G.accInUse--; _G.bInUse--;
}
&& (size != 2)
&& (size != 4))
{
- D(emitcode (";", "genRightShiftLiteral wimping out"););
+ D(emitcode (";", "genRightShiftLiteral wimping out"););
return FALSE;
}
genRightShift (iCode * ic)
{
operand *right, *left, *result;
- sym_link *retype;
+ sym_link *letype;
int size, offset;
char *l;
symbol *tlbl, *tlbl1;
/* if signed then we do it the hard way preserve the
sign bit moving it inwards */
- retype = getSpec (operandType (IC_RESULT (ic)));
+ letype = getSpec (operandType (IC_LEFT (ic)));
- if (!SPEC_USIGN (retype))
+ if (!SPEC_USIGN (letype))
{
genSignedRightShift (ic);
return;
aopOp (left, ic, FALSE, FALSE);
/* if left is rematerialisable and
- result is not bit variable type and
+ result is not bitfield variable type and
the left is pointer to data space i.e
lower 128 bytes of space */
if (AOP_TYPE (left) == AOP_IMMD &&
- !IS_BITVAR (retype) &&
- !IS_BITVAR (letype) &&
+ !IS_BITFIELD (retype) &&
+ !IS_BITFIELD (letype) &&
DCL_TYPE (ltype) == POINTER)
{
genDataPointerGet (left, result, ic);
aopOp (result, ic, FALSE, FALSE);
/* if bitfield then unpack the bits */
- if (IS_BITVAR (retype) || IS_BITVAR (letype))
+ if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
genUnpackBits (result, rname, POINTER);
else
{
aopOp (result, ic, FALSE, FALSE);
/* if bitfield then unpack the bits */
- if (IS_BITVAR (retype) || IS_BITVAR (letype))
+ if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
genUnpackBits (result, rname, PPOINTER);
else
{
aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
/* if bit then unpack */
- if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
+ if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
if (AOP_INDPTRn(left)) {
genSetDPTR(AOP(left)->aopu.dptr);
}
aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
/* if bit then unpack */
- if (IS_BITVAR (retype)) {
+ if (IS_BITFIELD (retype)) {
if (AOP_INDPTRn(left)) {
genSetDPTR(AOP(left)->aopu.dptr);
}
_G.bInUse--;
/* if bit then unpack */
- if (IS_BITVAR (retype) || IS_BITVAR (letype))
+ if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
{
genUnpackBits (result, "dptr", GPOINTER);
}
aopOp (right, ic, FALSE, FALSE);
/* if bitfield then unpack the bits */
- if (IS_BITVAR (retype) || IS_BITVAR (letype))
- genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
+ if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
+ genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
else
{
/* we have can just get the values */
aopOp (right, ic, FALSE, FALSE);
/* if bitfield then unpack the bits */
- if (IS_BITVAR (retype) || IS_BITVAR (letype))
- genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
+ if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
+ genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
else
{
/* we have can just get the values */
aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
/* if bit then unpack */
- if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
+ if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
if (AOP_INDPTRn(result)) {
genSetDPTR(AOP(result)->aopu.dptr);
}
- genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
+ genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
if (AOP_INDPTRn(result)) {
genSetDPTR(0);
}
/* if bit then unpack */
- if (IS_BITVAR (retype) || IS_BITVAR (letype))
+ if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
{
- genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
+ genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
}
else
{
if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
return;
- aopOp (right, ic, FALSE, FALSE);
+ aopOp (right, ic, FALSE, AOP_IS_STR (result));
aopOp (result, ic, FALSE, (AOP_TYPE(right) == AOP_DPTR));
/* if the result is a bit */
for (ic = lic; ic; ic = ic->next)
{
+ _G.current_iCode = ic;
+
if (ic->lineno && cln != ic->lineno)
{
if (options.debug)