#ifdef HAVE_ENDIAN_H
#include <endian.h>
#else
-#if !defined(__BORLANDC__) && !defined(_MSC_VER)
+#if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__)
#warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
#warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
#endif
#endif
#endif
+#define BETTER_LITERAL_SHIFT
+
char *aopLiteral (value * val, int offset);
/* this is the down and dirty file with all kinds of
#define D(x) x
unsigned fReturnSizeDS390 = 5; /* shared with ralloc.c */
-static char *fReturn[] =
+static char *fReturn24[] =
{"dpl", "dph", "dpx", "b", "a"};
+static char *fReturn16[] =
+{"dpl", "dph", "b", "a"};
+static char **fReturn = fReturn24;
static char *accUse[] =
{"a", "b"};
}
_G;
-static void saverbank (int, iCode *, bool);
+static void saveRBank (int, iCode *, bool);
#define RESULTONSTACK(x) \
(IC_RESULT(x) && IC_RESULT(x)->aop && \
emitcode (char *inst, char *fmt,...)
{
va_list ap;
- char lb[MAX_INLINEASM];
+ char lb[INITIAL_INLINEASM];
char *lbp = lb;
va_start (ap, fmt);
/* first check if r0 & r1 are used by this
instruction, in which case we are in trouble */
- if ((r0iu = bitVectBitValue (ic->rUsed, R0_IDX)) &&
- (r1iu = bitVectBitValue (ic->rUsed, R1_IDX)))
- {
+ r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
+ r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
+ if (r0iu && r1iu) {
goto endOfWorld;
}
{
_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");
+ if (options.model == MODEL_FLAT24)
+ emitcode ("mov", "dpx1,#0x40");
emitcode ("mov", "dph1,#0x00");
emitcode ("mov", "dpl1, a");
- /* genSetDPTR(0); */
}
else
{
- emitcode ("mov", "dpx,#0x40");
+ if (options.model == MODEL_FLAT24)
+ emitcode ("mov", "dpx,#0x40");
emitcode ("mov", "dph,#0x00");
emitcode ("mov", "dpl, a");
}
/* if the registers have been saved already then
do nothing */
- if (ic->regsSaved || (OP_SYMBOL (IC_LEFT (ic))->calleeSave))
+ if (ic->regsSaved || (OP_SYMBOL (IC_LEFT (ic))->calleeSave) ||
+ SPEC_NAKED(OP_SYM_ETYPE(IC_LEFT(ic))))
return;
/* find the registers in use at this time
for (i = 0; i < ds390_nRegs; i++)
{
if (bitVectBitValue (rsave, i))
- emitcode ("push", "%s ;jwk saveRegisters", ds390_regWithIdx (i)->dname);
+ emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
}
detype = getSpec (operandType (IC_LEFT (ic)));
- if (detype &&
- (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
- IS_ISR (currFunc->etype) &&
- !ic->bankSaved)
-
- saverbank (SPEC_BANK (detype), ic, TRUE);
-
}
+
/*-----------------------------------------------------------------*/
/* unsaveRegisters - pop the pushed registers */
/*-----------------------------------------------------------------*/
for (i = ds390_nRegs; i >= 0; i--)
{
if (bitVectBitValue (rsave, i))
- emitcode ("pop", "%s ;jwk unsaveRegisters", ds390_regWithIdx (i)->dname);
+ emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
}
}
MOVA (l);
l = "acc";
}
- emitcode ("push", "%s ;jwk genIpush: !parm", l);
+ emitcode ("push", "%s", l);
}
_endLazyDPSEvaluation ();
return;
emitcode ("push", "acc");
}
else
- emitcode ("push", "%s ;jwk genIpush", l);
+ emitcode ("push", "%s", l);
}
_endLazyDPSEvaluation ();
_startLazyDPSEvaluation ();
while (size--)
{
- emitcode ("pop", "%s ;jwk genIpop", aopGet (AOP (IC_LEFT (ic)), offset--,
+ emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
FALSE, TRUE, TRUE));
}
_endLazyDPSEvaluation ();
}
/*-----------------------------------------------------------------*/
-/* unsaverbank - restores the resgister bank from stack */
+/* unsaveRBank - restores the resgister bank from stack */
/*-----------------------------------------------------------------*/
static void
-unsaverbank (int bank, iCode * ic, bool popPsw)
+unsaveRBank (int bank, iCode * ic, bool popPsw)
{
int i;
- asmop *aop;
+ asmop *aop = NULL;
regs *r = NULL;
+ if (options.useXstack)
+ {
+ if (!ic)
+ {
+ /* Assume r0 is available for use. */
+ r = ds390_regWithIdx (R0_IDX);;
+ }
+ else
+ {
+ aop = newAsmop (0);
+ r = getFreePtr (ic, &aop, FALSE);
+ }
+ emitcode ("mov", "%s,_spx", r->name);
+ }
+
if (popPsw)
{
if (options.useXstack)
- {
- aop = newAsmop (0);
- r = getFreePtr (ic, &aop, FALSE);
-
-
- emitcode ("mov", "%s,_spx", r->name);
+ {
emitcode ("movx", "a,@%s", r->name);
emitcode ("mov", "psw,a");
emitcode ("dec", "%s", r->name);
-
}
else
+ {
emitcode ("pop", "psw");
+ }
}
for (i = (ds390_nRegs - 1); i >= 0; i--)
if (options.useXstack)
{
-
emitcode ("mov", "_spx,%s", r->name);
- freeAsmop (NULL, aop, ic, TRUE);
-
}
+
+ if (aop)
+ {
+ freeAsmop (NULL, aop, ic, TRUE);
+ }
}
/*-----------------------------------------------------------------*/
-/* saverbank - saves an entire register bank on the stack */
+/* saveRBank - saves an entire register bank on the stack */
/*-----------------------------------------------------------------*/
static void
-saverbank (int bank, iCode * ic, bool pushPsw)
+saveRBank (int bank, iCode * ic, bool pushPsw)
{
int i;
- asmop *aop;
+ asmop *aop = NULL;
regs *r = NULL;
if (options.useXstack)
{
-
- aop = newAsmop (0);
- r = getFreePtr (ic, &aop, FALSE);
- emitcode ("mov", "%s,_spx", r->name);
-
+ if (!ic)
+ {
+ /* Assume r0 is available for use. */
+ r = ds390_regWithIdx (R0_IDX);;
+ }
+ else
+ {
+ aop = newAsmop (0);
+ r = getFreePtr (ic, &aop, FALSE);
+ }
+ emitcode ("mov", "%s,_spx", r->name);
}
for (i = 0; i < ds390_nRegs; i++)
emitcode ("movx", "@%s,a", r->name);
emitcode ("inc", "%s", r->name);
emitcode ("mov", "_spx,%s", r->name);
- freeAsmop (NULL, aop, ic, TRUE);
-
}
else
+ {
emitcode ("push", "psw");
+ }
emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
}
- ic->bankSaved = 1;
-
+
+ if (aop)
+ {
+ freeAsmop (NULL, aop, ic, TRUE);
+ }
+
+ if (ic)
+ {
+ ic->bankSaved = 1;
+ }
}
/*-----------------------------------------------------------------*/
genCall (iCode * ic)
{
sym_link *detype;
+ bool restoreBank = FALSE;
+ bool swapBanks = FALSE;
- D (emitcode (";", "genCall ");
- );
-
- /* if caller saves & we have not saved then */
- if (!ic->regsSaved)
- saveRegisters (ic);
+ D (emitcode (";", "genCall "););
- /* if we are calling a function that is not using
+ /* if we are calling a not _naked function that is not using
the same register bank then we need to save the
destination registers on the stack */
detype = getSpec (operandType (IC_LEFT (ic)));
- if (detype &&
+ if (detype && !SPEC_NAKED(detype) &&
(SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
- IS_ISR (currFunc->etype) &&
- !ic->bankSaved)
-
- saverbank (SPEC_BANK (detype), ic, TRUE);
-
+ IS_ISR (currFunc->etype))
+ {
+ if (!ic->bankSaved)
+ {
+ /* This is unexpected; the bank should have been saved in
+ * genFunction.
+ */
+ saveRBank (SPEC_BANK (detype), ic, FALSE);
+ restoreBank = TRUE;
+ }
+ swapBanks = TRUE;
+ }
+
+ /* if caller saves & we have not saved then */
+ if (!ic->regsSaved)
+ saveRegisters (ic);
+
/* if send set is not empty the assign */
+ /* We've saved all the registers we care about;
+ * therefore, we may clobber any register not used
+ * in the calling convention (i.e. anything not in
+ * fReturn.
+ */
if (_G.sendSet)
{
iCode *sic;
{
int size, offset = 0;
- aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
+ aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
size = AOP_SIZE (IC_LEFT (sic));
_startLazyDPSEvaluation ();
while (size--)
{
- char *l = aopGet (AOP (IC_LEFT (sic)), offset,
+ char *l = aopGet (AOP(IC_LEFT(sic)), offset,
FALSE, FALSE, TRUE);
- if (strcmp (l, fReturn[offset])) {
- genSetDPTR(0);
- _flushLazyDPS();
- emitcode ("mov", "%s,%s ;jwk lazy genCall",
- fReturn[offset],
- l);
- }
+ if ((AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR) && size)
+ {
+ emitcode("mov", "%s,%s", regs390[offset].name, l);
+ }
+ else if (strcmp (l, fReturn[offset]))
+ {
+ emitcode ("mov", "%s,%s",
+ fReturn[offset],
+ l);
+ }
offset++;
}
_endLazyDPSEvaluation ();
+ if (AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR)
+ {
+ size = AOP_SIZE (IC_LEFT (sic));
+ if (size)
+ {
+ size--;
+ }
+ while (size)
+ {
+ size--;
+ emitcode("mov", "%s,%s",
+ fReturn[size], regs390[size].name);
+ }
+ }
freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
}
_G.sendSet = NULL;
- }
+ }
+
+ if (swapBanks)
+ {
+ emitcode ("mov", "psw,#0x%02x",
+ ((SPEC_BANK(detype)) << 3) & 0xff);
+ }
+
/* make the call */
emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
OP_SYMBOL (IC_LEFT (ic))->rname :
OP_SYMBOL (IC_LEFT (ic))->name));
+ if (swapBanks)
+ {
+ emitcode ("mov", "psw,#0x%02x",
+ ((SPEC_BANK(currFunc->etype)) << 3) & 0xff);
+ }
+
/* if we need assign a result value */
if ((IS_ITEMP (IC_RESULT (ic)) &&
(OP_SYMBOL (IC_RESULT (ic))->nRegs ||
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)
{
else
for (i = 0; i < ic->parmBytes; i++)
emitcode ("dec", "%s", spname);
-
}
- /* if register bank was saved then pop them */
- if (ic->bankSaved)
- unsaverbank (SPEC_BANK (detype), ic, TRUE);
-
/* if we hade saved some registers then unsave them */
if (ic->regsSaved && !(OP_SYMBOL (IC_LEFT (ic))->calleeSave))
unsaveRegisters (ic);
-
+ /* if register bank was saved then pop them */
+ if (restoreBank)
+ unsaveRBank (SPEC_BANK (detype), ic, FALSE);
}
/*-----------------------------------------------------------------*/
if (detype &&
IS_ISR (currFunc->etype) &&
(SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)))
- saverbank (SPEC_BANK (detype), ic, TRUE);
+ saveRBank (SPEC_BANK (detype), ic, TRUE);
/* push the return address on to the stack */
if (detype &&
(SPEC_BANK (currFunc->etype) !=
SPEC_BANK (detype)))
- unsaverbank (SPEC_BANK (detype), ic, TRUE);
+ unsaveRBank (SPEC_BANK (detype), ic, TRUE);
/* if we hade saved some registers then
unsave them */
{
symbol *sym;
sym_link *fetype;
+ bool switchedPSW = FALSE;
- D (emitcode (";", "genFunction ");
- );
+ D (emitcode (";", "genFunction "););
_G.nRegsSaved = 0;
/* create the function header */
emitcode ("", "%s:", sym->rname);
fetype = getSpec (operandType (IC_LEFT (ic)));
+ if (SPEC_NAKED(fetype))
+ {
+ emitcode(";", "naked function: no prologue.");
+ return;
+ }
+
/* if critical function then turn interrupts off */
if (SPEC_CRTCL (fetype))
emitcode ("clr", "ea");
else
{
/* this function has a function call cannot
- determines register usage so we will have the
+ determines register usage so we will have to push the
entire bank */
- saverbank (0, ic, FALSE);
+ saveRBank (0, ic, FALSE);
+ }
+ }
+ else
+ {
+ /* This ISR uses a non-zero bank.
+ *
+ * We assume that the bank is available for our
+ * exclusive use.
+ *
+ * However, if this ISR calls a function which uses some
+ * other bank, we must save that bank entirely.
+ */
+ unsigned long banksToSave = 0;
+
+ if (sym->hasFcall)
+ {
+
+#define MAX_REGISTER_BANKS 4
+
+ iCode *i;
+ int ix;
+
+ for (i = ic; i; i = i->next)
+ {
+ if (i->op == ENDFUNCTION)
+ {
+ /* we got to the end OK. */
+ break;
+ }
+
+ if (i->op == CALL)
+ {
+ sym_link *detype;
+
+ detype = getSpec(operandType (IC_LEFT(i)));
+ if (detype
+ && SPEC_BANK(detype) != SPEC_BANK(sym->etype))
+ {
+ /* Mark this bank for saving. */
+ if (SPEC_BANK(detype) >= MAX_REGISTER_BANKS)
+ {
+ werror(E_NO_SUCH_BANK, SPEC_BANK(detype));
+ }
+ else
+ {
+ banksToSave |= (1 << SPEC_BANK(detype));
+ }
+
+ /* And note that we don't need to do it in
+ * genCall.
+ */
+ i->bankSaved = 1;
+ }
+ }
+ if (i->op == PCALL)
+ {
+ /* This is a mess; we have no idea what
+ * register bank the called function might
+ * use.
+ *
+ * The only thing I can think of to do is
+ * throw a warning and hope.
+ */
+ werror(W_FUNCPTR_IN_USING_ISR);
+ }
+ }
+
+ if (banksToSave && options.useXstack)
+ {
+ /* Since we aren't passing it an ic,
+ * saveRBank will assume r0 is available to abuse.
+ *
+ * So switch to our (trashable) bank now, so
+ * the caller's R0 isn't trashed.
+ */
+ emitcode ("push", "psw");
+ emitcode ("mov", "psw,#0x%02x",
+ (SPEC_BANK (sym->etype) << 3) & 0x00ff);
+ switchedPSW = TRUE;
+ }
+
+ for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
+ {
+ if (banksToSave & (1 << ix))
+ {
+ saveRBank(ix, NULL, FALSE);
+ }
+ }
}
+ SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
}
}
else
}
/* set the register bank to the desired value */
- if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
+ if ((SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
+ && !switchedPSW)
{
emitcode ("push", "psw");
emitcode ("mov", "psw,#0x%02x", (SPEC_BANK (sym->etype) << 3) & 0x00ff);
{
symbol *sym = OP_SYMBOL (IC_LEFT (ic));
- D (emitcode (";", "genEndFunction ");
- );
+ D (emitcode (";", "genEndFunction "););
+
+ if (SPEC_NAKED(sym->etype))
+ {
+ emitcode(";", "naked function: no epilogue.");
+ return;
+ }
if (IS_RENT (sym->etype) || options.stackAuto)
{
/* restore the register bank */
if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
- emitcode ("pop", "psw");
+ {
+ if (!SPEC_BANK (sym->etype) || !IS_ISR (sym->etype)
+ || !options.useXstack)
+ {
+ /* Special case of ISR using non-zero bank with useXstack
+ * is handled below.
+ */
+ emitcode ("pop", "psw");
+ }
+ }
if (IS_ISR (sym->etype))
{
registers :-) */
if (!SPEC_BANK (sym->etype))
{
-
/* if this function does not call any other
function then we can be economical and
save only those registers that are used */
else
{
/* this function has a function call cannot
- determines register usage so we will have the
+ determines register usage so we will have to pop the
entire bank */
- unsaverbank (0, ic, FALSE);
+ unsaveRBank (0, ic, FALSE);
+ }
+ }
+ else
+ {
+ /* This ISR uses a non-zero bank.
+ *
+ * Restore any register banks saved by genFunction
+ * in reverse order.
+ */
+ unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
+ int ix;
+
+ for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
+ {
+ if (savedBanks & (1 << ix))
+ {
+ unsaveRBank(ix, NULL, FALSE);
+ }
+ }
+
+ if (options.useXstack)
+ {
+ /* Restore bank AFTER calling unsaveRBank,
+ * since it can trash r0.
+ */
+ emitcode ("pop", "psw");
}
}
emitcode ("setb", "ea");
/* if debug then send end of function */
-/* if (options.debug && currFunc) { */
- if (currFunc)
- {
+ if (options.debug && currFunc) {
_G.debugLine = 1;
emitcode ("", "C$%s$%d$%d$%d ==.",
FileBaseName (ic->filename), currFunc->lastLine,
}
/* if debug then send end of function */
- if (currFunc)
+ if (options.debug && currFunc)
{
_G.debugLine = 1;
emitcode ("", "C$%s$%d$%d$%d ==.",
}
else
{
+ /* Since A is the last element of fReturn,
+ * is is OK to clobber it in the aopGet.
+ */
l = aopGet (AOP (IC_LEFT (ic)), offset,
- FALSE, FALSE, FALSE);
+ FALSE, FALSE, TRUE);
if (strcmp (fReturn[offset], l))
emitcode ("mov", "%s,%s", fReturn[offset++], l);
}
_startLazyDPSEvaluation ();
while (size--)
{
- if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
+ if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
{
MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
if (offset == 0)
}
else
{
+ if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
+ {
+ /* right is going to use ACC or we would have taken the
+ * above branch.
+ */
+ assert(AOP_NEEDSACC(IC_RIGHT(ic)));
+ D(emitcode(";", "+ AOP_ACC special case."););
+ emitcode("xch", "a, %s", DP2_RESULT_REG);
+ }
MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
if (offset == 0)
- emitcode ("add", "a,%s",
- aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
+ {
+ if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
+ {
+ emitcode("add", "a, %s", DP2_RESULT_REG);
+ }
+ else
+ {
+ emitcode ("add", "a,%s",
+ aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE));
+ }
+ }
else
+ {
emitcode ("addc", "a,%s",
aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
+ }
}
if (!pushResult)
{
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)
{
else
{
/* first add without previous c */
- if (!offset)
- emitcode ("add", "a,#0x%02x",
- (unsigned int) (lit & 0x0FFL));
- else
+ if (!offset) {
+ if (!size && lit==-1) {
+ emitcode ("dec", "a");
+ } else {
+ emitcode ("add", "a,#0x%02x",
+ (unsigned int) (lit & 0x0FFL));
+ }
+ } else {
emitcode ("addc", "a,#0x%02x",
(unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
+ }
}
if (pushResult)
symbol *lbl;
int size=AOP_SIZE(result);
- emitcode (";",__FUNCTION__);
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);
+ AOP_SIZE(result), __FILE__, lineno);
exit (1);
}
emitcode (";", "signed");
emitcode ("clr", "F0"); // reset sign flag
- emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
lbl=newiTempLabel(NULL);
emitcode ("inc", "a");
emitcode ("", "%05d$:", lbl->key+100);
- emitcode ("xch", "a,b");
/* if literal */
if (AOP_TYPE(right)==AOP_LIT) {
+ signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
/* AND literal negative */
- if ((int) floatFromVal (AOP (right)->aopu.aop_lit) < 0) {
- // two's complement for literal<0
- emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
- emitcode ("cpl", "a");
- emitcode ("inc", "a");
+ if ((int) val < 0) {
+ emitcode ("cpl", "F0"); // complement sign flag
+ emitcode ("mov", "b,#0x%02x", -val);
+ } else {
+ emitcode ("mov", "b,#0x%02x", val);
}
} else {
lbl=newiTempLabel(NULL);
+ emitcode ("mov", "b,a");
+ emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
// right side is negative, 8-bit two's complement
- emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
+ emitcode ("cpl", "F0"); // complement sign flag
emitcode ("cpl", "a");
emitcode ("inc", "a");
emitcode ("", "%05d$:", lbl->key+100);
emitcode ("setb", "c");
while (sizer--)
{
- MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
- emitcode ("anl", "a,%s",
- aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
+ if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
+ emitcode ("anl", "a,%s",
+ aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
+ } else {
+ if (AOP_TYPE(left)==AOP_ACC) {
+ emitcode("mov", "b,a");
+ MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
+ emitcode("anl", "a,b");
+ }else {
+ MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
+ emitcode ("anl", "a,%s",
+ aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
+ }
+ }
emitcode ("jnz", "%05d$", tlbl->key + 100);
offset++;
}
emitcode ("setb", "c");
while (sizer--)
{
- MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
- emitcode ("orl", "a,%s",
- aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
+ if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
+ emitcode ("orl", "a,%s",
+ aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
+ } else {
+ MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
+ emitcode ("orl", "a,%s",
+ aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
+ }
emitcode ("jnz", "%05d$", tlbl->key + 100);
offset++;
}
}
else
{
- MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
- emitcode ("xrl", "a,%s",
- aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
+ if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
+ emitcode ("xrl", "a,%s",
+ aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
+ } else {
+ MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
+ emitcode ("xrl", "a,%s",
+ aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
+ }
}
emitcode ("jnz", "%05d$", tlbl->key + 100);
offset++;
static void
genInline (iCode * ic)
{
- char buffer[MAX_INLINEASM];
- char *bp = buffer;
- char *bp1 = buffer;
+ char *buffer, *bp, *bp1;
D (emitcode (";", "genInline ");
);
_G.inLine += (!options.asmpeep);
+
+ buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
strcpy (buffer, IC_INLINE (ic));
/* emit each line as a code */
}
}
-#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
-//REMOVE ME!!!
+#ifdef BETTER_LITERAL_SHIFT
/*-----------------------------------------------------------------*/
/* 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(lsb, shCount);
+ }
else
- AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount);
- if (getDataSize (result) > 1)
- aopPut (AOP (result), "a", offr + MSB16);
+ {
+ AccAXRsh(lsb, 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
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
shiftRLong (operand * left, int offl,
operand * result, int sign)
{
- if (!sign)
+ int isSameRegs=sameRegs(AOP(left),AOP(result));
+
+ if (isSameRegs && offl>1) {
+ // we are in big trouble, but this shouldn't happen
+ werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
+ }
+
+ MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
+
+ if (offl==MSB16) {
+ // shift is > 8
+ if (sign) {
+ emitcode ("rlc", "a");
+ emitcode ("subb", "a,acc");
+ emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
+ } else {
+ aopPut (AOP(result), zero, MSB32);
+ }
+ }
+
+ if (!sign) {
emitcode ("clr", "c");
- MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE));
- if (sign)
+ } else {
emitcode ("mov", "c,acc.7");
- emitcode ("rrc", "a");
- aopPut (AOP (result), "a", MSB32 - offl);
- if (offl == MSB16)
- /* add sign of "a" */
- addSign (result, MSB32, sign);
+ }
- MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE));
emitcode ("rrc", "a");
- aopPut (AOP (result), "a", MSB24 - offl);
- MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
+ if (isSameRegs && offl==MSB16) {
+ emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
+ } else {
+ aopPut (AOP (result), "a", MSB32);
+ MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
+ }
+
+ emitcode ("rrc", "a");
+ if (isSameRegs && offl==1) {
+ emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
+ } else {
+ aopPut (AOP (result), "a", MSB24);
+ MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
+ }
emitcode ("rrc", "a");
aopPut (AOP (result), "a", MSB16 - offl);
if (offl == LSB)
{
- MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, TRUE));
+ MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
emitcode ("rrc", "a");
aopPut (AOP (result), "a", LSB);
}
}
#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);
{
emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
- emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
+ if (options.model == MODEL_FLAT24)
+ emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
}
else
{
);
emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
- emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
+ if (options.model == MODEL_FLAT24)
+ emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
emitcode ("pop", "dph");
emitcode ("pop", "dpl");
}
{
emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
- emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
+ if (options.model == MODEL_FLAT24)
+ emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
}
else
{
);
emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
- emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
+ if (options.model == MODEL_FLAT24)
+ emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
emitcode ("pop", "dph");
emitcode ("pop", "dpl");
}
l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
genSetDPTR(0);
_flushLazyDPS();
- emitcode ("mov", "dpl,%s ;jwk lazy genGenPointerGet", l);
+ emitcode ("mov", "dpl,%s", l);
l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
genSetDPTR(0);
_flushLazyDPS();
- emitcode ("mov", "dph,%s ;jwk lazy genGenPointerGet", l);
- l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
- genSetDPTR(0);
- _flushLazyDPS();
- emitcode ("mov", "dpx,%s ;jwk lazy genGenPointerGet", l);
- emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
+ emitcode ("mov", "dph,%s", l);
+ if (options.model == MODEL_FLAT24) {
+ l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
+ genSetDPTR(0);
+ _flushLazyDPS();
+ emitcode ("mov", "dpx,%s", l);
+ emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
+ } else {
+ emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
+ }
} else {
emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
- emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
- emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
+ if (options.model == MODEL_FLAT24) {
+ emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
+ emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
+ } else {
+ emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
+ }
}
_endLazyDPSEvaluation ();
}
{
emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
- emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
+ if (options.model == MODEL_FLAT24)
+ emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
}
else
{
);
emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
- emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
+ if (options.model == MODEL_FLAT24)
+ emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
emitcode ("pop", "dph");
emitcode ("pop", "dpl");
}
{ /* we need to get it byte by byte */
emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
- emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
- emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
+ if (options.model == MODEL_FLAT24) {
+ emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
+ emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
+ } else {
+ emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
+ }
}
_endLazyDPSEvaluation ();
}
}
+/*-----------------------------------------------------------------*/
+/* genArrayInit - generates code for address of */
+/*-----------------------------------------------------------------*/
+static void
+genArrayInit (iCode * ic)
+{
+ literalList *iLoop;
+ int ix, count;
+ int elementSize = 0, eIndex;
+ unsigned val, lastVal;
+ sym_link *type;
+
+ D (emitcode (";", "genArrayInit "););
+
+ aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
+
+ if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
+ {
+ // Load immediate value into DPTR.
+ emitcode("mov", "dptr, %s",
+ aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, TRUE));
+ }
+ else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
+ {
+ werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+ "Unexpected operand to genArrayInit.\n");
+ exit(1);
+ }
+
+ type = operandType(IC_LEFT(ic));
+
+ if (type && type->next)
+ {
+ elementSize = getSize(type->next);
+ }
+ else
+ {
+ werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+ "can't determine element size in genArrayInit.\n");
+ exit(1);
+ }
+
+ iLoop = IC_ARRAYILIST(ic);
+ lastVal = 0xffff;
+
+ while (iLoop)
+ {
+ bool firstpass = TRUE;
+
+ emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
+ iLoop->count, (int)iLoop->literalValue, elementSize);
+
+ ix = iLoop->count;
+
+ while (ix)
+ {
+ symbol *tlbl = NULL;
+
+ count = ix > 256 ? 256 : ix;
+
+ if (count > 1)
+ {
+ tlbl = newiTempLabel (NULL);
+ if (firstpass || (count & 0xff))
+ {
+ emitcode("mov", "b, #0x%x", count & 0xff);
+ }
+
+ emitcode ("", "%05d$:", tlbl->key + 100);
+ }
+
+ firstpass = FALSE;
+
+ for (eIndex = 0; eIndex < elementSize; eIndex++)
+ {
+ val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
+ if (val != lastVal)
+ {
+ emitcode("mov", "a, #0x%x", val);
+ lastVal = val;
+ }
+
+ emitcode("movx", "@dptr, a");
+ emitcode("inc", "dptr");
+ }
+
+ if (count > 1)
+ {
+ emitcode("djnz", "b, %05d$", tlbl->key + 100);
+ }
+
+ ix -= count;
+ }
+
+ iLoop = iLoop->next;
+ }
+
+ freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
+}
+
/*-----------------------------------------------------------------*/
/* genFarFarAssign - assignment when both are in far space */
/*-----------------------------------------------------------------*/
{
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))
{
lineHead = lineCurr = NULL;
+ if (options.model == MODEL_FLAT24) {
+ fReturnSizeDS390 = 5;
+ fReturn = fReturn24;
+ } else {
+ fReturnSizeDS390 = 4;
+ fReturn = fReturn16;
+ options.stack10bit=0;
+ }
#if 0
//REMOVE ME!!!
/* print the allocation information */
addSet (&_G.sendSet, ic);
break;
+ case ARRAYINIT:
+ genArrayInit(ic);
+ break;
+
default:
ic = ic;
}