#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 */
/* 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);
}
/*-----------------------------------------------------------------*/
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)
+ {
+ 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))))
{
- aopPut (AOP (result), "b", 1);
+ operand *t = right;
+ right = left;
+ left = t;
+ }
+
+ lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
+ rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
+
+ 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;
}
- return;
- }
- // we have to do a signed multiply
+ /* we have to do a signed multiply */
+ /* emitcode (";", "signed"); */
+
+ /* now sign adjust for both left & right */
- emitcode (";", "signed");
- emitcode ("clr", "F0"); // reset sign flag
- 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);
- // 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");
+ 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;
+ }
- 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;
+ }
- /* 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);
+ /* initialize F0, which stores the runtime sign */
+ if (runtimeSign)
+ {
+ if (compiletimeSign)
+ emitcode ("setb", "F0"); /* set sign flag */
+ else
+ emitcode ("clr", "F0"); /* reset sign flag */
}
- } 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);
- }
+
+ /* 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--;
}
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);
for (ic = lic; ic; ic = ic->next)
{
+ _G.current_iCode = ic;
+
if (ic->lineno && cln != ic->lineno)
{
if (options.debug)