-------------------------------------------------------------------------*/
-//#define D(x)
-#define D(x) x
+#define D(x)
+//#define D(x) x
#include <stdio.h>
#include <stdlib.h>
char *aopLiteral (value * val, int offset);
char *aopLiteralLong (value * val, int offset, int size);
extern int allocInfo;
+static int pushReg (regs *reg, bool freereg);
+static void pullReg (regs *reg);
static char *zero = "#0x00";
static char *one = "#0x01";
int stackPushes;
short regsinuse;
set *sendSet;
+ iCode *current_iCode;
}
_G;
(lineHead = newLineNode (lb)));
lineCurr->isInline = _G.inLine;
lineCurr->isDebug = _G.debugLine;
+ lineCurr->ic = _G.current_iCode;
+ lineCurr->isComment = (*lbp==';');
//printf("%s\n", lb);
va_end (ap);
emitcode ("", "%05d$:", (tlbl->key +100));
}
+/*-----------------------------------------------------------------*/
+/* hc08_emitDebuggerSymbol - associate the current code location */
+/* with a debugger symbol */
+/*-----------------------------------------------------------------*/
+void
+hc08_emitDebuggerSymbol (char * debugSym)
+{
+ _G.debugLine = 1;
+ emitcode ("", "%s ==.", debugSym);
+ _G.debugLine = 0;
+}
/*--------------------------------------------------------------------------*/
return;
}
- emitcode ("", "; transferRegReg(%s,%s)",
- sreg->name, dreg->name);
+ D(emitcode ("", "; transferRegReg(%s,%s)",
+ sreg->name, dreg->name));
srcidx = sreg->rIdx;
dstidx = dreg->rIdx;
switch (srcidx)
{
case H_IDX: /* H to A */
- emitcode ("pshh", "");
- emitcode ("pula", "");
+ pushReg (hc08_reg_h, FALSE);
+ pullReg (hc08_reg_a);
break;
case X_IDX: /* X to A */
emitcode ("txa", "");
switch (srcidx)
{
case A_IDX: /* A to H */
- emitcode ("psha", "");
- emitcode ("pulh", "");
+ pushReg (hc08_reg_a, FALSE);
+ pullReg (hc08_reg_h);
break;
case X_IDX: /* X to H */
- emitcode ("pshx", "");
- emitcode ("pulh", "");
+ pushReg (hc08_reg_x, FALSE);
+ pullReg (hc08_reg_h);
break;
default:
error=1;
emitcode ("tax", "");
break;
case H_IDX: /* H to X */
- emitcode ("pshh", "");
- emitcode ("pulx", "");
+ pushReg (hc08_reg_h, FALSE);
+ pullReg (hc08_reg_x);
break;
default:
error=1;
switch (srcidx)
{
case XA_IDX: /* XA to HX */
- emitcode ("pshx", "");
- emitcode ("pulh", "");
+ pushReg (hc08_reg_x, FALSE);
+ pullReg (hc08_reg_h);
emitcode ("tax", "");
break;
default:
{
case HX_IDX: /* HX to XA */
emitcode ("txa", "");
- emitcode ("pshh", "");
- emitcode ("pulx", "");
+ pushReg (hc08_reg_h, FALSE);
+ pullReg (hc08_reg_x);
break;
default:
error=1;
hc08_useReg(dreg);
}
+/*--------------------------------------------------------------------------*/
+/* updateCFA - update the debugger information to reflect the current */
+/* connonical frame address relative to the stack pointer */
+/*--------------------------------------------------------------------------*/
+static void
+updateCFA(void)
+{
+ /* there is no frame unless there is a function */
+ if (!currFunc)
+ return;
+
+ debugFile->writeFrameAddress (NULL, hc08_reg_sp,
+ 1 + _G.stackOfs + _G.stackPushes);
+}
+
/*--------------------------------------------------------------------------*/
/* pushReg - Push register reg onto the stack. If freereg is true, reg is */
/* marked free and available for reuse. */
case A_IDX:
emitcode ("psha", "");
_G.stackPushes++;
+ updateCFA();
break;
case X_IDX:
emitcode ("pshx", "");
_G.stackPushes++;
+ updateCFA();
break;
case H_IDX:
emitcode ("pshh", "");
_G.stackPushes++;
+ updateCFA();
break;
case HX_IDX:
emitcode ("pshx", "");
+ _G.stackPushes++;
+ updateCFA();
emitcode ("pshh", "");
- _G.stackPushes += 2;
+ _G.stackPushes++;
+ updateCFA();
break;
case XA_IDX:
emitcode ("psha", "");
+ updateCFA();
+ _G.stackPushes++;
emitcode ("pshx", "");
- _G.stackPushes += 2;
+ updateCFA();
+ _G.stackPushes++;
break;
default:
break;
case A_IDX:
emitcode ("pula", "");
_G.stackPushes--;
+ updateCFA();
break;
case X_IDX:
emitcode ("pulx", "");
_G.stackPushes--;
+ updateCFA();
break;
case H_IDX:
emitcode ("pulh", "");
_G.stackPushes--;
+ updateCFA();
break;
case HX_IDX:
- emitcode ("pulx", "");
emitcode ("pulh", "");
- _G.stackPushes -= 2;
+ _G.stackPushes--;
+ updateCFA();
+ emitcode ("pulx", "");
+ _G.stackPushes--;
+ updateCFA();
break;
case XA_IDX:
- emitcode ("pula", "");
emitcode ("pulx", "");
- _G.stackPushes -= 2;
+ _G.stackPushes--;
+ updateCFA();
+ emitcode ("pula", "");
+ _G.stackPushes--;
+ updateCFA();
break;
default:
break;
{
emitcode("ais","#%d",n);
_G.stackPushes -= n;
+ updateCFA();
}
}
static void
adjustStack (int n)
{
- _G.stackPushes -= n;
while (n)
{
if (n>127)
{
emitcode ("ais","#127");
n -= 127;
+ _G.stackPushes -= 127;
+ updateCFA();
}
else if (n<-128)
{
emitcode ("ais","#-128");
n += 128;
+ _G.stackPushes += 128;
+ updateCFA();
}
else
{
emitcode ("ais", "#%d", n);
+ _G.stackPushes -= n;
n = 0;
+ updateCFA();
}
}
}
printf(" reg missing operand link\n");
#endif
- emitcode ("", "; loadRegFromAop (%s, %s, %d)",
- reg->name, aopName (aop), loffset);
+ D(emitcode ("", "; loadRegFromAop (%s, %s, %d)",
+ reg->name, aopName (aop), loffset));
/* If operand is volatile, we cannot optimize. */
if (!aop->op || isOperandVolatile (aop->op, FALSE))
&& (reg->aopofs == loffset))
{
hc08_useReg(reg);
- emitcode ("","; already had correct value for %s", reg->name);
+ D(emitcode ("","; already had correct value for %s", reg->name));
return;
}
&& operandsEqu(hc08_reg_h->aop->op,aop->op)
&& (hc08_reg_h->aopofs == loffset))
{
- emitcode ("","; found correct value for %s in h", reg->name);
+ D(emitcode ("","; found correct value for %s in h", reg->name));
transferRegReg (hc08_reg_h, reg, FALSE);
hc08_useReg (reg);
return;
&& operandsEqu(hc08_reg_x->aop->op,aop->op)
&& (hc08_reg_x->aopofs == loffset))
{
- emitcode ("","; found correct value for %s in x", reg->name);
+ D(emitcode ("","; found correct value for %s in x", reg->name));
transferRegReg (hc08_reg_x, reg, FALSE);
hc08_useReg (reg);
return;
&& operandsEqu(hc08_reg_a->aop->op,aop->op)
&& (hc08_reg_a->aopofs == loffset))
{
- emitcode ("","; found correct value for %s in a", reg->name);
+ D(emitcode ("","; found correct value for %s in a", reg->name));
transferRegReg (hc08_reg_a, reg, FALSE);
hc08_useReg (reg);
return;
emitcode ("clra", ""); /* TODO: handle sign extension */
}
else
- emitcode ("lda","%s", aopAdrStr (aop, loffset, FALSE));
+ {
+ char * l = aopAdrStr (aop, loffset, FALSE);
+ if (!strcmp (l, zero))
+ emitcode ("clra", "");
+ else
+ emitcode ("lda", "%s", l);
+ }
break;
case X_IDX:
if (aop->type == AOP_REG)
emitcode ("clrx", ""); /* TODO: handle sign extension */
}
else
- emitcode ("ldx","%s", aopAdrStr (aop, loffset, FALSE));
+ {
+ char * l = aopAdrStr (aop, loffset, FALSE);
+ if (!strcmp (l, zero))
+ emitcode ("clrx", "");
+ else
+ emitcode ("ldx", "%s", l);
+ }
break;
case H_IDX:
+ {
+ char * l = aopAdrStr (aop, loffset, FALSE);
+ if (!strcmp (l, zero))
+ {
+ emitcode ("clrh", "");
+ break;
+ }
+ }
if (hc08_reg_a->isFree)
{
loadRegFromAop (hc08_reg_a, aop, loffset);
asmop *newaop = newAsmop (aop->type);
memcpy (newaop, aop, sizeof(*newaop));
- emitcode("", "; forcedStackAop %s", aopName(aop));
+ D(emitcode("", "; forcedStackAop %s", aopName(aop)));
for (loffset=0; loffset < newaop->size; loffset++)
{
asmop *aopsof = newAsmop (AOP_SOF);
int otheridx;
#endif
- emitcode ("", "; storeRegToAop (%s, %s, %d), stacked=%d, isaddr=%d",
- reg->name, aopName (aop), loffset, aop->stacked, aop->isaddr);
+ D(emitcode ("", "; storeRegToAop (%s, %s, %d), stacked=%d, isaddr=%d",
+ reg->name, aopName (aop), loffset, aop->stacked, aop->isaddr));
if ((reg->rIdx == HX_IDX) && aop->stacked
&& (aop->stk_aop[loffset] || aop->stk_aop[loffset+1]))
return;
}
- switch (regidx)
+ if (aop->type == AOP_DUMMY)
+ return;
+
+ switch (regidx)
{
case A_IDX:
if ((aop->type == AOP_REG) && (loffset < aop->size))
&& operandsEqu(otherreg->aop->op,aop->op)
&& (otherreg->aopofs == loffset))
{
- emitcode("","; marking %s stale", otherreg->name);
+ D(emitcode("","; marking %s stale", otherreg->name));
otherreg->aop=NULL;
}
}
if ((!hc08_reg_x->aop || !hc08_reg_h->aop) && hc08_reg_hx->aop)
{
hc08_reg_hx->aop = NULL;
- emitcode("","; marking hx stale");
+ D(emitcode("","; marking hx stale"));
}
if ((!hc08_reg_x->aop || !hc08_reg_a->aop) && hc08_reg_xa->aop)
{
hc08_reg_xa->aop = NULL;
- emitcode("","; marking xa stale");
+ D(emitcode("","; marking xa stale"));
}
reg->aop = aop;
break;
loadRegFromConst (aop->aopu.aop_reg[loffset], c);
break;
+ case AOP_DUMMY:
+ break;
default:
if (hc08_reg_a->isFree)
{
/*--------------------------------------------------------------------------*/
/* transferAopAop - Transfer the value at logical offset srcofs of asmop */
-/* srcaop to logical offset dstofs of asmop dstofs. */
+/* srcaop to logical offset dstofs of asmop dstaop. */
/*--------------------------------------------------------------------------*/
static void
transferAopAop (asmop *srcaop, int srcofs, asmop *dstaop, int dstofs)
int regIdx;
bool keepreg = FALSE;
+ /* ignore transfers at the same byte, unless its volatile */
+ if (srcaop->op && !isOperandVolatile (srcaop->op, FALSE)
+ && dstaop->op && !isOperandVolatile (dstaop->op, FALSE)
+ && operandsEqu(srcaop->op, dstaop->op) && srcofs == dstofs)
+ return;
+
if (srcaop->stacked && srcaop->stk_aop[srcofs])
{
transferAopAop (srcaop->stk_aop[srcofs], 0, dstaop, dstofs);
return;
}
-// emitcode ("", "; transferAopAop (%s, %d, %s, %d)",
-// aopName (srcaop), srcofs, aopName (dstaop), dstofs);
-// emitcode ("", "; srcaop->type = %d", srcaop->type);
-// emitcode ("", "; dstaop->type = %d", dstaop->type);
+// D(emitcode ("", "; transferAopAop (%s, %d, %s, %d)",
+// aopName (srcaop), srcofs, aopName (dstaop), dstofs));
+// D(emitcode ("", "; srcaop->type = %d", srcaop->type));
+// D(emitcode ("", "; dstaop->type = %d", dstaop->type));
if (dstofs >= dstaop->size)
return;
if ((dstaop->type == AOP_DIR)
&& ((srcaop->type == AOP_DIR) || (srcaop->type == AOP_LIT)) )
{
+ if (srcaop->type == AOP_LIT)
+ {
+ unsigned long lit;
+ unsigned char bytemask;
+
+ lit = (unsigned long) floatFromVal (srcaop->aopu.aop_lit);
+ bytemask = (lit >> (srcofs*8)) & 0xff;
+
+ if (bytemask == 0)
+ {
+ emitcode ("clr", "%s", aopAdrStr(dstaop, dstofs, FALSE));
+ return;
+ }
+ }
+
emitcode("mov", "%s,%s", aopAdrStr(srcaop, srcofs, FALSE),
aopAdrStr(dstaop, dstofs, FALSE));
return;
accopWithAop (accop, aop->stk_aop[loffset], 0);
return;
}
-
+
+ if (aop->type == AOP_DUMMY)
+ return;
+
if (aop->type == AOP_REG)
{
pushReg (aop->aopu.aop_reg[loffset], FALSE);
/*--------------------------------------------------------------------------*/
/* accopWithAop - Emit read/modify/write instruction rmwop with the byte at */
/* logical offset loffset of asmop aop. */
-/* Supports: com, dec, inc, lsl, lsr, neg, rol, ror */
+/* Supports: com, dec, inc, lsl, lsr, neg, rol, ror, tst */
/*--------------------------------------------------------------------------*/
static void
rmwWithAop (char *rmwop, asmop *aop, int loffset)
break;
case AOP_EXT:
needpula = pushRegIfUsed (hc08_reg_a);
- loadRegFromAop (hc08_reg_a, aop, loffset);
+ loadRegFromAop (hc08_reg_a, aop, loffset);
rmwWithReg (rmwop, hc08_reg_a);
- storeRegToAop (hc08_reg_a, aop, loffset);
+ if (strcmp ("tst", rmwop))
+ storeRegToAop (hc08_reg_a, aop, loffset);
pullOrFreeReg (hc08_reg_a, needpula);
break;
+ case AOP_DUMMY:
+ break;
default:
emitcode (rmwop, "%s", aopAdrStr (aop, loffset, FALSE));
}
aopForRemat (symbol * sym)
{
iCode *ic = sym->rematiCode;
- asmop *aop = newAsmop (AOP_IMMD);
+ asmop *aop = NULL;
int ptr_type=0;
int val = 0;
ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
}
- if (val)
- sprintf (buffer, "(%s %c 0x%04x)",
- OP_SYMBOL (IC_LEFT (ic))->rname,
- val >= 0 ? '+' : '-',
- abs (val) & 0xffff);
- else
- strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
+ if (ic->op == ADDRESS_OF)
+ {
+ if (val)
+ sprintf (buffer, "(%s %c 0x%04x)",
+ OP_SYMBOL (IC_LEFT (ic))->rname,
+ val >= 0 ? '+' : '-',
+ abs (val) & 0xffff);
+ else
+ strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
- aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
- strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
- /* set immd2 field if required */
- if (aop->aopu.aop_immd.from_cast_remat) {
+ aop = newAsmop (AOP_IMMD);
+ aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
+ strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
+ /* set immd2 field if required */
+ if (aop->aopu.aop_immd.from_cast_remat)
+ {
sprintf(buffer,"#0x%02x",ptr_type);
aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
- }
+ }
+ }
+ else if (ic->op == '=')
+ {
+ val += (int) operandLitValue (IC_RIGHT (ic));
+ val &= 0xffff;
+ sprintf (buffer, "0x%04x", val);
+ aop = newAsmop (AOP_LIT);
+ aop->aopu.aop_lit = constVal (buffer);
+ }
+ else
+ werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+ "unexpected rematerialization");
+
+
return aop;
}
if (sym1 == sym2)
return TRUE;
- if (strcmp (sym1->rname, sym2->rname) == 0)
+ if (sym1->rname[0] && sym2->rname[0]
+ && strcmp (sym1->rname, sym2->rname) == 0)
return TRUE;
-
/* if left is a tmp & right is not */
if (IS_ITEMP (op1) &&
!IS_ITEMP (op2) &&
}
#endif
/* else spill location */
-// printf("checking spill loc\n");
-// if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
- if (sym->usl.spillLoc && sym->usl.spillLoc->aop
- && sym->usl.spillLoc->aop->size != getSize (sym->type))
+ if (sym->usl.spillLoc)
{
- /* force a new aop if sizes differ */
- sym->usl.spillLoc->aop = NULL;
- //printf ("forcing new aop\n");
- }
- sym->aop = op->aop = aop =
- aopForSym (ic, sym->usl.spillLoc, result);
+ if (sym->usl.spillLoc->aop
+ && sym->usl.spillLoc->aop->size != getSize (sym->type))
+ {
+ /* force a new aop if sizes differ */
+ sym->usl.spillLoc->aop = NULL;
+ //printf ("forcing new aop\n");
+ }
+ sym->aop = op->aop = aop = aopForSym (ic, sym->usl.spillLoc, result);
+ aop->size = getSize (sym->type);
+ aop->op = op;
+ aop->isaddr = op->isaddr;
+ //printf ("spill symbol %s\n", OP_SYMBOL (op)->name);
+ //printf (" with size = %d\n", aop->size);
+ return;
+ }
+
+ /* else must be a dummy iTemp */
+ sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
aop->size = getSize (sym->type);
- aop->op = op;
- aop->isaddr = op->isaddr;
- //printf ("spill symbol %s\n", OP_SYMBOL (op)->name);
- //printf (" with size = %d\n", aop->size);
- /* if (aop->isaddr & IS_ITEMP (op))
- {
- aop->psize=aop->size;
- aop->size = getSize( operandType (op)->next);
- } */
return;
}
int stackAdjust;
int loffset;
- emitcode ("","; freeAsmop restoring stacked %s", aopName(aop));
+ D(emitcode ("","; freeAsmop restoring stacked %s", aopName(aop)));
aop->stacked = 0;
stackAdjust = 0;
for (loffset=0; loffset<aop->size; loffset++)
sym_link *type, *etype;
int p_type;
- emitcode ("", "; aopDerefAop(%s)", aopName(aop));
+ D(emitcode ("", "; aopDerefAop(%s)", aopName(aop)));
if (aop->op)
{
switch (aop->type)
{
+ case AOP_DUMMY:
+ return zero;
+
case AOP_IMMD:
if (aop->aopu.aop_immd.from_cast_remat && (loffset == (aop->size-1))) {
sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
case AOP_LIT:
if (bit16)
- return aopLiteralLong (aop->aopu.aop_lit, loffset, 2);
+ return aopLiteralLong (aop->aopu.aop_lit, /*loffset*/ 0, 2);
else
return aopLiteral (aop->aopu.aop_lit, loffset);
return size;
}
-/*-----------------------------------------------------------------*/
-/* outAcc - output Acc */
-/*-----------------------------------------------------------------*/
-static void
-outAcc (operand * result)
-{
- int size, offset;
- size = getDataSize (result);
- if (size)
- {
- storeRegToAop (hc08_reg_a, AOP (result), 0);
- size--;
- offset = 1;
- /* unsigned or positive */
- while (size--)
- {
- storeConstToAop (zero, AOP (result), offset++);
- }
- }
-}
-
-/*-----------------------------------------------------------------*/
-/* outBitC - output a bit C */
-/*-----------------------------------------------------------------*/
-static void
-outBitC (operand * result)
-{
-
-#if 0
- /* if the result is bit */
- if (AOP_TYPE (result) == AOP_CRY)
- aopPut (AOP (result), "c", 0);
- else
-#endif
- {
- emitcode ("clra", "");
- emitcode ("rola", "");
- outAcc (result);
- }
-}
-
-/*-----------------------------------------------------------------*/
-/* outBitNV - output a bit N^V */
-/*-----------------------------------------------------------------*/
-static void
-outBitNV (operand * result)
-{
- symbol *tlbl, *tlbl1;
-
- tlbl = newiTempLabel (NULL);
- tlbl1 = newiTempLabel (NULL);
-
- emitBranch ("blt", tlbl);
- loadRegFromConst (hc08_reg_a, zero);
- emitBranch ("bra", tlbl1);
- emitLabel (tlbl);
- loadRegFromConst (hc08_reg_a, one);
- emitLabel (tlbl1);
- outAcc (result);
-}
-
/*-----------------------------------------------------------------*/
/* asmopToBool - Emit code to convert an asmop to a boolean. */
emitcode ("", "%05d$:", (tlbl->key + 100));
}
else
- werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
- "Bad rIdx in asmToBool");
- return;
+ {
+ werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+ "Bad rIdx in asmToBool");
+ return;
+ }
+ break;
case AOP_EXT:
if (resultInA)
needpula = FALSE;
hc08_useReg (reg);
storeRegToAop (reg, AOP (IC_RESULT (ic)), offset);
hc08_freeReg (reg);
+ offset++;
}
/* release the aops */
while (size--)
{
- if (!size)
- {
- needpula = pushRegIfUsed (hc08_reg_a);
- loadRegFromAop (hc08_reg_a, AOP (op), offset);
- emitcode ("eor", "#0x80");
- hc08_useReg (hc08_reg_a);
- storeRegToAop (hc08_reg_a, AOP (result), offset);
- pullOrFreeReg (hc08_reg_a, needpula);
- }
- else
- transferAopAop (AOP (op), offset, AOP (result), offset);
+ transferAopAop (AOP (op), offset, AOP (result), offset);
offset++;
}
+ needpula = pushRegIfUsed (hc08_reg_a);
+ loadRegFromAop (hc08_reg_a, AOP (op), offset);
+ emitcode ("eor", "#0x80");
+ hc08_useReg (hc08_reg_a);
+ storeRegToAop (hc08_reg_a, AOP (result), offset);
+ pullOrFreeReg (hc08_reg_a, needpula);
}
/*-----------------------------------------------------------------*/
sym_link *optype, *rtype;
char *sub;
bool needpula;
+ asmop *result;
D(emitcode ("; genUminus",""));
if (size == 1)
{
- needpula = pushRegIfUsed (hc08_reg_a);
+ if (!IS_AOP_A (AOP (IC_LEFT (ic))))
+ needpula = pushRegIfUsed (hc08_reg_a);
+ else
+ needpula = FALSE;
loadRegFromAop (hc08_reg_a, AOP( IC_LEFT (ic)), 0);
emitcode ("nega", "");
hc08_freeReg (hc08_reg_a);
}
else
{
+ if (IS_AOP_XA (AOP (IC_RESULT (ic))))
+ result = forceStackedAop (AOP (IC_RESULT (ic)));
+ else
+ result = AOP (IC_RESULT (ic));
+
needpula = pushRegIfUsed (hc08_reg_a);
sub="sub";
while (size--)
{
loadRegFromConst (hc08_reg_a, zero);
accopWithAop (sub, AOP( IC_LEFT (ic)), offset);
- storeRegToAop (hc08_reg_a, AOP( IC_RESULT (ic)), offset++);
+ storeRegToAop (hc08_reg_a, result, offset++);
sub = "sbc";
}
- storeRegSignToUpperAop (hc08_reg_a, AOP( IC_RESULT (ic)), offset,
+ storeRegSignToUpperAop (hc08_reg_a, result, offset,
SPEC_USIGN (operandType (IC_LEFT (ic))));
pullOrFreeReg (hc08_reg_a, needpula);
+
+ if (IS_AOP_XA (AOP (IC_RESULT (ic))))
+ freeAsmop (NULL, result, ic, TRUE);
}
release:
/* release the aops */
freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
- freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
+ freeAsmop (IC_LEFT (ic), NULL, ic, FALSE);
}
/*-----------------------------------------------------------------*/
{
iCode *sic;
- for (sic = setFirstItem (_G.sendSet); sic;
- sic = setNextItem (_G.sendSet)) {
+ for (sic = setFirstItem (sendSet); sic;
+ sic = setNextItem (sendSet)) {
int size, offset = 0;
aopOp (IC_LEFT (sic), sic, FALSE);
size = AOP_SIZE (IC_LEFT (sic));
- if (sic->argreg) {
+ if (sic->argreg) {
offset = size-1;
while (size--) {
transferAopAop( AOP (IC_LEFT (sic)), offset,
D(emitcode("; genCall",""));
dtype = operandType (IC_LEFT (ic));
- /* if send set is not empty the assign */
+ /* if send set is not empty then assign */
if (_G.sendSet)
{
if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
static void
genFunction (iCode * ic)
{
- symbol *sym;
+ symbol *sym = OP_SYMBOL (IC_LEFT (ic));
sym_link *ftype;
- int calleesaves_saved_register = -1;
+ iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
+ int stackAdjust = sym->stack;
+ int accIsFree = sym->recvSize == 0;
_G.nRegsSaved = 0;
_G.stackPushes = 0;
/* create the function header */
emitcode (";", "-----------------------------------------");
- emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
+ emitcode (";", " function %s", sym->name);
emitcode (";", "-----------------------------------------");
emitcode ("", "%s:", sym->rname);
ftype = operandType (IC_LEFT (ic));
+
+ _G.stackOfs = 0;
+ _G.stackPushes = 0;
+ debugFile->writeFrameAddress (NULL, hc08_reg_sp, 0);
if (IFFUNC_ISNAKED(ftype))
{
return;
}
-
-
/* if this is an interrupt service routine then
save h */
if (IFFUNC_ISISR (sym->type))
{
if (!inExcludeList ("h"))
- emitcode ("pshh", "");
+ pushReg (hc08_reg_h, FALSE);
}
- else
+
+ /* For some cases it is worthwhile to perform a RECEIVE iCode */
+ /* before setting up the stack frame completely. */
+ while (ric && ric->next && ric->next->op == RECEIVE)
+ ric = ric->next;
+ while (ric && IC_RESULT (ric))
{
- /* if callee-save to be used for this function
- then save the registers being used in this function */
- if (IFFUNC_CALLEESAVES(sym->type))
- {
- int i;
+ symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
+ int rsymSize = rsym ? getSize(rsym->type) : 0;
- /* if any registers used */
- if (sym->regsUsed)
- {
- /* save the registers used */
- for (i = 0; i < sym->regsUsed->size; i++)
- {
- if (bitVectBitValue (sym->regsUsed, i))
- {
- /* remember one saved register for later usage */
- if (calleesaves_saved_register < 0)
- calleesaves_saved_register = i;
- pushReg (hc08_regWithIdx (i), FALSE);
- _G.nRegsSaved++;
- }
- }
- }
- }
- }
+ if (rsym->isitmp)
+ {
+ if (rsym && rsym->regType == REG_CND)
+ rsym = NULL;
+ if (rsym && (rsym->accuse || rsym->ruonly))
+ rsym = NULL;
+ if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
+ rsym = rsym->usl.spillLoc;
+ }
- if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
- {
+ /* If the RECEIVE operand immediately spills to the first entry on the */
+ /* stack, we can push it directly rather than use an sp relative store. */
+ if (rsym && rsym->onStack && rsym->stack == -_G.stackPushes-rsymSize)
+ {
+ int ofs;
+ _G.current_iCode = ric;
+ D(emitcode ("; genReceive",""));
+ for (ofs=0; ofs < rsymSize; ofs++)
+ {
+ regs * reg = hc08_aop_pass[ofs+(ric->argreg-1)]->aopu.aop_reg[0];
+ pushReg (reg, TRUE);
+ if (reg->rIdx == A_IDX)
+ accIsFree = 1;
+ stackAdjust--;
+ }
+ _G.current_iCode = ic;
+ ric->generated = 1;
+ }
+ ric = (ric->prev && ric->prev->op == RECEIVE) ? ric->prev : NULL;
}
/* adjust the stack for the function */
- if (sym->stack)
+ if (stackAdjust)
{
-
- int i = sym->stack;
-// if (i > 256)
-// werror (W_STACK_OVERFLOW, sym->name);
-
- adjustStack (-i);
+ adjustStack (-stackAdjust);
}
_G.stackOfs = sym->stack;
_G.stackPushes = 0;
/* if critical function then turn interrupts off */
if (IFFUNC_ISCRITICAL (ftype))
{
- if (IFFUNC_ARGS (ftype))
+ if (!accIsFree)
{
/* Function was passed parameters, so make sure A is preserved */
pushReg (hc08_reg_a, FALSE);
if (IFFUNC_ISNAKED(sym->type))
{
emitcode(";", "naked function: no epilogue.");
+ if (options.debug && currFunc)
+ debugFile->writeEndFunction (currFunc, ic, 0);
return;
}
{
if (!inExcludeList ("h"))
- emitcode ("pulh", "");
+ pullReg (hc08_reg_h);
/* if debug then send end of function */
if (options.debug && currFunc)
{
- _G.debugLine = 1;
- emitcode ("", "C$%s$%d$%d$%d ==.",
- FileBaseName (ic->filename), currFunc->lastLine,
- ic->level, ic->block);
- if (IS_STATIC (currFunc->etype))
- emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
- else
- emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
- _G.debugLine = 0;
+ debugFile->writeEndFunction (currFunc, ic, 1);
}
emitcode ("rti", "");
{
if (bitVectBitValue (sym->regsUsed, i) ||
(hc08_ptrRegReq && (i == HX_IDX || i == HX_IDX)))
- emitcode ("pop", "%s", hc08_regWithIdx (i)->dname);
+ emitcode ("pop", "%s", hc08_regWithIdx (i)->name);
}
}
/* if debug then send end of function */
if (options.debug && currFunc)
{
- _G.debugLine = 1;
- emitcode ("", "C$%s$%d$%d$%d ==.",
- FileBaseName (ic->filename), currFunc->lastLine,
- ic->level, ic->block);
- if (IS_STATIC (currFunc->etype))
- emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
- else
- emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
- _G.debugLine = 0;
+ debugFile->writeEndFunction (currFunc, ic, 1);
}
emitcode ("rts", "");
/* special case never generate */
if (IC_LABEL (ic) == entryLabel)
return;
+
+ debugFile->writeLabel(IC_LABEL (ic), ic);
emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
bool needpulh;
bool needpula;
unsigned int size = getDataSize (IC_RESULT (ic));
- int offset;
+ unsigned int offset;
symbol *tlbl = NULL;
left = IC_LEFT (ic);
icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
- emitcode ("", "; IS_AOP_HX = %d", IS_AOP_HX (AOP (left)));
+ D(emitcode ("", "; IS_AOP_HX = %d", IS_AOP_HX (AOP (left))));
if ((IS_AOP_HX (AOP (left)) ||
( (AOP_TYPE (left) == AOP_DIR) && (AOP_TYPE (result) == AOP_DIR) )
)
&& (icount>=-128) && (icount<=127) && (size==2))
{
- needpulx = pushRegIfUsed (hc08_reg_x);
- needpulh = pushRegIfUsed (hc08_reg_h);
+ if (!IS_AOP_HX (AOP (left)))
+ {
+ needpulx = pushRegIfUsed (hc08_reg_x);
+ needpulh = pushRegIfUsed (hc08_reg_h);
+ }
+ else
+ {
+ needpulx = FALSE;
+ needpulh = FALSE;
+ }
loadRegFromAop (hc08_reg_hx, AOP(left), 0);
emitcode ("aix","#%d", icount);
hc08_dirtyReg (hc08_reg_hx, FALSE);
return TRUE;
}
- emitcode ("", "; icount = %d, sameRegs=%d", icount,
- sameRegs (AOP (left), AOP (result)));
+ D(emitcode ("", "; icount = %d, sameRegs=%d", icount,
+ sameRegs (AOP (left), AOP (result))));
if ((icount > 255) || (icount<0))
return FALSE;
}
else
{
- needpula = pushRegIfUsed (hc08_reg_a);
+ if (!IS_AOP_A (AOP (result)) && !IS_AOP_XA (AOP (result)))
+ needpula = pushRegIfUsed (hc08_reg_a);
+ else
+ needpula = FALSE;
loadRegFromAop (hc08_reg_a, AOP (result), 0);
accopWithAop ("add", AOP (IC_RIGHT (ic)), 0);
hc08_useReg (hc08_reg_a);
if (genPlusIncr (ic) == TRUE)
goto release;
- emitcode("","; left size = %d", getDataSize (IC_LEFT(ic)));
- emitcode("","; right size = %d", getDataSize (IC_RIGHT(ic)));
- emitcode("","; result size = %d", getDataSize (IC_RESULT(ic)));
+ D(emitcode("","; left size = %d", getDataSize (IC_LEFT(ic))));
+ D(emitcode("","; right size = %d", getDataSize (IC_RIGHT(ic))));
+ D(emitcode("","; result size = %d", getDataSize (IC_RESULT(ic))));
size = getDataSize (IC_RESULT (ic));
if ((AOP_TYPE (left) == AOP_DIR) && (AOP_TYPE (result) == AOP_DIR)
&& (icount>=-127) && (icount<=128) && (size==2))
{
- needpulx = pushRegIfUsed (hc08_reg_x);
- needpulh = pushRegIfUsed (hc08_reg_h);
+ if (!IS_AOP_HX (AOP (left)))
+ {
+ needpulx = pushRegIfUsed (hc08_reg_x);
+ needpulh = pushRegIfUsed (hc08_reg_h);
+ }
+ else
+ {
+ needpulx = FALSE;
+ needpulh = FALSE;
+ }
loadRegFromAop (hc08_reg_hx, AOP(left), 0);
emitcode ("aix","#%d", -icount);
hc08_dirtyReg (hc08_reg_hx, FALSE);
{
char *sub;
int size, offset = 0;
+
+ asmop *leftOp, *rightOp;
D(emitcode ("; genMinus",""));
size = getDataSize (IC_RESULT (ic));
- asmop *leftOp, *rightOp;
leftOp = AOP(IC_LEFT(ic));
rightOp = AOP(IC_RIGHT(ic));
operand * right,
operand * result)
{
- sym_link *opetype = operandType (result);
+ /* sym_link *opetype = operandType (result); */
symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
int size=AOP_SIZE(result);
bool negLiteral = FALSE;
+ bool lUnsigned, rUnsigned;
D(emitcode ("; genMultOneByte",""));
operand *t = right;
right = left;
left = t;
- //emitcode (";", "swapped left and right");
+ }
+ /* if an operand is in A, make sure it is on the left */
+ if (IS_AOP_A (AOP (right)))
+ {
+ operand *t = right;
+ right = left;
+ left = t;
}
- if (SPEC_USIGN(opetype))
+ lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
+ rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
+
+ /* lUnsigned rUnsigned negLiteral negate case */
+ /* false false false odd 3 */
+ /* false false true even 3 */
+ /* false true false odd 3 */
+ /* false true true impossible */
+ /* true false false odd 3 */
+ /* true false true always 2 */
+ /* true true false never 1 */
+ /* true true true impossible */
+
+ /* case 1 */
+ if (size == 1
+ || (lUnsigned && rUnsigned))
{
// just an unsigned 8*8=8/16 multiply
- //emitcode (";","unsigned");
+ //D(emitcode (";","unsigned"));
loadRegFromAop (hc08_reg_a, AOP (left), 0);
loadRegFromAop (hc08_reg_x, AOP (right), 0);
// we have to do a signed multiply
+ /* case 2 */
+ /* left unsigned, right signed literal -- literal determines sign handling */
+ if (AOP_TYPE(right)==AOP_LIT && lUnsigned && !rUnsigned)
+ {
+ signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
+
+ loadRegFromAop (hc08_reg_a, AOP (left), 0);
+ if (val < 0)
+ emitcode ("ldx", "#0x%02x", -val);
+ else
+ emitcode ("ldx", "#0x%02x", val);
+
+ emitcode ("mul", "");
+
+ if (val < 0)
+ {
+ rmwWithReg ("neg", hc08_reg_a);
+ tlbl4 = newiTempLabel (NULL);
+ emitBranch ("bcc", tlbl4);
+ rmwWithReg ("inc", hc08_reg_x);
+ emitLabel (tlbl4);
+ rmwWithReg ("neg", hc08_reg_x);
+ }
+
+ hc08_dirtyReg (hc08_reg_xa, FALSE);
+ storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
+ hc08_freeReg (hc08_reg_xa);
+ return;
+ }
+
- //emitcode (";", "signed");
+ /* case 3 */
adjustStack (-1);
emitcode ("clr", "1,s");
- tlbl1 = newiTempLabel (NULL);
loadRegFromAop (hc08_reg_a, AOP (left), 0);
- emitcode ("tsta","");
- emitBranch ("bpl", tlbl1);
- emitcode ("inc", "1,s");
- rmwWithReg ("neg", hc08_reg_a);
- emitLabel (tlbl1);
+ if (!lUnsigned)
+ {
+ tlbl1 = newiTempLabel (NULL);
+ emitcode ("tsta","");
+ emitBranch ("bpl", tlbl1);
+ emitcode ("inc", "1,s");
+ rmwWithReg ("neg", hc08_reg_a);
+ emitLabel (tlbl1);
+ }
- if (AOP_TYPE(right)==AOP_LIT)
+ if (AOP_TYPE(right)==AOP_LIT && !rUnsigned)
{
signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
/* AND literal negative */
}
else
{
- tlbl2 = newiTempLabel (NULL);
loadRegFromAop (hc08_reg_x, AOP (right), 0);
- emitcode ("tstx", "");
- emitBranch ("bpl", tlbl2);
- emitcode ("inc", "1,s");
- rmwWithReg ("neg", hc08_reg_x);
- emitLabel (tlbl2);
+ if (!rUnsigned)
+ {
+ tlbl2 = newiTempLabel (NULL);
+ emitcode ("tstx", "");
+ emitBranch ("bpl", tlbl2);
+ emitcode ("inc", "1,s");
+ rmwWithReg ("neg", hc08_reg_x);
+ emitLabel (tlbl2);
+ }
}
emitcode ("mul", "");
tlbl3 = newiTempLabel (NULL);
emitcode ("dec", "1,s");
- if (negLiteral)
- emitBranch ("bne", tlbl3);
- else
+ if (!lUnsigned && !rUnsigned && negLiteral)
emitBranch ("beq", tlbl3);
+ else
+ emitBranch ("bne", tlbl3);
rmwWithReg ("neg", hc08_reg_a);
- if (size>1)
- {
- tlbl4 = newiTempLabel (NULL);
- emitBranch ("bcc", tlbl4);
- rmwWithReg ("inc", hc08_reg_x);
- emitLabel (tlbl4);
- rmwWithReg ("neg", hc08_reg_x);
- }
+ tlbl4 = newiTempLabel (NULL);
+ emitBranch ("bcc", tlbl4);
+ rmwWithReg ("inc", hc08_reg_x);
+ emitLabel (tlbl4);
+ rmwWithReg ("neg", hc08_reg_x);
emitLabel (tlbl3);
adjustStack (1);
operand * right,
operand * result)
{
- sym_link *opetype = operandType (result);
-// char *l;
- symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
+ symbol *tlbl1, *tlbl2, *tlbl3;
int size;
- bool negLiteral = FALSE;
+ int offset = 0;
+ bool lUnsigned, rUnsigned;
+ bool runtimeSign, compiletimeSign;
+
+ lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
+ rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
D(emitcode ("; genDivOneByte",""));
size = AOP_SIZE (result);
/* signed or unsigned */
- if (SPEC_USIGN (opetype))
+ if (lUnsigned && rUnsigned)
{
/* unsigned is easy */
loadRegFromAop (hc08_reg_h, AOP (left), 1);
- loadRegFromAop (hc08_reg_a, AOP (left), 0);
loadRegFromAop (hc08_reg_x, AOP (right), 0);
+ loadRegFromAop (hc08_reg_a, AOP (left), 0);
emitcode ("div", "");
hc08_dirtyReg (hc08_reg_a, FALSE);
hc08_dirtyReg (hc08_reg_h, FALSE);
/* signed is a little bit more difficult */
- adjustStack (-1);
- emitcode ("clr", "1,s");
+ /* now sign adjust for both left & right */
- tlbl1 = newiTempLabel (NULL);
- tlbl2 = newiTempLabel (NULL);
- loadRegFromAop (hc08_reg_a, AOP (left), 0);
- loadRegFromAop (hc08_reg_x, AOP (left), 1);
- emitBranch ("bpl", tlbl1);
- emitcode ("inc", "1,s");
- rmwWithReg ("neg", hc08_reg_a);
- emitBranch ("bcc", tlbl2);
- rmwWithReg ("inc", hc08_reg_x);
- emitLabel (tlbl2);
- rmwWithReg ("neg", hc08_reg_x);
- transferRegReg (hc08_reg_x, hc08_reg_h, TRUE);
- emitLabel (tlbl1);
+ /* let's see what's needed: */
+ /* apply negative sign during runtime */
+ runtimeSign = FALSE;
+ /* negative sign from literals */
+ compiletimeSign = FALSE;
- if (AOP_TYPE(right)==AOP_LIT)
+ if (!lUnsigned)
{
- signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
- /* AND literal negative */
- if (val < 0) {
+ 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 the runtime sign */
+ if (runtimeSign)
+ {
+ if (compiletimeSign)
+ loadRegFromConst (hc08_reg_x, "#1"); /* set sign flag */
+ else
+ loadRegFromConst (hc08_reg_x, zero); /* reset sign flag */
+ pushReg (hc08_reg_x, TRUE);
+ }
+
+ /* 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 ("ldx", "#0x%02x", -val);
- negLiteral = TRUE;
- } else {
- emitcode ("ldx", "#0x%02x", val);
- }
- hc08_useReg (hc08_reg_x);
+ else
+ emitcode ("ldx", "#0x%02x", (unsigned char) val);
}
- else
+ else /* ! literal */
{
- tlbl3 = newiTempLabel (NULL);
loadRegFromAop (hc08_reg_x, AOP (right), 0);
- emitBranch ("bpl", tlbl3);
- emitcode ("inc", "1,s");
- rmwWithReg ("neg", hc08_reg_x);
- emitLabel (tlbl3);
+ if (!rUnsigned)
+ {
+ tlbl1 = newiTempLabel (NULL);
+ emitcode ("tstx", "");
+ emitBranch ("bpl", tlbl1);
+ emitcode ("inc", "1,s");
+ rmwWithReg ("neg", hc08_reg_x);
+ emitLabel (tlbl1);
+ }
}
+ if (AOP_TYPE(left) == AOP_LIT)
+ {
+ signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
+
+ if (!lUnsigned && val < 0)
+ emitcode ("lda", "#0x%02x", -val);
+ else
+ emitcode ("lda", "#0x%02x", (unsigned char) val);
+ }
+ else /* ! literal */
+ {
+ loadRegFromAop (hc08_reg_a, AOP (left), 0);
+ if (!lUnsigned)
+ {
+ tlbl2 = newiTempLabel (NULL);
+ emitcode ("tsta", "");
+ emitBranch ("bpl", tlbl2);
+ emitcode ("inc", "1,s");
+ rmwWithReg ("neg", hc08_reg_a);
+ emitLabel (tlbl2);
+ }
+ }
+
+ loadRegFromConst (hc08_reg_h, zero);
emitcode ("div", "");
hc08_dirtyReg (hc08_reg_x, FALSE);
hc08_dirtyReg (hc08_reg_a, FALSE);
hc08_dirtyReg (hc08_reg_h, FALSE);
-
- tlbl4 = newiTempLabel (NULL);
- emitcode ("dec", "1,s");
- if (negLiteral)
- emitBranch ("bne", tlbl4);
+
+ if (runtimeSign || compiletimeSign)
+ {
+ tlbl3 = newiTempLabel (NULL);
+ if (runtimeSign)
+ {
+ pullReg (hc08_reg_x);
+ rmwWithReg ("lsr", hc08_reg_x);
+ rmwWithReg ("ror", hc08_reg_x);
+ emitBranch ("bpl", tlbl3);
+ }
+
+ rmwWithReg ("neg", hc08_reg_a);
+ if (runtimeSign)
+ emitLabel (tlbl3);
+
+ storeRegToAop (hc08_reg_a, AOP (result), 0);
+
+ if (size > 1)
+ {
+ /* msb is 0x00 or 0xff depending on the sign */
+ if (runtimeSign)
+ {
+ rmwWithReg ("lsl", hc08_reg_x);
+ emitcode ("clra", "");
+ emitcode ("sbc", "#0");
+ while (--size)
+ storeRegToAop (hc08_reg_a, AOP (result), ++offset);
+ }
+ else /* compiletimeSign */
+ while (--size)
+ storeConstToAop ("#0xff", AOP (result), ++offset);
+ }
+ }
else
- emitBranch ("beq", tlbl4);
- rmwWithReg ("neg", hc08_reg_a);
+ {
+ storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
+ }
- emitLabel (tlbl4);
- adjustStack (1);
- storeRegToFullAop (hc08_reg_a, AOP (result), TRUE);
hc08_freeReg (hc08_reg_a);
hc08_freeReg (hc08_reg_x);
hc08_freeReg (hc08_reg_h);
-
-
}
/*-----------------------------------------------------------------*/
operand * right,
operand * result)
{
- sym_link *opetype = operandType (result);
-// symbol *lbl;
- symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
+ symbol *tlbl1, *tlbl2, *tlbl3;
int size;
- bool negLiteral = FALSE;
+ int offset = 0;
+ bool lUnsigned, rUnsigned;
+ bool runtimeSign, compiletimeSign;
+
+ lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
+ rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
D(emitcode ("; genModOneByte",""));
size = AOP_SIZE (result);
- /* signed or unsigned */
- if (SPEC_USIGN (opetype))
+
+ if (lUnsigned && rUnsigned)
{
/* unsigned is easy */
+ loadRegFromAop (hc08_reg_x, AOP (right), 0);
loadRegFromAop (hc08_reg_h, AOP (left), 1);
loadRegFromAop (hc08_reg_a, AOP (left), 0);
- loadRegFromAop (hc08_reg_x, AOP (right), 0);
emitcode ("div", "");
hc08_dirtyReg (hc08_reg_a, FALSE);
hc08_dirtyReg (hc08_reg_h, FALSE);
}
/* signed is a little bit more difficult */
-
- adjustStack (-1);
- emitcode ("clr", "1,s");
-
- tlbl1 = newiTempLabel (NULL);
- tlbl2 = newiTempLabel (NULL);
- loadRegFromAop (hc08_reg_a, AOP (left), 0);
- loadRegFromAop (hc08_reg_x, AOP (left), 1);
- emitBranch ("bpl", tlbl1);
- emitcode ("inc", "1,s");
- rmwWithReg ("neg", hc08_reg_a);
- emitBranch ("bcc", tlbl2);
- rmwWithReg ("inc", hc08_reg_x);
- emitLabel (tlbl2);
- rmwWithReg ("neg", hc08_reg_x);
- transferRegReg (hc08_reg_x, hc08_reg_h, TRUE);
- emitLabel (tlbl1);
-
- if (AOP_TYPE(right)==AOP_LIT)
+
+ if (AOP_TYPE(right) == AOP_LIT)
{
- signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
- /* AND literal negative */
- if (val < 0) {
+ signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
+
+ if (!rUnsigned && val < 0)
emitcode ("ldx", "#0x%02x", -val);
- negLiteral = TRUE;
- } else {
- emitcode ("ldx", "#0x%02x", val);
- }
- hc08_useReg (hc08_reg_x);
+ else
+ emitcode ("ldx", "#0x%02x", (unsigned char) val);
}
- else
+ else /* ! literal */
{
- tlbl3 = newiTempLabel (NULL);
loadRegFromAop (hc08_reg_x, AOP (right), 0);
- emitBranch ("bpl", tlbl3);
- emitcode ("inc", "1,s");
- rmwWithReg ("neg", hc08_reg_x);
- emitLabel (tlbl3);
+ if (!rUnsigned)
+ {
+ tlbl1 = newiTempLabel (NULL);
+ emitcode ("tstx", "");
+ emitBranch ("bpl", tlbl1);
+ rmwWithReg ("neg", hc08_reg_x);
+ emitLabel (tlbl1);
+ }
}
+
+ /* let's see what's needed: */
+ /* apply negative sign during runtime */
+ runtimeSign = FALSE;
+ /* negative sign from literals */
+ compiletimeSign = FALSE;
+
+ /* sign adjust left side */
+ if (AOP_TYPE(left) == AOP_LIT)
+ {
+ signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
+ if (!lUnsigned && val < 0)
+ {
+ compiletimeSign = TRUE; /* set sign flag */
+ emitcode ("lda", "#0x%02x", -val);
+ }
+ else
+ emitcode ("lda", "#0x%02x", (unsigned char) val);
+ }
+ else /* ! literal */
+ {
+ if (lUnsigned)
+ loadRegFromAop (hc08_reg_a, AOP (left), 0);
+ else
+ {
+ runtimeSign = TRUE;
+ adjustStack (-1);
+ emitcode ("clr", "1,s");
+
+ loadRegFromAop (hc08_reg_a, AOP (left), 0);
+ tlbl2 = newiTempLabel (NULL);
+ emitcode ("tsta", "");
+ emitBranch ("bpl", tlbl2);
+ emitcode ("inc", "1,s");
+ rmwWithReg ("neg", hc08_reg_a);
+ emitLabel (tlbl2);
+ }
+ }
+
+ loadRegFromConst (hc08_reg_h, zero);
emitcode ("div", "");
hc08_dirtyReg (hc08_reg_x, FALSE);
hc08_dirtyReg (hc08_reg_a, FALSE);
hc08_dirtyReg (hc08_reg_h, FALSE);
- tlbl4 = newiTempLabel (NULL);
- transferRegReg (hc08_reg_h, hc08_reg_a, TRUE);
- emitcode ("dec", "1,s");
- if (negLiteral)
- emitBranch ("bne", tlbl4);
+ if (runtimeSign || compiletimeSign)
+ {
+ transferRegReg (hc08_reg_h, hc08_reg_a, TRUE);
+ tlbl3 = newiTempLabel (NULL);
+ if (runtimeSign)
+ {
+ pullReg (hc08_reg_x);
+ rmwWithReg ("lsr", hc08_reg_x);
+ rmwWithReg ("ror", hc08_reg_x);
+ emitBranch ("bpl", tlbl3);
+ }
+
+ rmwWithReg ("neg", hc08_reg_a);
+ if (runtimeSign)
+ emitLabel (tlbl3);
+
+ storeRegToAop (hc08_reg_a, AOP (result), 0);
+
+ if (size > 1)
+ {
+ /* msb is 0x00 or 0xff depending on the sign */
+ if (runtimeSign)
+ {
+ rmwWithReg ("lsl", hc08_reg_x);
+ emitcode ("clra", "");
+ emitcode ("sbc", "#0");
+ while (--size)
+ storeRegToAop (hc08_reg_a, AOP (result), ++offset);
+ }
+ else /* compiletimeSign */
+ while (--size)
+ storeConstToAop ("#0xff", AOP (result), ++offset);
+ }
+ }
else
- emitBranch ("beq", tlbl4);
- rmwWithReg ("neg", hc08_reg_a);
-
- emitLabel (tlbl4);
- adjustStack (1);
- storeRegToFullAop (hc08_reg_a, AOP (result), TRUE);
+ {
+ storeRegToFullAop (hc08_reg_h, AOP (result), FALSE);
+ }
+
hc08_freeReg (hc08_reg_a);
hc08_freeReg (hc08_reg_x);
hc08_freeReg (hc08_reg_h);
-
}
/*-----------------------------------------------------------------*/
ic->generated = 1;
}
+
/*-----------------------------------------------------------------*/
-/* genCmp :- greater or less than comparison */
+/* exchangedCmp : returns the opcode need if the two operands are */
+/* exchanged in a comparison */
/*-----------------------------------------------------------------*/
-static void
-genCmp (operand * left, operand * right,
- operand * result, iCode * ifx, int sign, iCode *ic)
-{
- int size, offset = 0;
- unsigned long lit = 0L;
- char *sub;
- bool needpula = FALSE;
-
- D(emitcode ("; genCmp",""));
-
- /* subtract right from left if at the
- end the carry flag is set then we know that
- left is greater than right */
- size = max (AOP_SIZE (left), AOP_SIZE (right));
-
- if (AOP_TYPE (right) == AOP_LIT)
- {
- lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
- /* optimize if(x < 0) or if(x >= 0) */
- if (lit == 0L)
- {
- if (!sign)
- {
- CLRC;
- }
- else
- {
- needpula = pushRegIfUsed (hc08_reg_a);
- loadRegFromAop (hc08_reg_a, AOP (left), AOP_SIZE (left) -1);
- emitcode ("rola", "");
- hc08_useReg (hc08_reg_a);
- }
- sign = 0;
- goto release;
- }
+static int
+exchangedCmp (int opcode)
+{
+ switch (opcode)
+ {
+ case '<':
+ return '>';
+ case '>':
+ return '<';
+ case LE_OP:
+ return GE_OP;
+ case GE_OP:
+ return LE_OP;
+ case NE_OP:
+ return NE_OP;
+ case EQ_OP:
+ return EQ_OP;
+ default:
+ werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+ "opcode not a comparison");
}
+ return EQ_OP; /* shouldn't happen, but need to return something */
+}
- if ((size==2)
- && ((AOP_TYPE (right) == AOP_LIT) ||
- ((AOP_TYPE (right) == AOP_DIR) && (AOP_SIZE (right) == 2)) )
- && hc08_reg_hx->isFree)
- {
- loadRegFromAop (hc08_reg_hx, AOP (left), 0);
- emitcode ("cphx","%s", aopAdrStr (AOP (right), 1, TRUE));
- hc08_freeReg (hc08_reg_hx);
- goto release;
+/*------------------------------------------------------------------*/
+/* negatedCmp : returns the equivalent opcode for when a comparison */
+/* if not true */
+/*------------------------------------------------------------------*/
+static int
+negatedCmp (int opcode)
+{
+ switch (opcode)
+ {
+ case '<':
+ return GE_OP;
+ case '>':
+ return LE_OP;
+ case LE_OP:
+ return '>';
+ case GE_OP:
+ return '<';
+ case NE_OP:
+ return EQ_OP;
+ case EQ_OP:
+ return NE_OP;
+ default:
+ werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+ "opcode not a comparison");
}
+ return EQ_OP; /* shouldn't happen, but need to return something */
+}
- offset = 0;
- if (size==1)
- sub="cmp";
- else
- sub="sub";
- while (size--)
- {
- loadRegFromAop (hc08_reg_a, AOP (left), offset);
- accopWithAop (sub, AOP (right), offset);
- hc08_freeReg (hc08_reg_a);
- offset++;
- sub="sbc";
+/* compile only if the debugging macro D is enabled */
+#if (D(1) -0)
+static char *
+nameCmp (int opcode)
+{
+ switch (opcode)
+ {
+ case '<':
+ return "<";
+ case '>':
+ return ">";
+ case LE_OP:
+ return "<=";
+ case GE_OP:
+ return ">=";
+ case NE_OP:
+ return "!=";
+ case EQ_OP:
+ return "==";
+ default:
+ return "invalid";
}
+}
+#endif
-release:
- freeAsmop (right, NULL, ic, TRUE);
- freeAsmop (left, NULL, ic, TRUE);
- if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
- {
- outBitC (result);
- }
- else
+/*------------------------------------------------------------------*/
+/* branchInstCmp : returns the conditional branch instruction that */
+/* will branch if the comparison is true */
+/*------------------------------------------------------------------*/
+static char *
+branchInstCmp (int opcode, int sign)
+{
+ switch (opcode)
{
- /* if the result is used in the next
- ifx conditional branch then generate
- code a little differently */
- if (ifx)
- {
- pullOrFreeReg(hc08_reg_a,needpula);
- genIfxJump (ifx, sign ? "s" : "c");
- }
+ case '<':
+ if (sign)
+ return "blt";
+ else
+ return "bcs"; /* same as blo */
+ case '>':
+ if (sign)
+ return "bgt";
+ else
+ return "bhi";
+ case LE_OP:
+ if (sign)
+ return "ble";
+ else
+ return "bls";
+ case GE_OP:
+ if (sign)
+ return "bge";
else
- if (!sign)
- outBitC (result);
- else
- outBitNV (result);
- pullOrFreeReg(hc08_reg_a,needpula);
+ return "bcc"; /* same as bhs */
+ case NE_OP:
+ return "bne";
+ case EQ_OP:
+ return "beq";
+ default:
+ werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+ "opcode not a comparison");
}
+ return "brn";
}
-/*-----------------------------------------------------------------*/
-/* genCmpGt :- greater than comparison */
-/*-----------------------------------------------------------------*/
-static void
-genCmpGt (iCode * ic, iCode * ifx)
-{
- operand *left, *right, *result;
- sym_link *letype, *retype;
- int sign;
-
- D(emitcode ("; genCmpGt",""));
-
- result = IC_RESULT (ic);
- left = IC_LEFT (ic);
- right = IC_RIGHT (ic);
-
- letype = getSpec (operandType (left));
- retype = getSpec (operandType (right));
- sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
- /* assign the amsops */
- aopOp (left, ic, FALSE);
- aopOp (right, ic, FALSE);
- aopOp (result, ic, TRUE);
-
- genCmp (right, left, result, ifx, sign,ic);
-
- freeAsmop (result, NULL, ic, TRUE);
-}
-/*-----------------------------------------------------------------*/
-/* genCmpLt - less than comparisons */
-/*-----------------------------------------------------------------*/
+/*------------------------------------------------------------------*/
+/* genCmp :- greater or less than (and maybe with equal) comparison */
+/*------------------------------------------------------------------*/
static void
-genCmpLt (iCode * ic, iCode * ifx)
-{
+genCmp (iCode * ic, iCode * ifx)
+{
operand *left, *right, *result;
sym_link *letype, *retype;
- int sign;
+ int sign, opcode;
+ int size, offset = 0;
+ unsigned long lit = 0L;
+ char *sub;
+ symbol *jlbl = NULL;
- D(emitcode ("; genCmpLt",""));
+ opcode = ic->op;
+
+ D(emitcode ("; genCmp", "(%s)",nameCmp (opcode)));
result = IC_RESULT (ic);
left = IC_LEFT (ic);
letype = getSpec (operandType (left));
retype = getSpec (operandType (right));
sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
-
/* assign the amsops */
aopOp (left, ic, FALSE);
aopOp (right, ic, FALSE);
aopOp (result, ic, TRUE);
- genCmp (left, right, result, ifx, sign,ic);
-
- freeAsmop (result, NULL, ic, TRUE);
-}
-
-/*-----------------------------------------------------------------*/
-/* - compare and branch if not equal */
-/*-----------------------------------------------------------------*/
-static void
-gencbneshort (operand * left, operand * right, symbol * lbl)
-{
- int size = max (AOP_SIZE (left), AOP_SIZE (right));
- int offset = 0;
- unsigned long lit = 0L;
-
- /* if the left side is a literal or
- if the right is in a pointer register and left
- is not */
- if (AOP_TYPE (left) == AOP_LIT)
+ /* need register operand on left, prefer literal operand on right */
+ if ((AOP_TYPE (right) == AOP_REG) || AOP_TYPE (left) == AOP_LIT)
{
- operand *t = right;
- right = left;
- left = t;
+ operand *temp = left;
+ left = right;
+ right = temp;
+ opcode = exchangedCmp (opcode);
}
- if (AOP_TYPE (right) == AOP_LIT)
- lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
- while (size--)
+ if (ifx)
{
- loadRegFromAop (hc08_reg_a, AOP (left), offset);
- accopWithAop ("cmp", AOP (right), offset);
- hc08_useReg (hc08_reg_a);
- hc08_freeReg (hc08_reg_a);
- emitBranch ("bne", lbl);
- offset++;
+ if (IC_TRUE (ifx))
+ {
+ jlbl = IC_TRUE (ifx);
+ opcode = negatedCmp (opcode);
+ }
+ else
+ {
+ /* false label is present */
+ jlbl = IC_FALSE (ifx);
+ }
}
+
+ size = max (AOP_SIZE (left), AOP_SIZE (right));
+
+ if ((size == 2)
+ && ((AOP_TYPE (left) == AOP_DIR) && (AOP_SIZE (left) == 2))
+ && ((AOP_TYPE (right) == AOP_LIT) ||
+ ((AOP_TYPE (right) == AOP_DIR) && (AOP_SIZE (right) == 2)) )
+ && hc08_reg_hx->isFree)
+ {
+ loadRegFromAop (hc08_reg_hx, AOP (left), 0);
+ emitcode ("cphx","%s", aopAdrStr (AOP (right), 1, TRUE));
+ hc08_freeReg (hc08_reg_hx);
+ }
+ else
+ {
+ offset = 0;
+ if (size == 1)
+ sub = "cmp";
+ else
+ {
+ sub = "sub";
+
+ /* These conditions depend on the Z flag bit, but Z is */
+ /* only valid for the last byte of the comparison, not */
+ /* the whole value. So exchange the operands to get a */
+ /* comparison that doesn't depend on Z. (This is safe */
+ /* to do here since ralloc won't assign multi-byte */
+ /* operands to registers for comparisons) */
+ if ((opcode == '>') || (opcode == LE_OP))
+ {
+ operand *temp = left;
+ left = right;
+ right = temp;
+ opcode = exchangedCmp (opcode);
+ }
+
+ if ((AOP_TYPE (right) == AOP_LIT) && !isOperandVolatile (left, FALSE))
+ {
+ lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
+ while ((size > 1) && (((lit >> (8*offset)) & 0xff) == 0))
+ {
+ offset++;
+ size--;
+ }
+ }
+ }
+ while (size--)
+ {
+ loadRegFromAop (hc08_reg_a, AOP (left), offset);
+ accopWithAop (sub, AOP (right), offset);
+ hc08_freeReg (hc08_reg_a);
+ offset++;
+ sub = "sbc";
+ }
+ }
+ freeAsmop (right, NULL, ic, FALSE);
+ freeAsmop (left, NULL, ic, FALSE);
-}
-
-/*-----------------------------------------------------------------*/
-/* gencjne - compare and jump if not equal */
-/*-----------------------------------------------------------------*/
-static void
-gencjne (operand * left, operand * right, symbol * lbl)
-{
- symbol *tlbl = newiTempLabel (NULL);
-
- gencbneshort (left, right, lbl);
+ if (ifx)
+ {
+ symbol *tlbl = newiTempLabel (NULL);
+ char *inst;
- loadRegFromConst (hc08_reg_a, one);
- emitBranch ("bra", tlbl);
- emitLabel (lbl);
- loadRegFromConst (hc08_reg_a, zero);
- emitLabel (tlbl);
+ freeAsmop (result, NULL, ic, TRUE);
+
+ inst = branchInstCmp (opcode, sign);
+ emitBranch (inst, tlbl);
+ emitBranch ("jmp", jlbl);
+ emitLabel (tlbl);
- hc08_useReg(hc08_reg_a);
- hc08_freeReg(hc08_reg_a);
+ /* mark the icode as generated */
+ ifx->generated = 1;
+ }
+ else
+ {
+ symbol *tlbl1 = newiTempLabel (NULL);
+ symbol *tlbl2 = newiTempLabel (NULL);
+
+ emitBranch (branchInstCmp (opcode, sign), tlbl1);
+ loadRegFromConst (hc08_reg_a, zero);
+ emitBranch ("bra", tlbl2);
+ emitLabel (tlbl1);
+ loadRegFromConst (hc08_reg_a, one);
+ emitLabel (tlbl2);
+ storeRegToFullAop (hc08_reg_a, AOP(result), FALSE);
+ freeAsmop (result, NULL, ic, TRUE);
+ }
+
}
/*-----------------------------------------------------------------*/
-/* genCmpEq - generates code for equal to */
+/* genCmpEQorNE - equal or not equal comparison */
/*-----------------------------------------------------------------*/
static void
-genCmpEq (iCode * ic, iCode * ifx)
-{
+genCmpEQorNE (iCode * ic, iCode * ifx)
+{
operand *left, *right, *result;
+ sym_link *letype, *retype;
+ int sign, opcode;
+ int size, offset = 0;
+ char *sub;
+ symbol *jlbl = NULL;
+ symbol *tlbl_NE = NULL;
+ symbol *tlbl_EQ = NULL;
+
+ opcode = ic->op;
- D(emitcode ("; genCmpEq",""));
+ D(emitcode ("; genCmpEQorNE", "(%s)",nameCmp (opcode)));
- aopOp ((left = IC_LEFT (ic)), ic, FALSE);
- aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
- aopOp ((result = IC_RESULT (ic)), ic, TRUE);
+ result = IC_RESULT (ic);
+ left = IC_LEFT (ic);
+ right = IC_RIGHT (ic);
- /* if literal, literal on the right or
- if the right is in a pointer register and left
- is not */
- if (AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
+ letype = getSpec (operandType (left));
+ retype = getSpec (operandType (right));
+ sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
+ /* assign the amsops */
+ aopOp (left, ic, FALSE);
+ aopOp (right, ic, FALSE);
+ aopOp (result, ic, TRUE);
+
+ /* need register operand on left, prefer literal operand on right */
+ if ((AOP_TYPE (right) == AOP_REG) || AOP_TYPE (left) == AOP_LIT)
{
- operand *t = IC_RIGHT (ic);
- IC_RIGHT (ic) = IC_LEFT (ic);
- IC_LEFT (ic) = t;
+ operand *temp = left;
+ left = right;
+ right = temp;
+ opcode = exchangedCmp (opcode);
}
- if (ifx && !AOP_SIZE (result))
+ if (ifx)
{
- symbol *tlbl;
- tlbl = newiTempLabel (NULL);
- gencbneshort (left, right, tlbl);
if (IC_TRUE (ifx))
{
- emitBranch ("jmp", IC_TRUE (ifx));
- emitLabel (tlbl);
+ jlbl = IC_TRUE (ifx);
+ opcode = negatedCmp (opcode);
}
else
- {
- symbol *lbl = newiTempLabel (NULL);
- emitBranch ("bra", lbl);
- emitLabel (tlbl);
- emitBranch ("jmp", IC_FALSE (ifx));
- emitLabel (lbl);
- }
+ {
+ /* false label is present */
+ jlbl = IC_FALSE (ifx);
+ }
+ }
- /* mark the icode as generated */
- ifx->generated = 1;
- goto release;
+ size = max (AOP_SIZE (left), AOP_SIZE (right));
+
+ if ((size == 2)
+ && ((AOP_TYPE (left) == AOP_DIR) && (AOP_SIZE (left) == 2))
+ && ((AOP_TYPE (right) == AOP_LIT) ||
+ ((AOP_TYPE (right) == AOP_DIR) && (AOP_SIZE (right) == 2)) )
+ && hc08_reg_hx->isFree)
+ {
+ loadRegFromAop (hc08_reg_hx, AOP (left), 0);
+ emitcode ("cphx","%s", aopAdrStr (AOP (right), 1, TRUE));
+ hc08_freeReg (hc08_reg_hx);
}
-
- gencjne (left, right, newiTempLabel (NULL));
- if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
+ else
{
- storeRegToAop (hc08_reg_a, AOP (result), 0);
- goto release;
+ offset = 0;
+ sub = "cmp";
+ while (size--)
+ {
+ loadRegFromAop (hc08_reg_a, AOP (left), offset);
+ accopWithAop (sub, AOP (right), offset);
+ if (size)
+ {
+ if (!tlbl_NE)
+ tlbl_NE = newiTempLabel (NULL);
+ emitBranch ("bne", tlbl_NE);
+ }
+ hc08_freeReg (hc08_reg_a);
+ offset++;
+ }
}
+ freeAsmop (right, NULL, ic, FALSE);
+ freeAsmop (left, NULL, ic, FALSE);
+
if (ifx)
{
- genIfxJump (ifx, "a");
- goto release;
- }
- /* if the result is used in an arithmetic operation
- then put the result in place */
- if (AOP_TYPE (result) != AOP_CRY)
- outAcc (result);
+ freeAsmop (result, NULL, ic, TRUE);
+
+ if (opcode == EQ_OP)
+ {
+ if (!tlbl_EQ)
+ tlbl_EQ = newiTempLabel (NULL);
+ emitBranch ("beq", tlbl_EQ);
+ if (tlbl_NE)
+ emitLabel (tlbl_NE);
+ emitBranch ("jmp", jlbl);
+ emitLabel (tlbl_EQ);
+ }
+ else
+ {
+ if (!tlbl_NE)
+ tlbl_NE = newiTempLabel (NULL);
+ emitBranch ("bne", tlbl_NE);
+ emitBranch ("jmp", jlbl);
+ emitLabel (tlbl_NE);
+ }
-release:
- freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
- freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
- freeAsmop (result, NULL, ic, TRUE);
+ /* mark the icode as generated */
+ ifx->generated = 1;
+ }
+ else
+ {
+ symbol *tlbl = newiTempLabel (NULL);
+
+ if (opcode == EQ_OP)
+ {
+ if (!tlbl_EQ)
+ tlbl_EQ = newiTempLabel (NULL);
+ emitBranch ("beq", tlbl_EQ);
+ if (tlbl_NE)
+ emitLabel (tlbl_NE);
+ loadRegFromConst (hc08_reg_a, zero);
+ emitBranch ("bra", tlbl);
+ emitLabel (tlbl_EQ);
+ loadRegFromConst (hc08_reg_a, one);
+ }
+ else
+ {
+ if (!tlbl_NE)
+ tlbl_NE = newiTempLabel (NULL);
+ emitBranch ("bne", tlbl_NE);
+ loadRegFromConst (hc08_reg_a, zero);
+ emitBranch ("bra", tlbl);
+ emitLabel (tlbl_NE);
+ loadRegFromConst (hc08_reg_a, one);
+ }
+
+ emitLabel (tlbl);
+ storeRegToFullAop (hc08_reg_a, AOP(result), FALSE);
+ freeAsmop (result, NULL, ic, TRUE);
+ }
+
}
+
/*-----------------------------------------------------------------*/
/* ifxForOp - returns the icode containing the ifx for operand */
/*-----------------------------------------------------------------*/
{
iCode *lic = ic->next;
bool pset, pget;
- int offset, size;
+ int size;
symbol *sym;
asmop *derefaop;
/* Make sure we have a next iCode */
- emitcode("","; checking lic");
+ D(emitcode("","; checking lic"));
if (!lic)
return FALSE;
/* Make sure the result of the addition is an iCode */
- emitcode("","; checking IS_ITEMP");
+ D(emitcode("","; checking IS_ITEMP"));
if (!IS_ITEMP (IC_RESULT (ic)))
return FALSE;
/* Make sure the next iCode is a pointer set or get */
pset = POINTER_SET(lic);
pget = POINTER_GET(lic);
- emitcode("","; pset=%d, pget=%d",pset,pget);
+ D(emitcode("","; pset=%d, pget=%d",pset,pget));
if (!pset && !pget)
return FALSE;
- emitcode("", "; checking pset operandsEqu");
+ /* Make sure this is the only use of the pointer */
+ if (bitVectnBitsOn (OP_USES (IC_RESULT (ic))) > 1)
+ return FALSE;
+
+ D(emitcode("", "; checking pset operandsEqu"));
if (pset & !operandsEqu (IC_RESULT (ic), IC_RESULT (lic)))
return FALSE;
- emitcode("", "; checking pget operandsEqu");
+ D(emitcode("", "; checking pget operandsEqu"));
if (pget & !operandsEqu (IC_RESULT (ic), IC_LEFT (lic)))
return FALSE;
- emitcode("", "; checking IS_SYMOP");
+ D(emitcode("", "; checking IS_SYMOP"));
if (!IS_SYMOP (IC_LEFT (ic)))
return FALSE;
- emitcode("", "; checking !IS_TRUE_SYMOP");
+ D(emitcode("", "; checking !IS_TRUE_SYMOP"));
if (IS_TRUE_SYMOP (IC_LEFT (ic)))
return FALSE;
sym = OP_SYMBOL (IC_LEFT (ic));
- emitcode("", "; checking remat");
+ D(emitcode("", "; checking remat"));
if (!sym->remat)
return FALSE;
+
if (pget)
{
D(emitcode ("; genPointerGetOfs",""));
aopOp (IC_RIGHT(ic), ic, FALSE);
aopOp (IC_RESULT(lic), lic, FALSE);
-
- loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
+ if (AOP_SIZE (IC_RIGHT (ic)) == 1)
+ {
+ if (SPEC_USIGN (getSpec (operandType (IC_RIGHT (ic)))))
+ {
+ loadRegFromAop (hc08_reg_x, AOP (IC_RIGHT (ic)), 0);
+ loadRegFromConst (hc08_reg_h, zero);
+ }
+ else
+ {
+ loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
+ transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
+ emitcode ("rola","");
+ emitcode ("clra","");
+ emitcode ("sbc", "#0");
+ hc08_useReg (hc08_reg_a);
+ transferRegReg (hc08_reg_a, hc08_reg_h, FALSE);
+ }
+ }
+ else
+ loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
size = AOP_SIZE (IC_RESULT(lic));
derefaop->size = size;
- offset=0;
while (size--)
{
emitcode ("lda", "%s,x",
- aopAdrStr (derefaop, offset, TRUE));
+ aopAdrStr (derefaop, size, TRUE));
hc08_useReg (hc08_reg_a);
- storeRegToAop (hc08_reg_a, AOP (IC_RESULT (lic)), offset++);
+ storeRegToAop (hc08_reg_a, AOP (IC_RESULT (lic)), size);
hc08_freeReg (hc08_reg_a);
}
aopOp (IC_RIGHT(ic), ic, FALSE);
aopOp (IC_RIGHT(lic), lic, FALSE);
-
- loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
+ if (AOP_SIZE (IC_RIGHT (ic)) == 1)
+ {
+ if (SPEC_USIGN (getSpec (operandType (IC_RIGHT (ic)))))
+ {
+ loadRegFromAop (hc08_reg_x, AOP (IC_RIGHT (ic)), 0);
+ loadRegFromConst (hc08_reg_h, zero);
+ }
+ else
+ {
+ loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
+ transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
+ emitcode ("rola","");
+ emitcode ("clra","");
+ emitcode ("sbc", "#0");
+ hc08_useReg (hc08_reg_a);
+ transferRegReg (hc08_reg_a, hc08_reg_h, FALSE);
+ }
+ }
+ else
+ loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
size = AOP_SIZE (IC_RIGHT(lic));
derefaop->size = size;
- offset=0;
while (size--)
{
- loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (lic)), offset);
+ loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (lic)), size);
emitcode ("sta", "%s,x",
- aopAdrStr (derefaop, offset, TRUE));
+ aopAdrStr (derefaop, size, TRUE));
hc08_freeReg (hc08_reg_a);
- offset++;
}
lic->generated = 1;
return lic;
}
/* if the operand used or deffed */
- if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
+ if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
return NULL;
}
/* if GOTO or IFX */
int size, offset = 0;
unsigned long lit = 0L;
unsigned long litinv;
+ unsigned char bytemask;
// int bytelit = 0;
aopOp ((result = IC_RESULT (ic)), ic, TRUE);
#ifdef DEBUG_TYPE
- emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
+ D(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
AOP_TYPE (result),
- AOP_TYPE (left), AOP_TYPE (right));
- emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
+ AOP_TYPE (left), AOP_TYPE (right)));
+ D(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
AOP_SIZE (result),
- AOP_SIZE (left), AOP_SIZE (right));
+ AOP_SIZE (left), AOP_SIZE (right)));
#endif
/* if left is a literal & right is not then exchange them */
left = tmp;
}
- /* if left is accumulator & right is not then exchange them */
+ /* if right is accumulator & left is not then exchange them */
if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
{
operand *tmp = right;
left = tmp;
}
+ if (AOP_TYPE (right) == AOP_LIT)
+ lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
+
+ size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
+
+ if (AOP_TYPE (result) == AOP_CRY
+ && size > 1
+ && (isOperandVolatile (left, FALSE) || isOperandVolatile (right, FALSE)))
+ {
+ /* this generates ugly code, but meets volatility requirements */
+ loadRegFromConst (hc08_reg_a, zero);
+ pushReg (hc08_reg_a, TRUE);
+
+ offset = 0;
+ while (size--)
+ {
+ loadRegFromAop (hc08_reg_a, AOP (left), offset);
+ accopWithAop ("and", AOP (right), offset);
+ emitcode ("ora", "1,s");
+ emitcode ("sta", "1,s");
+ offset++;
+ }
+
+ pullReg (hc08_reg_a);
+ emitcode ("tsta", "");
+ genIfxJump (ifx, "a");
+ goto release;
+ }
+
+ if (AOP_TYPE (result) == AOP_CRY)
+ {
+ symbol *tlbl = NULL;
+ wassertl (ifx, "AOP_CRY result without ifx");
+
+ offset = 0;
+ while (size--)
+ {
+ bytemask = (lit >> (offset*8)) & 0xff;
+
+ if (AOP_TYPE (right) == AOP_LIT && bytemask == 0)
+ {
+ /* do nothing */
+ }
+ else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff)
+ {
+ rmwWithAop ("tst", AOP (left), offset);
+ if (size)
+ {
+ if (!tlbl)
+ tlbl = newiTempLabel (NULL);
+ emitBranch ("bne", tlbl);
+ }
+ }
+ else
+ {
+ loadRegFromAop (hc08_reg_a, AOP (left), offset);
+ accopWithAop ("and", AOP (right), offset);
+ hc08_freeReg( hc08_reg_a);
+ if (size)
+ {
+ if (!tlbl)
+ tlbl = newiTempLabel (NULL);
+ emitBranch ("bne", tlbl);
+ }
+ }
+ offset++;
+ }
+ if (tlbl)
+ emitLabel (tlbl);
+ genIfxJump (ifx, "a");
+ goto release;
+ }
+
size = AOP_SIZE (result);
if (AOP_TYPE (right) == AOP_LIT)
{
- lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
litinv = (~lit) & (((unsigned int)0xffffffff) >> (8*(4-size))) ;
-
if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
(AOP_TYPE (left) == AOP_DIR) && isLiteralBit(litinv))
{
goto release;
}
}
-
+
offset = 0;
while (size--)
{
- loadRegFromAop (hc08_reg_a, AOP (left), offset);
- if ((AOP_TYPE (right) != AOP_LIT)
- || (((lit >> (offset*8)) & 0xff) != 0xff))
- accopWithAop ("and", AOP (right), offset);
- storeRegToAop (hc08_reg_a, AOP (result), offset++);
- hc08_freeReg( hc08_reg_a);
- }
-
-release:
+ bytemask = (lit >> (offset*8)) & 0xff;
+
+ if (AOP_TYPE (right) == AOP_LIT && bytemask == 0)
+ {
+ if (isOperandVolatile (left, FALSE))
+ {
+ loadRegFromAop (hc08_reg_a, AOP (left), offset);
+ hc08_freeReg( hc08_reg_a);
+ }
+ storeConstToAop (zero, AOP (result), offset);
+ }
+ else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff)
+ {
+ transferAopAop (AOP (left), offset, AOP (result), offset);
+ }
+ else
+ {
+ loadRegFromAop (hc08_reg_a, AOP (left), offset);
+ accopWithAop ("and", AOP (right), offset);
+ storeRegToAop (hc08_reg_a, AOP (result), offset);
+ hc08_freeReg (hc08_reg_a);
+ }
+ offset++;
+ }
+
+release:
freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
freeAsmop (result, NULL, ic, TRUE);
operand *left, *right, *result;
int size, offset = 0;
unsigned long lit = 0L;
+ unsigned char bytemask;
D(emitcode ("; genOr",""));
aopOp ((result = IC_RESULT (ic)), ic, TRUE);
#ifdef DEBUG_TYPE
- emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
+ D(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
AOP_TYPE (result),
- AOP_TYPE (left), AOP_TYPE (right));
- emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
+ AOP_TYPE (left), AOP_TYPE (right)));
+ D(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
AOP_SIZE (result),
- AOP_SIZE (left), AOP_SIZE (right));
+ AOP_SIZE (left), AOP_SIZE (right)));
#endif
/* if left is a literal & right is not then exchange them */
left = tmp;
}
- /* if right is bit then exchange them */
- if (AOP_TYPE (right) == AOP_CRY &&
- AOP_TYPE (left) != AOP_CRY)
+ if (AOP_TYPE (right) == AOP_LIT)
+ lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
+
+ size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
+
+ if (AOP_TYPE (result) == AOP_CRY
+ && size > 1
+ && (isOperandVolatile (left, FALSE) || isOperandVolatile (right, FALSE)))
{
- operand *tmp = right;
- right = left;
- left = tmp;
+ /* this generates ugly code, but meets volatility requirements */
+ loadRegFromConst (hc08_reg_a, zero);
+ pushReg (hc08_reg_a, TRUE);
+
+ offset = 0;
+ while (size--)
+ {
+ loadRegFromAop (hc08_reg_a, AOP (left), offset);
+ accopWithAop ("ora", AOP (right), offset);
+ emitcode ("ora", "1,s");
+ emitcode ("sta", "1,s");
+ offset++;
+ }
+
+ pullReg (hc08_reg_a);
+ emitcode ("tsta", "");
+ genIfxJump (ifx, "a");
+ goto release;
+ }
+
+ if (AOP_TYPE (result) == AOP_CRY)
+ {
+ symbol *tlbl = NULL;
+ wassertl (ifx, "AOP_CRY result without ifx");
+
+ offset = 0;
+ while (size--)
+ {
+ bytemask = (lit >> (offset*8)) & 0xff;
+
+ if (AOP_TYPE (right) == AOP_LIT && bytemask == 0x00)
+ {
+ rmwWithAop ("tst", AOP (left), offset);
+ if (size)
+ {
+ if (!tlbl)
+ tlbl = newiTempLabel (NULL);
+ emitBranch ("bne", tlbl);
+ }
+ }
+ else
+ {
+ loadRegFromAop (hc08_reg_a, AOP (left), offset);
+ accopWithAop ("ora", AOP (right), offset);
+ hc08_freeReg( hc08_reg_a);
+ if (size)
+ {
+ if (!tlbl)
+ tlbl = newiTempLabel (NULL);
+ emitBranch ("bne", tlbl);
+ }
+ }
+ offset++;
+ }
+ if (tlbl)
+ emitLabel (tlbl);
+ genIfxJump (ifx, "a");
}
+
if (AOP_TYPE (right) == AOP_LIT)
lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
goto release;
}
-
-
offset = 0;
while (size--)
{
- loadRegFromAop (hc08_reg_a, AOP (left), offset);
- accopWithAop ("ora", AOP (right), offset);
- storeRegToAop (hc08_reg_a, AOP (result), offset++);
- hc08_freeReg( hc08_reg_a);
+ bytemask = (lit >> (offset*8)) & 0xff;
+
+ if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff)
+ {
+ if (isOperandVolatile (left, FALSE))
+ {
+ loadRegFromAop (hc08_reg_a, AOP (left), offset);
+ hc08_freeReg( hc08_reg_a);
+ }
+ transferAopAop (AOP (right), offset, AOP (result), offset);
+ }
+ else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0)
+ {
+ transferAopAop (AOP (left), offset, AOP (result), offset);
+ }
+ else
+ {
+ loadRegFromAop (hc08_reg_a, AOP (left), offset);
+ accopWithAop ("ora", AOP (right), offset);
+ storeRegToAop (hc08_reg_a, AOP (result), offset);
+ hc08_freeReg (hc08_reg_a);
+ }
+ offset++;
}
aopOp ((result = IC_RESULT (ic)), ic, TRUE);
#ifdef DEBUG_TYPE
- emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
+ D(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
AOP_TYPE (result),
- AOP_TYPE (left), AOP_TYPE (right));
- emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
+ AOP_TYPE (left), AOP_TYPE (right)));
+ D(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
AOP_SIZE (result),
- AOP_SIZE (left), AOP_SIZE (right));
+ AOP_SIZE (left), AOP_SIZE (right)));
#endif
/* if left is a literal & right is not ||
left = tmp;
}
- /* if right is bit then exchange them */
- if (AOP_TYPE (right) == AOP_CRY &&
- AOP_TYPE (left) != AOP_CRY)
+ if (AOP_TYPE (result) == AOP_CRY)
{
- operand *tmp = right;
- right = left;
- left = tmp;
+ symbol *tlbl;
+ wassertl (ifx, "AOP_CPY result without ifx");
+
+ tlbl = newiTempLabel (NULL);
+ size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
+ offset = 0;
+ while (size--)
+ {
+ loadRegFromAop (hc08_reg_a, AOP (left), offset);
+ if ((AOP_TYPE (right) == AOP_LIT)
+ && (((lit >> (offset*8)) & 0xff) == 0))
+ emitcode ("tsta","");
+ else
+ accopWithAop ("eor", AOP (right), offset);
+ hc08_freeReg( hc08_reg_a);
+ if (size)
+ emitBranch ("bne", tlbl);
+ else
+ {
+ emitLabel (tlbl);
+ genIfxJump (ifx, "a");
+ }
+ offset++;
+ }
}
+
if (AOP_TYPE (right) == AOP_LIT)
lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
hc08_freeReg( hc08_reg_a);
}
-
//release:
freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
if (*l=='#')
l++;
sym->isref = 1;
- if (!sym->allocreq && !sym->ismyparm)
+ if (sym->level && !sym->allocreq && !sym->ismyparm)
{
werror (E_ID_UNDEF, sym->name);
werror (W_CONTINUE,
emitcode ("rola", "");
hc08_dirtyReg (hc08_reg_a, FALSE);
storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
+ hc08_freeReg (hc08_reg_a);
freeAsmop (left, NULL, ic, TRUE);
freeAsmop (result, NULL, ic, TRUE);
}
+/*-----------------------------------------------------------------*/
+/* genSwap - generates code to swap nibbles or bytes */
+/*-----------------------------------------------------------------*/
+static void
+genSwap (iCode * ic)
+{
+ operand *left, *result;
+
+ D(emitcode ("; genSwap",""));
+
+ left = IC_LEFT (ic);
+ result = IC_RESULT (ic);
+ aopOp (left, ic, FALSE);
+ aopOp (result, ic, FALSE);
+
+ switch (AOP_SIZE (left))
+ {
+ case 1: /* swap nibbles in byte */
+ loadRegFromAop (hc08_reg_a, AOP (left), 0);
+ emitcode ("nsa", "");
+ hc08_dirtyReg (hc08_reg_a, FALSE);
+ storeRegToAop (hc08_reg_a, AOP (result), 0);
+ hc08_freeReg (hc08_reg_a);
+ break;
+ case 2: /* swap bytes in a word */
+ if (operandsEqu (left, result))
+ {
+ loadRegFromAop (hc08_reg_a, AOP (left), 0);
+ hc08_useReg (hc08_reg_a);
+ transferAopAop (AOP (left), 1, AOP (result), 0);
+ storeRegToAop (hc08_reg_a, AOP (result), 1);
+ hc08_freeReg (hc08_reg_a);
+ }
+ else
+ {
+ transferAopAop (AOP (left), 0, AOP (result), 1);
+ transferAopAop (AOP (left), 1, AOP (result), 0);
+ }
+ break;
+ default:
+ wassertl(FALSE, "unsupported SWAP operand size");
+ }
+
+ freeAsmop (left, NULL, ic, TRUE);
+ freeAsmop (result, NULL, ic, TRUE);
+}
+
#if 0
/*-----------------------------------------------------------------*/
/* AccRol - rotate left accumulator by known count */
switch (shCount)
{
case 4:
+ if (optimize.codeSpeed)
+ break;
accopWithMisc ("nsa", "");
accopWithMisc ("and", "#0xf0");
/* total: 5 cycles, 3 bytes */
return;
case 5:
+ if (optimize.codeSpeed)
+ break;
accopWithMisc ("nsa", "");
accopWithMisc ("and", "#0xf0");
accopWithMisc ("lsla", "");
switch (shCount)
{
case 4:
+ if (optimize.codeSpeed)
+ break;
accopWithMisc ("nsa", "");
accopWithMisc ("and", "#0x0f");
/* total: 5 cycles, 3 bytes */
return;
case 5:
+ if (optimize.codeSpeed)
+ break;
accopWithMisc ("nsa", "");
accopWithMisc ("and", "#0x0f");
accopWithMisc ("lsra", "");
;
}
- /* asrx/rola is only 2 cycles and bytes, so an unrolled loop is often */
+ /* asrx/rora is only 2 cycles and bytes, so an unrolled loop is often */
/* the fastest and shortest. */
for (i=0;i<shCount;i++)
{
return;
}
- shCount &= 0x000f; // shCount : 0..7
+ shCount &= 0x000f; // shCount : 0..f
/* if we can beat 2n cycles or bytes for some special case, do it here */
switch (shCount)
** rola 1 1 bcde fgh0 0000 000a 0
** lslx 1 1 cdef gh00 0000 000a b
** rola 1 1 cdef gh00 0000 00ab 0
- ** clrx 1 1 0000 0000 0000 000a 0
+ ** clrx 1 1 0000 0000 0000 00ab 0
** total: 6 cycles, 6 bytes
*/
loadRegFromConst (hc08_reg_x, zero);
;
}
- /* lslx/rola is only 2 cycles and bytes, so an unrolled loop is often */
+ /* lsrx/rora is only 2 cycles and bytes, so an unrolled loop is often */
/* the fastest and shortest. */
for (i=0;i<shCount;i++)
{
- rmwWithReg ("lsl", hc08_reg_x);
- rmwWithReg ("rol", hc08_reg_a);
+ rmwWithReg ("lsr", hc08_reg_x);
+ rmwWithReg ("ror", hc08_reg_a);
}
}
}
-/*-----------------------------------------------------------------*/
-/* AccAXRsh1 - right shift 0->a:x->c by 1 */
-/*-----------------------------------------------------------------*/
-static void
-AccAXRsh1 (char *x)
-{
- emitcode ("lsra", "");
- emitcode ("ror", "%s", x);
-}
-
-
-/*-----------------------------------------------------------------*/
-/* AccAXRshS1 - signed right shift s->a:x->c by 1 */
-/*-----------------------------------------------------------------*/
-static void
-AccAXRshS1 (char *x)
-{
- emitcode ("asra", "");
- emitcode ("ror", "%s", x);
-}
-
-/*-----------------------------------------------------------------*/
-/* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
-/*-----------------------------------------------------------------*/
-static void
-AccAXLrl1 (char *x)
-{
- emitcode ("rol", "%s", x);
- emitcode ("rola", "");
-}
-
-/*-----------------------------------------------------------------*/
-/* AccAXLsh1 - left shift a:x<-0 by 1 */
-/*-----------------------------------------------------------------*/
-static void
-AccAXLsh1 (char *x)
-{
- emitcode ("lsl", "%s", x);
- emitcode ("rola", "");
-}
-
-/*-----------------------------------------------------------------*/
-/* AccAXLsh - left shift a:x by known count (0..7) */
-/*-----------------------------------------------------------------*/
-static void
-AccAXLsh (char *x, int shCount)
-{
- int i;
-
- for (i=0;i<shCount;i++) {
- AccAXLsh1 (x);
- }
-}
-
-/*-----------------------------------------------------------------*/
-/* AccAXRsh - right shift a:x known count (0..7) */
-/*-----------------------------------------------------------------*/
-static void
-AccAXRsh (char *x, int shCount)
-{
- int i;
-
- for (i=0;i<shCount;i++) {
- AccAXRsh1 (x);
- }
-
-}
-
-/*-----------------------------------------------------------------*/
-/* AccAXRshS - right shift signed a:x known count (0..7) */
-/*-----------------------------------------------------------------*/
-static void
-AccAXRshS (char *x, int shCount)
-{
- int i;
-
- for (i=0;i<shCount;i++) {
- AccAXRshS1 (x);
- }
-}
-
/*-----------------------------------------------------------------*/
/* shiftL2Left2Result - shift left two bytes from left to result */
/*-----------------------------------------------------------------*/
bool needpula = FALSE;
bool needpulx = FALSE;
- needpula = pushRegIfUsed (hc08_reg_a);
- needpulx = pushRegIfUsed (hc08_reg_x);
+ if (!IS_AOP_XA (AOP (left)) && !IS_AOP_A (AOP (left)))
+ needpula = pushRegIfUsed (hc08_reg_a);
+ else
+ needpula = FALSE;
+ if (!IS_AOP_XA (AOP (left)))
+ needpulx = pushRegIfUsed (hc08_reg_x);
+ else
+ needpulx = FALSE;
loadRegFromAop (hc08_reg_xa, AOP (left), offl);
rmwWithReg ("rol", hc08_reg_x);
}
}
- storeRegToAop (hc08_reg_xa, AOP (result), offl);
+ storeRegToAop (hc08_reg_xa, AOP (result), offr);
pullOrFreeReg (hc08_reg_x, needpulx);
pullOrFreeReg (hc08_reg_a, needpula);
D(emitcode ("; genlshTwo",""));
+
size = getDataSize (result);
/* if shCount >= 8 */
if (size > 1)
{
- if (shCount)
- shiftL1Left2Result (left, LSB, result, MSB16, shCount);
- else
- movLeft2Result (left, LSB, result, MSB16, 0);
+ loadRegFromAop (hc08_reg_a, AOP (left), 0);
+ AccLsh (shCount);
+ storeRegToAop (hc08_reg_a, AOP (result), 1);
}
storeConstToAop(zero, AOP (result), LSB);
}
/* 1 <= shCount <= 7 */
else
{
- if (size == 1)
- shiftL1Left2Result (left, LSB, result, LSB, shCount);
- else
- shiftL2Left2Result (left, LSB, result, LSB, shCount);
+ loadRegFromAop (hc08_reg_xa, AOP (left), 0);
+ XAccLsh (shCount);
+ storeRegToFullAop (hc08_reg_xa, AOP (result), 0);
}
}
loadRegFromAop (hc08_reg_a, AOP (left), MSB24);
rmwWithReg ("rol", hc08_reg_a);
storeRegToAop (hc08_reg_a, AOP (result), offr+2);
+ storeConstToAop (zero, AOP (result), 0);
}
pullOrFreeReg (hc08_reg_x, needpulx);
size = AOP_SIZE (result);
#if VIEW_SIZE
- emitcode ("; shift left ", "result %d, left %d", size,
- AOP_SIZE (left));
+ D(emitcode ("; shift left ", "result %d, left %d", size,
+ AOP_SIZE (left)));
#endif
if (shCount == 0)
rmwWithReg ("asr", hc08_reg_x);
else
rmwWithReg ("lsr", hc08_reg_x);
- rmwWithReg ("rol", hc08_reg_a);
+ rmwWithReg ("ror", hc08_reg_a);
storeRegToAop (hc08_reg_xa, AOP (result), MSB24);
}
else if (offl==MSB16)
else
rmwWithReg ("lsr", hc08_reg_a);
storeRegToAop (hc08_reg_a, AOP (result), MSB24);
+ storeRegSignToUpperAop (hc08_reg_a, AOP (result), MSB32, sign);
}
loadRegFromAop (hc08_reg_xa, AOP (left), offl);
loadRegFromConst (hc08_reg_a, zero);
XAccRsh (shCount-8, sign);
accopWithAop ("ora", AOP (result), 1);
- storeRegToFullAop (hc08_reg_xa, AOP (result), 1);
+ storeRegToAop (hc08_reg_xa, AOP (result), 1);
+ storeRegSignToUpperAop (hc08_reg_x, AOP(result), 3, sign);
}
}
else
loadRegFromAop (hc08_reg_a, AOP (left), 2);
AccLsh (8-shCount);
accopWithAop ("ora", AOP (result), 1);
- storeRegToFullAop (hc08_reg_xa, AOP (result), 1);
+ storeRegToAop (hc08_reg_a, AOP (result), 1);
loadRegFromAop (hc08_reg_xa, AOP (left), 2);
XAccRsh (shCount, sign);
storeRegToAop (hc08_reg_xa, AOP (result), 2);
aopOp (result, ic, FALSE);
#if VIEW_SIZE
- emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
- AOP_SIZE (left));
+ D(emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
+ AOP_SIZE (left)));
#endif
size = getDataSize (left);
freeAsmop (right, NULL, ic, TRUE);
}
+
/*-----------------------------------------------------------------*/
/* genUnpackBits - generates code for unpacking bits */
/*-----------------------------------------------------------------*/
static void
-genUnpackBits (operand * result)
+genUnpackBits (operand * result, iCode *ifx)
{
int offset = 0; /* result byte offset */
int rsize; /* result size */
{
emitcode ("lda", ",x");
hc08_dirtyReg (hc08_reg_a, FALSE);
- AccRsh (bstr, FALSE);
- emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
- storeRegToAop (hc08_reg_a, AOP (result), offset++);
+ if (!ifx)
+ {
+ AccRsh (bstr, FALSE);
+ emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
+ storeRegToAop (hc08_reg_a, AOP (result), offset++);
+ }
+ else
+ {
+ emitcode ("and", "#0x%02x",
+ (((unsigned char) -1) >> (8 - blen)) << bstr);
+ }
goto finish;
}
{
emitcode ("lda", ",x");
hc08_dirtyReg (hc08_reg_a, FALSE);
- storeRegToAop (hc08_reg_a, AOP (result), offset++);
+ if (!ifx)
+ storeRegToAop (hc08_reg_a, AOP (result), offset);
+ offset++;
if (rlen>8)
emitcode ("aix", "#1");
}
while (rsize--)
storeConstToAop (zero, AOP (result), offset++);
}
+
+ if (ifx && !ifx->generated)
+ {
+ genIfxJump (ifx, "a");
+ }
}
/*-----------------------------------------------------------------*/
-/* genDataPointerGet - generates code when ptr offset is known */
+/* genUnpackBitsImmed - generates code for unpacking bits */
/*-----------------------------------------------------------------*/
static void
-genDataPointerGet (operand * left,
- operand * result,
- iCode * ic)
+genUnpackBitsImmed (operand * left,
+ operand * result,
+ iCode *ic,
+ iCode *ifx)
{
- int size, offset = 0;
+ int size;
+ int offset = 0; /* result byte offset */
+ int rsize; /* result size */
+ int rlen = 0; /* remaining bitfield length */
+ sym_link *etype; /* bitfield type information */
+ int blen; /* bitfield length */
+ int bstr; /* bitfield starting bit within byte */
asmop *derefaop;
- D(emitcode ("; genDataPointerGet",""));
+ D(emitcode ("; genUnpackBitsImmed",""));
aopOp (result, ic, TRUE);
size = AOP_SIZE (result);
freeAsmop (left, NULL, ic, TRUE);
derefaop->size = size;
- while (size--)
- {
- transferAopAop(derefaop, offset, AOP (result), offset);
- offset++;
- }
-
- freeAsmop (NULL, derefaop, ic, TRUE);
- freeAsmop (result, NULL, ic, TRUE);
-}
+ etype = getSpec (operandType (result));
+ rsize = getSize (operandType (result));
+ blen = SPEC_BLEN (etype);
+ bstr = SPEC_BSTR (etype);
-/*-----------------------------------------------------------------*/
-/* genNearPointerGet - emitcode for near pointer fetch */
-/*-----------------------------------------------------------------*/
-static void
-genNearPointerGet (operand * left,
- operand * result,
- iCode * ic,
- iCode * pi)
-{
- int size, offset;
- sym_link *retype = getSpec (operandType (result));
+ /* if the bitfield is a single bit in the direct page */
+ if (blen == 1 && derefaop->type == AOP_DIR)
+ {
+ if (!ifx && bstr)
+ {
+ symbol *tlbl = newiTempLabel (NULL);
+
+ loadRegFromConst (hc08_reg_a, zero);
+ emitcode ("brclr", "#%d,%s,%05d$",
+ bstr, aopAdrStr (derefaop, 0, FALSE),
+ (tlbl->key + 100));
+ rmwWithReg ("inc", hc08_reg_a);
+ emitLabel (tlbl);
+ storeRegToAop (hc08_reg_a, AOP (result), offset);
+ hc08_freeReg (hc08_reg_a);
+ offset++;
+ goto finish;
+ }
+ else if (ifx)
+ {
+ symbol *tlbl = newiTempLabel (NULL);
+ symbol *jlbl;
+ char * inst;
+
+ if (IC_TRUE (ifx))
+ {
+ jlbl = IC_TRUE (ifx);
+ inst = "brclr";
+ }
+ else
+ {
+ jlbl = IC_FALSE (ifx);
+ inst = "brset";
+ }
+ emitcode (inst, "#%d,%s,%05d$",
+ bstr, aopAdrStr (derefaop, 0, FALSE),
+ (tlbl->key + 100));
+ emitBranch ("jmp", jlbl);
+ emitLabel (tlbl);
+ ifx->generated = 1;
+ offset++;
+ goto finish;
+ }
+ }
- D(emitcode ("; genNearPointerGet",""));
+ /* If the bitfield length is less than a byte */
+ if (blen < 8)
+ {
+ loadRegFromAop (hc08_reg_a, derefaop, 0);
+ if (!ifx)
+ {
+ AccRsh (bstr, FALSE);
+ emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
+ hc08_dirtyReg (hc08_reg_a, FALSE);
+ storeRegToAop (hc08_reg_a, AOP (result), offset);
+ }
+ else
+ {
+ emitcode ("and", "#0x%02x",
+ (((unsigned char) -1) >> (8 - blen)) << bstr);
+ hc08_dirtyReg (hc08_reg_a, FALSE);
+ }
+ offset++;
+ goto finish;
+ }
- aopOp (left, ic, FALSE);
+ /* Bit field did not fit in a byte. Copy all
+ but the partial byte at the end. */
+ for (rlen=blen;rlen>=8;rlen-=8)
+ {
+ loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
+ if (!ifx)
+ storeRegToAop (hc08_reg_a, AOP (result), offset);
+ else
+ emitcode ("tsta", "");
+ offset++;
+ }
- /* if left is rematerialisable and
- result is not bit variable type and
- the left is pointer to data space i.e
- lower 128 bytes of space */
- if ((AOP_TYPE (left) == AOP_IMMD)
- || (AOP_TYPE (left) == AOP_LIT)
- /* !IS_BITVAR (retype) */
- /* && DCL_TYPE (ltype) == POINTER */ )
- {
- genDataPointerGet (left, result, ic);
- return;
+ /* Handle the partial byte at the end */
+ if (rlen)
+ {
+ loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
+ emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen));
+ storeRegToAop (hc08_reg_a, AOP (result), offset++);
}
- /* if the operand is already in hx
- then we do nothing else we move the value to hx */
- if (AOP_TYPE (left) != AOP_STR)
+finish:
+ if (offset < rsize)
{
- /* if this is remateriazable */
- loadRegFromAop (hc08_reg_x, AOP (left), 0);
- loadRegFromConst (hc08_reg_h, zero);
+ rsize -= offset;
+ while (rsize--)
+ storeConstToAop (zero, AOP (result), offset++);
+ }
+
+ freeAsmop (NULL, derefaop, ic, TRUE);
+ freeAsmop (result, NULL, ic, TRUE);
+
+ if (ifx && !ifx->generated)
+ {
+ genIfxJump (ifx, "a");
}
+}
- /* so hx now contains the address */
- aopOp (result, ic, FALSE);
- /* if bit then unpack */
- if (IS_BITVAR (retype))
- genUnpackBits (result);
- else
- {
- size = AOP_SIZE (result);
- offset = size-1;
+/*-----------------------------------------------------------------*/
+/* genDataPointerGet - generates code when ptr offset is known */
+/*-----------------------------------------------------------------*/
+static void
+genDataPointerGet (operand * left,
+ operand * result,
+ iCode * ic,
+ iCode * ifx)
+{
+ int size;
+ asmop *derefaop;
+
+ D(emitcode ("; genDataPointerGet",""));
- while (size--)
- {
- accopWithMisc ("lda", ",x");
- if (size || pi)
- {
- rmwWithReg ("inc", hc08_reg_x);
- }
- storeRegToAop (hc08_reg_a, AOP (result), offset--);
- hc08_freeReg (hc08_reg_a);
- }
- }
+ aopOp (result, ic, TRUE);
+ size = AOP_SIZE (result);
+ derefaop = aopDerefAop (AOP (left));
freeAsmop (left, NULL, ic, TRUE);
- freeAsmop (result, NULL, ic, TRUE);
+ derefaop->size = size;
- if (pi /* && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR */) {
- aopOp (IC_RESULT (pi), pi, FALSE);
- storeRegToAop (hc08_reg_x, AOP (IC_RESULT (pi)), 0);
- freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
- pi->generated = 1;
- }
+ while (size--)
+ {
+ if (!ifx)
+ transferAopAop (derefaop, size, AOP (result), size);
+ else
+ loadRegFromAop (hc08_reg_a, derefaop, size);
+ }
- hc08_freeReg (hc08_reg_hx);
+ freeAsmop (NULL, derefaop, ic, TRUE);
+ freeAsmop (result, NULL, ic, TRUE);
+ if (ifx && !ifx->generated)
+ {
+ genIfxJump (ifx, "a");
+ }
}
/*-----------------------------------------------------------------*/
-/* genFarPointerGet - get value from far space */
+/* genPointerGet - generate code for pointer get */
/*-----------------------------------------------------------------*/
static void
-genFarPointerGet (operand * left,
- operand * result, iCode * ic, iCode * pi)
+genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
{
+ operand *left = IC_LEFT (ic);
+ operand *result = IC_RESULT (ic);
int size, offset;
sym_link *retype = getSpec (operandType (result));
- D(emitcode ("; genFarPointerGet",""));
+ D(emitcode ("; genPointerGet",""));
+ if (getSize (operandType (result))>1)
+ ifx = NULL;
+
aopOp (left, ic, FALSE);
/* if left is rematerialisable and
- result is not bit 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)
- /* && DCL_TYPE (ltype) == POINTER */ )
- {
- genDataPointerGet (left, result, ic);
- return;
+ result is not bit variable type */
+ if (AOP_TYPE (left) == AOP_IMMD || AOP_TYPE (left) == AOP_LIT)
+ {
+ if (!IS_BITVAR (retype))
+ {
+ genDataPointerGet (left, result, ic, ifx);
+ return;
+ }
+ else
+ {
+ genUnpackBitsImmed (left, result, ic, ifx);
+ return;
+ }
}
/* if the operand is already in hx
/* if bit then unpack */
if (IS_BITVAR (retype))
- genUnpackBits (result);
+ genUnpackBits (result, ifx);
else
{
size = AOP_SIZE (result);
emitcode ("aix", "#1");
hc08_dirtyReg (hc08_reg_hx, FALSE);
}
- storeRegToAop (hc08_reg_a, AOP (result), offset--);
+ if (!ifx)
+ storeRegToAop (hc08_reg_a, AOP (result), offset);
+ offset--;
hc08_freeReg (hc08_reg_a);
}
}
freeAsmop (left, NULL, ic, TRUE);
freeAsmop (result, NULL, ic, TRUE);
- if (pi /* && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR */) {
+ if (pi) {
aopOp (IC_RESULT (pi), pi, FALSE);
storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
pi->generated = 1;
}
+
+ if (ifx && !ifx->generated)
+ {
+ genIfxJump (ifx, "a");
+ }
hc08_freeReg (hc08_reg_hx);
}
-
-
/*-----------------------------------------------------------------*/
-/* genPointerGet - generate code for pointer get */
+/* genPackBits - generates code for packed bit storage */
/*-----------------------------------------------------------------*/
static void
-genPointerGet (iCode * ic, iCode *pi)
+genPackBits (sym_link * etype,
+ operand * right)
{
- operand *left, *result;
- sym_link *type, *etype;
- int p_type;
+ int offset = 0; /* source byte offset */
+ int rlen = 0; /* remaining bitfield length */
+ int blen; /* bitfield length */
+ int bstr; /* bitfield starting bit within byte */
+ int litval; /* source literal value (if AOP_LIT) */
+ unsigned char mask; /* bitmask within current byte */
+ int xoffset = 0;
- D(emitcode ("; genPointerGet",""));
+ D(emitcode ("; genPackBits",""));
- left = IC_LEFT (ic);
- result = IC_RESULT (ic);
+ blen = SPEC_BLEN (etype);
+ bstr = SPEC_BSTR (etype);
- /* depending on the type of pointer we need to
- move it to the correct pointer register */
- type = operandType (left);
- etype = getSpec (type);
- /* if left is of type of pointer then it is simple */
- if (IS_PTR (type) && !IS_FUNC (type->next))
- p_type = DCL_TYPE (type);
- else
+ /* If the bitfield length is less than a byte */
+ if (blen < 8)
{
- /* we have to go by the storage class */
- p_type = PTR_TYPE (SPEC_OCLS (etype));
+ mask = ((unsigned char) (0xFF << (blen + bstr)) |
+ (unsigned char) (0xFF >> (8 - bstr)));
+
+ if (AOP_TYPE (right) == AOP_LIT)
+ {
+ /* Case with a bitfield length <8 and literal source
+ */
+ litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
+ litval <<= bstr;
+ litval &= (~mask) & 0xff;
+
+ emitcode ("lda", ",x");
+ if ((mask|litval)!=0xff)
+ emitcode ("and","#0x%02x", mask);
+ if (litval)
+ emitcode ("ora","#0x%02x", litval);
+ hc08_dirtyReg (hc08_reg_a, FALSE);
+ emitcode ("sta", ",x");
+
+ hc08_freeReg (hc08_reg_a);
+ return;
+ }
+
+ /* Case with a bitfield length < 8 and arbitrary source
+ */
+ loadRegFromAop (hc08_reg_a, AOP (right), 0);
+ /* shift and mask source value */
+ AccLsh (bstr);
+ emitcode ("and", "#0x%02x", (~mask) & 0xff);
+ hc08_dirtyReg (hc08_reg_a, FALSE);
+ pushReg (hc08_reg_a, TRUE);
+
+ emitcode ("lda", ",x");
+ emitcode ("and", "#0x%02x", mask);
+ emitcode ("ora", "1,s");
+ emitcode ("sta", ",x");
+ pullReg (hc08_reg_a);
+
+ hc08_freeReg (hc08_reg_a);
+ return;
}
- /* special case when cast remat */
- if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
- IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
- left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
- type = operandType (left);
- p_type = DCL_TYPE (type);
- }
- /* now that we have the pointer type we assign
- the pointer values */
- switch (p_type)
+ /* Bit length is greater than 7 bits. In this case, copy */
+ /* all except the partial byte at the end */
+ for (rlen=blen;rlen>=8;rlen-=8)
{
+ if (AOP (right)->type == AOP_DIR)
+ {
+ emitcode ("mov", "%s,x+", aopAdrStr(AOP (right), offset, FALSE));
+ xoffset++;
+ }
+ else
+ {
+ loadRegFromAop (hc08_reg_a, AOP (right), offset);
+ emitcode ("sta", "%d,x", offset);
+ }
+ offset++;
+ }
- case POINTER:
- case IPOINTER:
-#if 0
- genNearPointerGet (left, result, ic, pi);
- break;
-#endif
- case GPOINTER:
- case CPOINTER:
- case FPOINTER:
- genFarPointerGet (left, result, ic, pi);
- break;
+ /* If there was a partial byte at the end */
+ if (rlen)
+ {
+ mask = (((unsigned char) -1 << rlen) & 0xff);
+
+ if (AOP_TYPE (right) == AOP_LIT)
+ {
+ /* Case with partial byte and literal source
+ */
+ litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
+ litval >>= (blen-rlen);
+ litval &= (~mask) & 0xff;
+ emitcode ("lda", "%d,x", offset - xoffset);
+ hc08_dirtyReg (hc08_reg_a, FALSE);
+ if ((mask|litval)!=0xff)
+ emitcode ("and","#0x%02x", mask);
+ if (litval)
+ emitcode ("ora","#0x%02x", litval);
+ emitcode ("sta", "%d,x", offset - xoffset);
+ hc08_dirtyReg (hc08_reg_a, FALSE);
+ hc08_freeReg (hc08_reg_a);
+ return;
+ }
+
+ /* Case with partial byte and arbitrary source
+ */
+ loadRegFromAop (hc08_reg_a, AOP (right), offset);
+ emitcode ("and", "#0x%02x", (~mask) & 0xff);
+ hc08_dirtyReg (hc08_reg_a, FALSE);
+ pushReg (hc08_reg_a, TRUE);
+ emitcode ("lda", "%d,x", offset - xoffset);
+ emitcode ("and", "#0x%02x", mask);
+ emitcode ("ora", "1,s");
+ emitcode ("sta", "%d,x", offset - xoffset);
+ pullReg (hc08_reg_a);
}
+ hc08_freeReg (hc08_reg_a);
}
/*-----------------------------------------------------------------*/
-/* genPackBits - generates code for packed bit storage */
+/* genPackBitsImmed - generates code for packed bit storage */
/*-----------------------------------------------------------------*/
static void
-genPackBits (sym_link * etype,
- operand * right)
+genPackBitsImmed (operand *result, sym_link * etype, operand * right, iCode * ic)
{
+ asmop *derefaop;
+ int size;
int offset = 0; /* source byte offset */
int rlen = 0; /* remaining bitfield length */
int blen; /* bitfield length */
int litval; /* source literal value (if AOP_LIT) */
unsigned char mask; /* bitmask within current byte */
- D(emitcode ("; genPackBits",""));
+ D(emitcode ("; genPackBitsImmed",""));
blen = SPEC_BLEN (etype);
bstr = SPEC_BSTR (etype);
-
+
+ aopOp (right, ic, FALSE);
+ size = AOP_SIZE (right);
+
+ derefaop = aopDerefAop (AOP (result));
+ freeAsmop (result, NULL, ic, TRUE);
+ derefaop->size = size;
+
+ /* if the bitfield is a single bit in the direct page */
+ if (blen == 1 && derefaop->type == AOP_DIR)
+ {
+ if (AOP_TYPE (right) == AOP_LIT)
+ {
+ litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
+
+ emitcode ((litval & 1) ? "bset" : "bclr",
+ "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
+ }
+ else
+ {
+ symbol *tlbl1 = newiTempLabel (NULL);
+ symbol *tlbl2 = newiTempLabel (NULL);
+
+ loadRegFromAop (hc08_reg_a, AOP (right), 0);
+ emitcode ("bit", "#1");
+ emitBranch ("bne", tlbl1);
+ emitcode ("bclr", "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
+ emitBranch ("bra", tlbl2);
+ emitLabel (tlbl1);
+ emitcode ("bset", "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
+ emitLabel (tlbl2);
+ hc08_freeReg (hc08_reg_a);
+ }
+ goto release;
+ }
+
/* If the bitfield length is less than a byte */
if (blen < 8)
{
litval <<= bstr;
litval &= (~mask) & 0xff;
- emitcode ("lda", ",x");
+ loadRegFromAop (hc08_reg_a, derefaop, 0);
if ((mask|litval)!=0xff)
emitcode ("and","#0x%02x", mask);
if (litval)
emitcode ("ora","#0x%02x", litval);
hc08_dirtyReg (hc08_reg_a, FALSE);
- emitcode ("sta", ",x");
+ storeRegToAop (hc08_reg_a, derefaop, 0);
hc08_freeReg (hc08_reg_a);
- return;
+ goto release;
}
/* Case with a bitfield length < 8 and arbitrary source
hc08_dirtyReg (hc08_reg_a, FALSE);
pushReg (hc08_reg_a, TRUE);
- emitcode ("lda", ",x");
+ loadRegFromAop (hc08_reg_a, derefaop, 0);
emitcode ("and", "#0x%02x", mask);
emitcode ("ora", "1,s");
- emitcode ("sta", ",x");
+ storeRegToAop (hc08_reg_a, derefaop, 0);
pullReg (hc08_reg_a);
hc08_freeReg (hc08_reg_a);
- return;
+ goto release;
}
/* Bit length is greater than 7 bits. In this case, copy */
/* all except the partial byte at the end */
for (rlen=blen;rlen>=8;rlen-=8)
{
- if (AOP (right)->type == AOP_DIR)
- {
- emitcode ("mov", "%s,x+", aopAdrStr(AOP (right), offset, FALSE));
- }
- else
- {
- loadRegFromAop (hc08_reg_a, AOP (right), offset);
- emitcode ("sta", "%d,x", offset);
- }
+ transferAopAop (AOP (right), offset, derefaop, size-offset-1);
offset++;
}
litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
litval >>= (blen-rlen);
litval &= (~mask) & 0xff;
- emitcode ("lda", "%d,x", offset);
- hc08_dirtyReg (hc08_reg_a, FALSE);
+ loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
if ((mask|litval)!=0xff)
emitcode ("and","#0x%02x", mask);
if (litval)
emitcode ("ora","#0x%02x", litval);
- emitcode ("sta", "%d,x", offset);
+ hc08_dirtyReg (hc08_reg_a, FALSE);
+ storeRegToAop (hc08_reg_a, derefaop, size-offset-1);
hc08_dirtyReg (hc08_reg_a, FALSE);
hc08_freeReg (hc08_reg_a);
- return;
+ goto release;
}
/* Case with partial byte and arbitrary source
*/
- loadRegFromAop (hc08_reg_a, AOP (right), offset++);
+ loadRegFromAop (hc08_reg_a, AOP (right), offset);
emitcode ("and", "#0x%02x", (~mask) & 0xff);
hc08_dirtyReg (hc08_reg_a, FALSE);
pushReg (hc08_reg_a, TRUE);
- emitcode ("lda", ",x");
+ loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
emitcode ("and", "#0x%02x", mask);
emitcode ("ora", "1,s");
- emitcode ("sta", ",x");
+ storeRegToAop (hc08_reg_a, derefaop, size-offset-1);
+ pullReg (hc08_reg_a);
}
hc08_freeReg (hc08_reg_a);
+
+release:
+ freeAsmop (right, NULL, ic, TRUE);
+ freeAsmop (NULL, derefaop, ic, TRUE);
}
/*-----------------------------------------------------------------*/
operand * result,
iCode * ic)
{
- int size, offset = 0;
+ int size;
asmop *derefaop;
D(emitcode ("; genDataPointerSet",""));
while (size--)
{
- transferAopAop (AOP (right), offset, derefaop, offset);
- offset++;
+ transferAopAop (AOP (right), size, derefaop, size);
}
freeAsmop (right, NULL, ic, TRUE);
freeAsmop (NULL, derefaop, ic, TRUE);
}
-/*-----------------------------------------------------------------*/
-/* genNearPointerSet - emitcode for near pointer put */
-/*-----------------------------------------------------------------*/
-static void
-genNearPointerSet (operand * right,
- operand * result,
- iCode * ic,
- iCode * pi)
-{
- int size, offset;
- sym_link *retype = getSpec (operandType (right));
- sym_link *letype = getSpec (operandType (result));
-
- D(emitcode ("; genNearPointerSet",""));
-
- aopOp (result, ic, FALSE);
-
- /* if the result is rematerializable &
- in data space & not a bit variable */
- if (AOP_TYPE (result) == AOP_IMMD &&
- /* DCL_TYPE (ptype) == POINTER && */
- !IS_BITVAR (retype) &&
- !IS_BITVAR (letype))
- {
- genDataPointerSet (right, result, ic);
- return;
- }
-
- /* if the operand is already in hx
- then we do nothing else we move the value to hx */
- if (AOP_TYPE (result) != AOP_STR)
- {
- loadRegFromAop (hc08_reg_x, AOP (result), 0);
- loadRegFromConst (hc08_reg_h, zero);
- }
- /* so hx now contains the address */
- aopOp (right, ic, FALSE);
-
- /* if bit then unpack */
- if (IS_BITVAR (retype) || IS_BITVAR (letype))
- genPackBits ((IS_BITVAR (retype) ? retype : letype), right);
- else
- {
- size = AOP_SIZE (right);
- offset = size-1;
-
- while (size--)
- {
- loadRegFromAop (hc08_reg_a, AOP (right), offset--);
- accopWithMisc ("sta", ",x");
- if (size || pi)
- {
- rmwWithReg ("inc", hc08_reg_x);
- }
- hc08_freeReg (hc08_reg_a);
- }
- }
-
- freeAsmop (result, NULL, ic, TRUE);
- freeAsmop (right, NULL, ic, TRUE);
-
- if (pi /* && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD */) {
- aopOp (IC_RESULT (pi), pi, FALSE);
- storeRegToAop (hc08_reg_x, AOP (IC_RESULT (pi)), 0);
- freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
- pi->generated=1;
- }
-
- hc08_freeReg (hc08_reg_hx);
-
-}
-
/*-----------------------------------------------------------------*/
-/* genFarPointerSet - set value from far space */
+/* genPointerSet - stores the value into a pointer location */
/*-----------------------------------------------------------------*/
static void
-genFarPointerSet (operand * right,
- operand * result, iCode * ic, iCode * pi)
+genPointerSet (iCode * ic, iCode *pi)
{
+ operand *right = IC_RIGHT (ic);
+ operand *result = IC_RESULT (ic);
+ sym_link *type, *etype;
int size, offset;
sym_link *retype = getSpec (operandType (right));
sym_link *letype = getSpec (operandType (result));
- D(emitcode ("; genFarPointerSet",""));
+ D(emitcode ("; genPointerSet",""));
+ type = operandType (result);
+ etype = getSpec (type);
+
aopOp (result, ic, FALSE);
- /* if the result is rematerializable &
- in data space & not a bit variable */
- if (AOP_TYPE (result) == AOP_IMMD &&
- /* DCL_TYPE (ptype) == POINTER && */
- !IS_BITVAR (retype) &&
- !IS_BITVAR (letype))
+ /* if the result is rematerializable */
+ if (AOP_TYPE (result) == AOP_IMMD || AOP_TYPE (result) == AOP_LIT)
{
- genDataPointerSet (right, result, ic);
- return;
+ if (!IS_BITVAR (retype) && !IS_BITVAR (letype))
+ {
+ genDataPointerSet (right, result, ic);
+ return;
+ }
+ else
+ {
+ genPackBitsImmed (result, (IS_BITVAR (retype) ? retype : letype), right, ic);
+ return;
+ }
}
/* if the operand is already in hx
freeAsmop (result, NULL, ic, TRUE);
freeAsmop (right, NULL, ic, TRUE);
- if (pi /* && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD */) {
+ if (pi) {
aopOp (IC_RESULT (pi), pi, FALSE);
storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
}
hc08_freeReg (hc08_reg_hx);
-
-
-}
-
-
-/*-----------------------------------------------------------------*/
-/* genPointerSet - stores the value into a pointer location */
-/*-----------------------------------------------------------------*/
-static void
-genPointerSet (iCode * ic, iCode *pi)
-{
- operand *right, *result;
- sym_link *type, *etype;
- int p_type;
-
- D(emitcode ("; genPointerSet",""));
-
- right = IC_RIGHT (ic);
- result = IC_RESULT (ic);
-
- /* depending on the type of pointer we need to
- move it to the correct pointer register */
- type = operandType (result);
- etype = getSpec (type);
- /* if left is of type of pointer then it is simple */
- if (IS_PTR (type) && !IS_FUNC (type->next))
- {
- p_type = DCL_TYPE (type);
- }
- else
- {
- /* we have to go by the storage class */
- p_type = PTR_TYPE (SPEC_OCLS (etype));
- }
-
- /* special case when cast remat */
- if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
- IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
- result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
- type = operandType (result);
- p_type = DCL_TYPE (type);
- }
- /* now that we have the pointer type we assign
- the pointer values */
- switch (p_type)
- {
-
- case POINTER:
- case IPOINTER:
-#if 0
- genNearPointerSet (right, result, ic, pi);
- break;
-#endif
-
- case GPOINTER:
- case FPOINTER:
- genFarPointerSet (right, result, ic, pi);
- break;
-
- default:
- werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
- "genPointerSet: illegal pointer type");
- }
}
genAssign (iCode * ic)
{
operand *result, *right;
- int size, offset;
+ int size;
// unsigned long lit = 0L;
D(emitcode("; genAssign",""));
/* general case */
size = AOP_SIZE (result);
- offset = 0;
-
while (size--)
{
- transferAopAop (AOP (right), offset, AOP (result), offset);
- offset++;
+ transferAopAop (AOP (right), size, AOP (result), size);
}
release:
}
/*-----------------------------------------------------------------*/
-/* genJumpTab - genrates code for jump table */
+/* genJumpTab - generates code for jump table */
/*-----------------------------------------------------------------*/
static void
genJumpTab (iCode * ic)
{
symbol *jtab;
-// char *l;
-
+ symbol *jtablo = newiTempLabel (NULL);
+ symbol *jtabhi = newiTempLabel (NULL);
+
D(emitcode ("; genJumpTab",""));
aopOp (IC_JTCOND (ic), ic, FALSE);
- /* get the condition into accumulator */
- loadRegFromAop (hc08_reg_a, AOP (IC_JTCOND (ic)), 0);
- freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
- /* multiply by three */
- pushReg (hc08_reg_a, FALSE);
- emitcode ("lsla", "");
- emitcode ("add","1,s");
- transferRegReg (hc08_reg_a, hc08_reg_x, TRUE);
- loadRegFromConst (hc08_reg_h, zero);
+
+ if (hc08_reg_x->isFree && hc08_reg_x->isFree)
+ {
+ /* get the condition into x */
+ loadRegFromAop (hc08_reg_x, AOP (IC_JTCOND (ic)), 0);
+ freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
+ loadRegFromConst (hc08_reg_h, zero);
+
+ emitcode ("lda", "%05d$,x", jtabhi->key + 100);
+ emitcode ("ldx", "%05d$,x", jtablo->key + 100);
+ transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
+ emitcode ("jmp", ",x");
+
+ hc08_dirtyReg (hc08_reg_a, TRUE);
+ hc08_dirtyReg (hc08_reg_hx, TRUE);
+ }
+ else
+ {
+ adjustStack(-2);
+ pushReg(hc08_reg_hx, TRUE);
+
+ /* get the condition into x */
+ loadRegFromAop (hc08_reg_x, AOP (IC_JTCOND (ic)), 0);
+ freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
+ loadRegFromConst (hc08_reg_h, zero);
+
+ emitcode ("lda", "%05d$,x", jtabhi->key + 100);
+ emitcode ("sta", "3,s");
+ emitcode ("lda", "%05d$,x", jtablo->key + 100);
+ emitcode ("sta", "4,s");
+
+ pullReg(hc08_reg_hx);
+ emitcode ("rts", "");
+ _G.stackPushes += 2;
+ updateCFA();
+ }
- jtab = newiTempLabel (NULL);
- emitcode ("jmp", "%05d$,x", jtab->key + 100);
- emitcode ("", "%05d$:", jtab->key + 100);
/* now generate the jump labels */
+ emitLabel (jtablo);
+ for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
+ jtab = setNextItem (IC_JTLABELS (ic)))
+ emitcode (".db", "%05d$", jtab->key + 100);
+ emitLabel (jtabhi);
for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
jtab = setNextItem (IC_JTLABELS (ic)))
- emitcode ("jmp", "%05d$", jtab->key + 100);
+ emitcode (".db", ">%05d$", jtab->key + 100);
- hc08_dirtyReg (hc08_reg_a, TRUE);
- hc08_dirtyReg (hc08_reg_hx, TRUE);
}
/*-----------------------------------------------------------------*/
exit(1);
}
- sprintf(gpValStr, "#0x%d", gpVal);
+ sprintf(gpValStr, "#0x%x", gpVal);
aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
}
#endif
if (operandLitValue (IC_RIGHT (ic)) != 1)
return 0;
+ /* dbnz doesn't support extended mode */
+ if (isOperandInFarSpace (IC_RESULT (ic)))
+ return 0;
+
/* if the size of this greater than one then no
saving */
// if (getSize (operandType (IC_RESULT (ic))) > 1)
freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
}
+/*-----------------------------------------------------------------*/
+/* genDummyRead - generate code for dummy read of volatiles */
+/*-----------------------------------------------------------------*/
+static void
+genDummyRead (iCode * ic)
+{
+ operand *op;
+ int size, offset;
+
+ D(emitcode("; genDummyRead",""));
+
+ op = IC_RIGHT (ic);
+ if (op && IS_SYMOP (op))
+ {
+
+ aopOp (op, ic, FALSE);
+
+ size = AOP_SIZE (op);
+ offset = 0;
+
+ while (size--)
+ {
+ loadRegFromAop (hc08_reg_a, AOP (op), offset);
+ hc08_freeReg (hc08_reg_a);
+ offset++;
+ }
+
+ freeAsmop (op, NULL, ic, TRUE);
+ }
+ op = IC_LEFT (ic);
+ if (op && IS_SYMOP (op))
+ {
+
+ aopOp (op, ic, FALSE);
+
+ size = AOP_SIZE (op);
+ offset = 0;
+
+ while (size--)
+ {
+ loadRegFromAop (hc08_reg_a, AOP (op), offset);
+ hc08_freeReg (hc08_reg_a);
+ offset++;
+ }
+
+ freeAsmop (op, NULL, ic, TRUE);
+ }
+}
+
+/*-----------------------------------------------------------------*/
+/* genCritical - generate code for start of a critical sequence */
+/*-----------------------------------------------------------------*/
+static void
+genCritical (iCode *ic)
+{
+ D(emitcode("; genCritical",""));
+
+ if (IC_RESULT (ic))
+ aopOp (IC_RESULT (ic), ic, TRUE);
+
+ emitcode ("tpa", "");
+ hc08_dirtyReg (hc08_reg_a, FALSE);
+ emitcode ("sei", "");
+
+ if (IC_RESULT (ic))
+ storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), 0);
+ else
+ pushReg (hc08_reg_a, FALSE);
+
+ hc08_freeReg (hc08_reg_a);
+ if (IC_RESULT (ic))
+ freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genEndCritical - generate code for end of a critical sequence */
+/*-----------------------------------------------------------------*/
+static void
+genEndCritical (iCode *ic)
+{
+ D(emitcode("; genEndCritical",""));
+
+ if (IC_RIGHT (ic))
+ {
+ aopOp (IC_RIGHT (ic), ic, FALSE);
+ loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
+ emitcode ("tap", "");
+ hc08_freeReg (hc08_reg_a);
+ freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
+ }
+ else
+ {
+ pullReg (hc08_reg_a);
+ emitcode ("tap", "");
+ }
+}
+
+
+
/*-----------------------------------------------------------------*/
/* genhc08Code - generate code for HC08 based controllers */
/*-----------------------------------------------------------------*/
{
iCode *ic;
int cln = 0;
+ int clevel = 0;
+ int cblock = 0;
lineHead = lineCurr = NULL;
/* if debug information required */
if (options.debug && currFunc)
{
- debugFile->writeFunction(currFunc);
+ debugFile->writeFunction (currFunc, lic);
+ #if 0
_G.debugLine = 1;
if (IS_STATIC (currFunc->etype))
emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
else
emitcode ("", "G$%s$0$0 ==.", currFunc->name);
_G.debugLine = 0;
+ #endif
}
/* stack pointer name */
if (options.useXstack)
spname = "_spx";
else
spname = "sp";
+
+ debugFile->writeFrameAddress (NULL, NULL, 0); /* have no idea where frame is now */
hc08_aop_pass[0] = newAsmop (AOP_REG);
hc08_aop_pass[0]->size=1;
for (ic = lic; ic; ic = ic->next)
{
-
+
+ _G.current_iCode = ic;
+
+ if (ic->level != clevel || ic->block != cblock)
+ {
+ if (options.debug)
+ {
+ debugFile->writeScope(ic);
+ }
+ clevel = ic->level;
+ cblock = ic->block;
+ }
+
if (ic->lineno && cln != ic->lineno)
{
if (options.debug)
{
+ debugFile->writeCLine(ic);
+ #if 0
_G.debugLine = 1;
emitcode ("", "C$%s$%d$%d$%d ==.",
FileBaseName (ic->filename), ic->lineno,
ic->level, ic->block);
_G.debugLine = 0;
+ #endif
}
if (!options.noCcodeInAsm) {
emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
break;
case '>':
- genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
- break;
-
case '<':
- genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
- break;
-
case LE_OP:
case GE_OP:
- case NE_OP:
-
- /* note these two are xlated by algebraic equivalence
- during parsing SDCC.y */
- werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
- "got '>=' or '<=' shouldn't have come here");
- break;
+ genCmp (ic, ifxForOp (IC_RESULT (ic), ic));
+ break;
+ case NE_OP:
case EQ_OP:
- genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
- break;
+ genCmpEQorNE (ic, ifxForOp (IC_RESULT (ic), ic));
+ break;
case AND_OP:
genAndOp (ic);
break;
case GET_VALUE_AT_ADDRESS:
- genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_RESULT(ic)))));
+ genPointerGet (ic,
+ hasInc (IC_LEFT (ic), ic,
+ getSize (operandType (IC_RESULT (ic)))),
+ ifxForOp (IC_RESULT (ic), ic) );
break;
case '=':
addSet (&_G.sendSet, ic);
break;
+ case DUMMY_READ_VOLATILE:
+ genDummyRead (ic);
+ break;
+
+ case CRITICAL:
+ genCritical (ic);
+ break;
+
+ case ENDCRITICAL:
+ genEndCritical (ic);
+ break;
+
+ case SWAP:
+ genSwap (ic);
+ break;
+
default:
ic = ic;
}
if (!hc08_reg_a->isFree)
- emitcode("","; forgot to free a");
+ D(emitcode("","; forgot to free a"));
if (!hc08_reg_x->isFree)
- emitcode("","; forgot to free x");
+ D(emitcode("","; forgot to free x"));
if (!hc08_reg_h->isFree)
- emitcode("","; forgot to free h");
+ D(emitcode("","; forgot to free h"));
if (!hc08_reg_hx->isFree)
- emitcode("","; forgot to free hx");
+ D(emitcode("","; forgot to free hx"));
if (!hc08_reg_xa->isFree)
- emitcode("","; forgot to free xa");
+ D(emitcode("","; forgot to free xa"));
}
+ debugFile->writeFrameAddress (NULL, NULL, 0); /* have no idea where frame is now */
+
/* now we are ready to call the
peep hole optimizer */