9. With asm optimised strings 17030 192 2223
10 and below are with asm strings off.
-
+
+ 10 Mucho optimisations 13562 201 1FCC
+
Apparent advantage of turning on regparams:
1. Cost of push
Decent case is push of a constant
#include <string.h>
#include <ctype.h>
-#ifdef HAVE_SYS_ISA_DEFS_H
-#include <sys/isa_defs.h>
+#if defined(__BORLANDC__) || defined(_MSC_VER)
+#define STRCASECMP stricmp
+#else
+#define STRCASECMP strcasecmp
#endif
#include "z80.h"
int pushedBC;
int pushedDE;
} stack;
+
+ struct
+ {
+ int pushedBC;
+ int pushedDE;
+ } calleeSaves;
+
int frameId;
int receiveOffset;
bool flushStatics;
"AOP_PAIRPT"
};
+static bool
+isLastUse (iCode *ic, operand *op)
+{
+ bitVect *uses = bitVectCopy (OP_USES (op));
+
+ while (!bitVectIsZero (uses))
+ {
+ if (bitVectFirstBit (uses) == ic->key)
+ {
+ if (bitVectnBitsOn (uses) == 1)
+ {
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+ }
+ bitVectUnSetBit (uses, bitVectFirstBit (uses));
+ }
+
+ return FALSE;
+}
+
static PAIR_ID
_getTempPairId(void)
{
return _pairs[_getTempPairId()].name;
}
+static bool
+isPairInUse (PAIR_ID id, iCode *ic)
+{
+ if (id == PAIR_DE)
+ {
+ return bitVectBitValue (ic->rMask, D_IDX) || bitVectBitValue(ic->rMask, E_IDX);
+ }
+ else if (id == PAIR_BC)
+ {
+ return bitVectBitValue (ic->rMask, B_IDX) || bitVectBitValue(ic->rMask, C_IDX);
+ }
+ else
+ {
+ wassertl (0, "Only implemented for DE and BC");
+ return TRUE;
+ }
+}
+
+static bool
+isPairInUseNotInRet(PAIR_ID id, iCode *ic)
+{
+ bitVect *rInUse;
+
+ rInUse = bitVectCplAnd (bitVectCopy (ic->rMask), ic->rUsed);
+
+ if (id == PAIR_DE)
+ {
+ return bitVectBitValue (rInUse, D_IDX) || bitVectBitValue(rInUse, E_IDX);
+ }
+ else
+ {
+ wassertl (0, "Only implemented for DE");
+ return TRUE;
+ }
+}
+
static PAIR_ID
getFreePairId (iCode *ic)
{
- if (!(bitVectBitValue (ic->rMask, B_IDX) || bitVectBitValue(ic->rMask, C_IDX)))
+ if (!isPairInUse (PAIR_BC, ic))
{
return PAIR_BC;
}
- else if (IS_Z80 && !(bitVectBitValue (ic->rMask, D_IDX) || bitVectBitValue(ic->rMask, E_IDX)))
+ else if (IS_Z80 && !isPairInUse (PAIR_DE, ic))
{
return PAIR_DE;
}
{
char buffer[256];
- tvsprintf (buffer, szFormat, ap);
+ tvsprintf (buffer, sizeof(buffer), szFormat, ap);
_tidyUp (buffer);
_G.lines.current = (_G.lines.current ?
static void
_emitMove(const char *to, const char *from)
{
- if (strcasecmp(to, from) != 0)
+ if (STRCASECMP(to, from) != 0)
{
emit2("ld %s,%s", to, from);
}
}
}
-static void
+void
aopDump(const char *plabel, asmop *aop)
{
emitDebug("; Dump of %s: type %s size %u", plabel, aopNames[aop->type], aop->size);
break;
default:
/* No information. */
+ break;
}
}
}
/* else spill location */
- op->aop = aop =
+ if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
+ /* force a new aop if sizes differ */
+ sym->usl.spillLoc->aop = NULL;
+ }
+ sym->aop = op->aop = aop =
aopForSym (ic, sym->usl.spillLoc, result, requires_a);
wassertl (aop->size >= getSize (sym->type), "Operand doesn't fit in the spill location");
aop->size = getSize (sym->type);
- /* PENDING: HACK. Can have different sizes in the same AOP. */
- sym->usl.spillLoc->aop = NULL;
return;
}
_pop (aop->aopu.aop_pairId);
}
+ if (getPairId (aop) == PAIR_HL)
+ {
+ spillPair (PAIR_HL);
+ }
+
dealloc:
/* all other cases just dealloc */
if (op)
char *
aopGetLitWordLong (asmop * aop, int offset, bool with_hash)
{
- char *s = buffer;
-
/* depending on type */
switch (aop->type)
{
/* PENDING: for re-target */
if (with_hash)
{
- tsprintf (s, "!hashedstr + %d", aop->aopu.aop_immd, offset);
+ tsprintf (buffer, sizeof(buffer),
+ "!hashedstr + %d", aop->aopu.aop_immd, offset);
}
else if (offset == 0)
{
- tsprintf (s, "%s", aop->aopu.aop_immd);
+ tsprintf (buffer, sizeof(buffer),
+ "%s", aop->aopu.aop_immd);
}
else
{
- tsprintf (s, "%s + %d", aop->aopu.aop_immd, offset);
+ tsprintf (buffer, sizeof(buffer),
+ "%s + %d", aop->aopu.aop_immd, offset);
}
- return traceAlloc(&_G.trace.aops, Safe_strdup(s));
+ return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
case AOP_LIT:
{
}
if (with_hash)
- tsprintf (buffer, "!immedword", v);
+ tsprintf (buffer, sizeof(buffer), "!immedword", v);
else
- tsprintf (buffer, "!constword", v);
+ tsprintf (buffer, sizeof(buffer), "!constword", v);
return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
}
/* it is type float */
fl.f = (float) floatFromVal (val);
-#ifdef _BIG_ENDIAN
+#ifdef WORDS_BIGENDIAN
i = fl.c[3-offset] | (fl.c[3-offset-1]<<8);
#else
i = fl.c[offset] | (fl.c[offset+1]<<8);
#endif
if (with_hash)
- tsprintf (buffer, "!immedword", i);
+ tsprintf (buffer, sizeof(buffer), "!immedword", i);
else
- tsprintf (buffer, "!constword", i);
+ tsprintf (buffer, sizeof(buffer), "!constword", i);
return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
}
emit2 ("ld %s,!hashedstr", pair, l);
}
+static PAIR_ID
+makeFreePairId (iCode *ic, bool *pisUsed)
+{
+ *pisUsed = FALSE;
+
+ if (ic != NULL)
+ {
+ if (!bitVectBitValue (ic->rMask, B_IDX) && !bitVectBitValue(ic->rMask, C_IDX))
+ {
+ return PAIR_BC;
+ }
+ else if (IS_Z80 && !bitVectBitValue (ic->rMask, D_IDX) && !bitVectBitValue(ic->rMask, E_IDX))
+ {
+ return PAIR_DE;
+ }
+ else
+ {
+ *pisUsed = TRUE;
+ return PAIR_HL;
+ }
+ }
+ else
+ {
+ *pisUsed = TRUE;
+ return PAIR_HL;
+ }
+}
+
static void
-fetchPairLong (PAIR_ID pairId, asmop * aop, int offset)
+fetchPairLong (PAIR_ID pairId, asmop * aop, iCode *ic, int offset)
{
/* if this is remateriazable */
if (isLitWord (aop)) {
}
else
{
- _push (PAIR_HL);
+ bool isUsed;
+ PAIR_ID id = makeFreePairId (ic, &isUsed);
+ if (isUsed)
+ _push (id);
/* Can't load into parts, so load into HL then exchange. */
- emit2 ("ld %s,%s", _pairs[PAIR_HL].l, aopGet (aop, offset, FALSE));
- emit2 ("ld %s,%s", _pairs[PAIR_HL].h, aopGet (aop, offset + 1, FALSE));
- emit2 ("push hl");
+ emit2 ("ld %s,%s", _pairs[id].l, aopGet (aop, offset, FALSE));
+ emit2 ("ld %s,%s", _pairs[id].h, aopGet (aop, offset + 1, FALSE));
+ emit2 ("push %s", _pairs[id].name);
emit2 ("pop iy");
- _pop (PAIR_HL);
+ if (isUsed)
+ _pop (id);
}
}
- else {
+ else
+ {
emit2 ("ld %s,%s", _pairs[pairId].l, aopGet (aop, offset, FALSE));
emit2 ("ld %s,%s", _pairs[pairId].h, aopGet (aop, offset + 1, FALSE));
- }
+ }
/* PENDING: check? */
if (pairId == PAIR_HL)
spillPair (PAIR_HL);
static void
fetchPair (PAIR_ID pairId, asmop * aop)
{
- fetchPairLong (pairId, aop, 0);
+ fetchPairLong (pairId, aop, NULL, 0);
}
static void
static const char *
aopGet (asmop * aop, int offset, bool bit16)
{
- char *s = buffer;
+ // char *s = buffer;
/* offset is greater than size then zero */
/* PENDING: this seems a bit screwed in some pointer cases. */
if (offset > (aop->size - 1) &&
aop->type != AOP_LIT)
{
- tsprintf (s, "!zero");
- return traceAlloc(&_G.trace.aops, Safe_strdup(s));
+ tsprintf (buffer, sizeof(buffer), "!zero");
+ return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
}
/* depending on type */
case AOP_IMMD:
/* PENDING: re-target */
if (bit16)
- tsprintf (s, "!immedwords", aop->aopu.aop_immd);
+ tsprintf (buffer, sizeof(buffer), "!immedwords", aop->aopu.aop_immd);
else
switch (offset)
{
case 2:
- tsprintf (s, "!bankimmeds", aop->aopu.aop_immd);
+ tsprintf (buffer, sizeof(buffer), "!bankimmeds", aop->aopu.aop_immd);
break;
case 1:
- tsprintf (s, "!msbimmeds", aop->aopu.aop_immd);
+ tsprintf (buffer, sizeof(buffer), "!msbimmeds", aop->aopu.aop_immd);
break;
case 0:
- tsprintf (s, "!lsbimmeds", aop->aopu.aop_immd);
+ tsprintf (buffer, sizeof(buffer), "!lsbimmeds", aop->aopu.aop_immd);
break;
default:
wassertl (0, "Fetching from beyond the limits of an immediate value.");
}
- return traceAlloc(&_G.trace.aops, Safe_strdup(s));
+ return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
case AOP_DIR:
wassert (IS_GB);
emit2 ("ld a,(%s+%d)", aop->aopu.aop_dir, offset);
- sprintf (s, "a");
+ SNPRINTF (buffer, sizeof(buffer), "a");
- return traceAlloc(&_G.trace.aops, Safe_strdup(s));
+ return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
case AOP_SFR:
wassert (IS_GB);
emit2 ("ldh a,(%s+%d)", aop->aopu.aop_dir, offset);
- sprintf (s, "a");
+ SNPRINTF (buffer, sizeof(buffer), "a");
- return traceAlloc(&_G.trace.aops, Safe_strdup(s));
+ return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
case AOP_REG:
return aop->aopu.aop_reg[offset]->name;
case AOP_HL:
wassert (IS_GB);
setupPair (PAIR_HL, aop, offset);
- tsprintf (s, "!*hl");
+ tsprintf (buffer, sizeof(buffer), "!*hl");
- return traceAlloc(&_G.trace.aops, Safe_strdup (s));
+ return traceAlloc(&_G.trace.aops, Safe_strdup (buffer));
case AOP_IY:
wassert (IS_Z80);
setupPair (PAIR_IY, aop, offset);
- tsprintf (s, "!*iyx", offset);
+ tsprintf (buffer, sizeof(buffer), "!*iyx", offset);
- return traceAlloc(&_G.trace.aops, Safe_strdup(s));
+ return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
case AOP_EXSTK:
wassert (IS_Z80);
setupPair (PAIR_IY, aop, offset);
- tsprintf (s, "!*iyx", offset, offset);
+ tsprintf (buffer, sizeof(buffer), "!*iyx", offset, offset);
- return traceAlloc(&_G.trace.aops, Safe_strdup(s));
+ return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
case AOP_STK:
if (IS_GB)
{
setupPair (PAIR_HL, aop, offset);
- tsprintf (s, "!*hl");
+ tsprintf (buffer, sizeof(buffer), "!*hl");
}
else
{
if (aop->aopu.aop_stk >= 0)
offset += _G.stack.param_offset;
- tsprintf (s, "!*ixx", aop->aopu.aop_stk + offset);
+ tsprintf (buffer, sizeof(buffer),
+ "!*ixx", aop->aopu.aop_stk + offset);
}
- return traceAlloc(&_G.trace.aops, Safe_strdup(s));
+ return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
case AOP_CRY:
wassertl (0, "Tried to fetch from a bit variable");
}
else
{
- tsprintf(s, "!zero");
- return traceAlloc(&_G.trace.aops, Safe_strdup(s));
+ tsprintf(buffer, sizeof(buffer), "!zero");
+ return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
}
case AOP_HLREG:
unsigned long v = aop->aopu.aop_simplelit;
v >>= (offset * 8);
- tsprintf (s, "!immedbyte", (unsigned int) v & 0xff);
+ tsprintf (buffer, sizeof(buffer),
+ "!immedbyte", (unsigned int) v & 0xff);
- return traceAlloc(&_G.trace.aops, Safe_strdup(s));
+ return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
}
case AOP_STR:
aop->coff = offset;
case AOP_PAIRPTR:
setupPair (aop->aopu.aop_pairId, aop, offset);
- sprintf (s, "(%s)", _pairs[aop->aopu.aop_pairId].name);
+ SNPRINTF (buffer, sizeof(buffer),
+ "(%s)", _pairs[aop->aopu.aop_pairId].name);
- return traceAlloc(&_G.trace.aops, Safe_strdup(s));
+ return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
default:
break;
}
// PENDING
- tsprintf(buffer2, s);
+ tsprintf(buffer2, sizeof(buffer2), s);
s = buffer2;
/* will assign value to value */
/* if bit variable */
if (!aop->aopu.aop_dir)
{
- emit2 ("ld a,#0");
+ emit2 ("ld a,!zero");
emit2 ("rla");
}
else
emit2 ("ld a,%s", aopGet (AOP (left), LSB, FALSE));
emit2 ("ld h,%s", aopGet (AOP (left), MSB16, FALSE));
emit2 ("ld l,a");
+ spillPair (PAIR_HL);
}
else if ( getPairId ( AOP (result)) == PAIR_IY)
{
aopPut ( AOP (IC_RESULT (ic)), "a", MSB16);
aopPut ( AOP (IC_RESULT (ic)), "e", LSB);
- fetchPairLong (PAIR_DE, left, MSB24);
+ fetchPairLong (PAIR_DE, left, NULL, MSB24);
aopGet (right, MSB24, FALSE);
_pop (PAIR_AF);
}
if (size == 4)
{
- fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), 2);
+ fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), ic, 2);
emit2 ("push hl");
spillPair (PAIR_HL);
_G.stack.pushed += 2;
- fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), 0);
+ fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), ic, 0);
emit2 ("push hl");
spillPair (PAIR_HL);
_G.stack.pushed += 2;
spillCached ();
if (i > 8)
{
- emit2 ("ld iy,#%d", i);
+ emit2 ("ld iy,!immedword", i);
emit2 ("add iy,sp");
emit2 ("ld sp,iy");
}
symbol *sym = OP_SYMBOL (IC_LEFT (ic));
sym_link *ftype;
-#if CALLEE_SAVES
bool bcInUse = FALSE;
bool deInUse = FALSE;
-#endif
setArea (IFFUNC_NONBANKED (sym->type));
/* Create the function header */
emit2 ("!functionheader", sym->name);
- /* PENDING: portability. */
- emit2 ("__%s_start:", sym->rname);
+ sprintf (buffer, "%s_start", sym->rname);
+ emit2 ("!labeldef", buffer);
emit2 ("!functionlabeldef", sym->rname);
if (options.profile)
_G.stack.param_offset = 0;
-#if CALLEE_SAVES
+ if (z80_opts.calleeSavesBC)
+ {
+ bcInUse = TRUE;
+ }
+
/* Detect which registers are used. */
- if (sym->regsUsed)
+ if (IFFUNC_CALLEESAVES(sym->type) && sym->regsUsed)
{
int i;
for (i = 0; i < sym->regsUsed->size; i++)
_G.stack.param_offset += 2;
}
- _G.stack.pushedBC = bcInUse;
+ _G.calleeSaves.pushedBC = bcInUse;
if (deInUse)
{
_G.stack.param_offset += 2;
}
- _G.stack.pushedDE = deInUse;
-#endif
+ _G.calleeSaves.pushedDE = deInUse;
/* adjust the stack for the function */
_G.stack.last = sym->stack;
emit2 ("!leave");
}
-#if CALLEE_SAVES
- if (_G.stack.pushedDE)
+ if (_G.calleeSaves.pushedDE)
{
emit2 ("pop de");
- _G.stack.pushedDE = FALSE;
+ _G.calleeSaves.pushedDE = FALSE;
}
- if (_G.stack.pushedDE)
+ if (_G.calleeSaves.pushedBC)
{
emit2 ("pop bc");
- _G.stack.pushedDE = FALSE;
+ _G.calleeSaves.pushedBC = FALSE;
}
-#endif
if (options.profile)
{
/* Both baned and non-banked just ret */
emit2 ("ret");
- /* PENDING: portability. */
- emit2 ("__%s_end:", sym->rname);
+ sprintf (buffer, "%s_end", sym->rname);
+ emit2 ("!labeldef", buffer);
}
_G.flushStatics = 1;
_G.stack.pushed = 0;
if (IS_GB && size == 4 && requiresHL (AOP (IC_LEFT (ic))))
{
fetchPair (PAIR_DE, AOP (IC_LEFT (ic)));
- fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), 2);
+ fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), ic, 2);
}
else
{
if (isPair (AOP (IC_RIGHT (ic))) && AOP_TYPE (IC_LEFT (ic)) == AOP_IMMD && getPairId (AOP (IC_RIGHT (ic))) != PAIR_HL)
{
fetchPair (PAIR_HL, AOP (IC_LEFT (ic)));
- emit2 ("add hl,%s ; 2", getPairName (AOP (IC_RIGHT (ic))));
+ emit2 ("add hl,%s", getPairName (AOP (IC_RIGHT (ic))));
spillCached();
commitPair ( AOP (IC_RESULT (ic)), PAIR_HL);
goto release;
// wassertl (val > 0, "Multiply must be positive");
wassertl (val != 1, "Can't multiply by 1");
- if (IS_Z80) {
+ if (IS_Z80 && isPairInUseNotInRet (PAIR_DE, ic)) {
_push (PAIR_DE);
+ _G.stack.pushedDE = TRUE;
}
if ( AOP_SIZE (IC_LEFT (ic)) == 1 && !SPEC_USIGN (getSpec (operandType ( IC_LEFT (ic)))))
spillCached();
- if (IS_Z80)
+ if (IS_Z80 && _G.stack.pushedDE)
{
_pop (PAIR_DE);
+ _G.stack.pushedDE = FALSE;
}
commitPair ( AOP (IC_RESULT (ic)), PAIR_HL);
// Save the flags
emit2 ("push af");
emit2 ("ld a,(de)");
- emit2 ("xor #0x80");
+ emit2 ("xor !immedbyte", 0x80);
emit2 ("ld e,a");
emit2 ("ld a,(hl)");
- emit2 ("xor #0x80");
+ emit2 ("xor !immedbyte", 0x80);
emit2 ("ld d,a");
emit2 ("pop af");
emit2 ("ld a,e");
// Save the flags
emit2 ("push af");
emit2 ("ld a,(hl)");
- emit2 ("xor #0x80");
+ emit2 ("xor !immedbyte", 0x80);
emit2 ("ld l,a");
emit2 ("ld a,%d(iy)", offset);
- emit2 ("xor #0x80");
+ emit2 ("xor !immedbyte", 0x80);
emit2 ("ld h,a");
emit2 ("pop af");
emit2 ("ld a,l");
movLeft2Result (left, offl, result, offr, 0);
movLeft2Result (left, offl + 1, result, offr + 1, 0);
}
- /* PENDING: for now just see if it'll work. */
- /*if (AOP(result)->type == AOP_REG) { */
- {
+
+ if (getPairId (AOP (result)) == PAIR_HL)
+ {
+ while (shCount--)
+ {
+ emit2 ("add hl,hl");
+ }
+ }
+ else
+ {
int size = 2;
int offset = 0;
symbol *tlbl, *tlbl1;
tlbl = newiTempLabel (NULL);
tlbl1 = newiTempLabel (NULL);
- /* Left is already in result - so now do the shift */
- if (shCount > 1)
+ if (AOP (result)->type == AOP_REG)
{
- emit2 ("ld a,!immedbyte+1", shCount);
- emit2 ("!shortjp !tlabel", tlbl1->key + 100);
- emitLabel (tlbl->key + 100);
+ while (shCount--)
+ {
+ for (offset = 0; offset < size; offset++)
+ {
+ l = aopGet (AOP (result), offset, FALSE);
+
+ if (offset == 0)
+ {
+ emit2 ("sla %s", l);
+ }
+ else
+ {
+ emit2 ("rl %s", l);
+ }
+ }
+ }
}
-
- while (size--)
+ else
{
- l = aopGet (AOP (result), offset, FALSE);
-
- if (offset == 0)
- {
- emit2 ("sla %s", l);
- }
- else
- {
- emit2 ("rl %s", l);
- }
+ /* Left is already in result - so now do the shift */
+ if (shCount > 1)
+ {
+ emit2 ("ld a,!immedbyte+1", shCount);
+ emit2 ("!shortjp !tlabel", tlbl1->key + 100);
+ emitLabel (tlbl->key + 100);
+ }
- offset++;
- }
- if (shCount > 1)
- {
- emitLabel (tlbl1->key + 100);
- emit2 ("dec a");
- emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
+ while (size--)
+ {
+ l = aopGet (AOP (result), offset, FALSE);
+
+ if (offset == 0)
+ {
+ emit2 ("sla %s", l);
+ }
+ else
+ {
+ emit2 ("rl %s", l);
+ }
+
+ offset++;
+ }
+ if (shCount > 1)
+ {
+ emitLabel (tlbl1->key + 100);
+ emit2 ("dec a");
+ emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
+ }
}
}
}
wassert (0);
}
- else if (shCount >= (size * 8))
+ else if (shCount >= (size * 8)) {
+ const char *s;
+ if (!SPEC_USIGN(getSpec(operandType(left)))) {
+ _moveA(aopGet (AOP (left), 0, FALSE));
+ emit2 ("rlc a");
+ emit2 ("sbc a,a");
+ s=ACC_NAME;
+ } else {
+ s="!zero";
+ }
while (size--)
- aopPut (AOP (result), "!zero", size);
+ aopPut (AOP (result), s, size);
+ }
else
{
switch (size)
/* Just do it */
if (isPtrPair (AOP (left)))
{
- tsprintf (buffer, "!*pair", getPairName (AOP (left)));
+ tsprintf (buffer, sizeof(buffer),
+ "!*pair", getPairName (AOP (left)));
aopPut (AOP (result), buffer, 0);
}
else
goto release;
}
- if ( getPairId( AOP (left)) == PAIR_IY)
+ if (getPairId (AOP (left)) == PAIR_IY)
{
/* Just do it */
offset = 0;
while (size--)
{
char at[20];
- tsprintf (at, "!*iyx", offset);
+ tsprintf (at, sizeof(at), "!*iyx", offset);
aopPut (AOP (result), at, offset);
offset++;
}
/* if this is remateriazable */
fetchPair (pair, AOP (left));
- freeAsmop (left, NULL, ic);
-
/* if bit then unpack */
if (IS_BITVAR (retype))
{
wassert (0);
}
- else if ( getPairId( AOP (result)) == PAIR_HL)
+ else if (getPairId (AOP (result)) == PAIR_HL)
{
wassertl (size == 2, "HL must be of size 2");
emit2 ("ld a,!*hl");
emit2 ("inc hl");
emit2 ("ld h,!*hl");
emit2 ("ld l,a");
+ spillPair (PAIR_HL);
+ }
+ else if (getPairId (AOP (left)) == PAIR_HL && !isLastUse (ic, left))
+ {
+ size = AOP_SIZE (result);
+ offset = 0;
+
+ while (size--)
+ {
+ /* PENDING: make this better */
+ if (!IS_GB && AOP_TYPE (result) == AOP_REG)
+ {
+ aopPut (AOP (result), "!*hl", offset++);
+ }
+ else
+ {
+ emit2 ("ld a,!*pair", _pairs[pair].name);
+ aopPut (AOP (result), "a", offset++);
+ }
+ if (size)
+ {
+ emit2 ("inc %s", _pairs[pair].name);
+ _G.pairs[pair].offset++;
+ }
+ }
+ /* Fixup HL back down */
+ for (size = AOP_SIZE (result)-1; size; size--)
+ {
+ emit2 ("dec %s", _pairs[pair].name);
+ }
}
else
{
while (size--)
{
/* PENDING: make this better */
- if (!IS_GB && AOP (result)->type == AOP_REG)
+ if (!IS_GB &&
+ (AOP_TYPE (result) == AOP_REG || AOP_TYPE (result) == AOP_HLREG))
{
aopPut (AOP (result), "!*hl", offset++);
}
}
}
+ freeAsmop (left, NULL, ic);
+
release:
freeAsmop (result, NULL, ic);
}
}
goto release;
}
+ else if (getPairId (AOP (result)) == PAIR_HL && !isLastUse (ic, result))
+ {
+ offset = 0;
+
+ while (size--)
+ {
+ const char *l = aopGet (AOP (right), offset, FALSE);
+ if (isRegOrLit (AOP (right)) && !IS_GB)
+ {
+ emit2 ("ld !*pair,%s", _pairs[PAIR_HL].name, l);
+ }
+ else
+ {
+ _moveA (l);
+ emit2 ("ld !*pair,a", _pairs[PAIR_HL].name);
+ }
+ if (size)
+ {
+ emit2 ("inc %s", _pairs[PAIR_HL].name);
+ _G.pairs[PAIR_HL].offset++;
+ }
+ offset++;
+ }
+
+ /* Fixup HL back down */
+ for (size = AOP_SIZE (right)-1; size; size--)
+ {
+ emit2 ("dec %s", _pairs[PAIR_HL].name);
+ }
+ goto release;
+ }
/* if the operand is already in dptr
then we do nothing else we move the value to dptr */
{
/* if it has an offset then we need to compute it */
if (sym->stack > 0)
- emit2 ("ld hl,#%d+%d+%d+%d", sym->stack, _G.stack.pushed, _G.stack.offset, _G.stack.param_offset);
+ emit2 ("ld hl,!immedword", sym->stack + _G.stack.pushed + _G.stack.offset + _G.stack.param_offset);
else
- emit2 ("ld hl,#%d+%d+%d", sym->stack, _G.stack.pushed, _G.stack.offset);
+ emit2 ("ld hl,!immedword", sym->stack + _G.stack.pushed + _G.stack.offset);
emit2 ("add hl,sp");
}
else
{
- emit2 ("ld hl,#%s", sym->rname);
+ emit2 ("ld hl,!hashedstr", sym->rname);
}
commitPair (AOP (IC_RESULT (ic)), PAIR_HL);
}
if (AOP_TYPE (right) == AOP_LIT)
{
- lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
+ lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
}
if (isPair (AOP (result)))
{
- fetchPair (getPairId (AOP (result)), AOP (right));
+ fetchPairLong (getPairId (AOP (result)), AOP (right), ic, LSB);
}
else if ((size > 1) &&
(AOP_TYPE (result) != AOP_REG) &&
genCast (iCode * ic)
{
operand *result = IC_RESULT (ic);
- sym_link *ctype = operandType (IC_LEFT (ic));
+ sym_link *rtype = operandType (IC_RIGHT (ic));
operand *right = IC_RIGHT (ic);
int size, offset;
/* now depending on the sign of the destination */
size = AOP_SIZE (result) - AOP_SIZE (right);
/* Unsigned or not an integral type - right fill with zeros */
- if (SPEC_USIGN (ctype) || !IS_SPEC (ctype))
+ if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE(right)==AOP_CRY)
{
while (size--)
aopPut (AOP (result), "!zero", offset++);
/* Yes, worthwhile. */
/* Commit whatever was in the buffer. */
_rleCommit(self);
- emit2(".db -%u,0x%02X", self->runLen, self->last);
+ emit2("!db !immed-%u,!immedbyte", self->runLen, self->last);
}
else
{
/* Commit whatever was in the buffer. */
_rleCommit(self);
- emit2 (".db -%u,0x%02X", self->runLen, self->last);
+ emit2 ("!db !immed-%u,!immedbyte", self->runLen, self->last);
self->runLen = 0;
}
self->runLen++;
genBuiltInMemcpy (iCode *ic, int nParams, operand **pparams)
{
operand *from, *to, *count;
- symbol *label;
bool deInUse;
- iCode *pcall;
wassertl (nParams == 3, "Built-in memcpy must have two parameters");
to = pparams[2];
if (cln != ic->lineno)
{
- emit2 ("; %s %d", ic->filename, ic->lineno);
+ if (!options.noCcodeInAsm) {
+ emit2 (";%s:%d: %s", ic->filename, ic->lineno,
+ printCLine(ic->filename, ic->lineno));
+ }
cln = ic->lineno;
}
+ if (options.iCodeInAsm) {
+ emit2 (";ic:%d: %s", ic->key, printILine(ic));
+ }
/* if the result is marked as
spilt and rematerializable or code for
this has already been generated then
v = 0-v;
v &= 0xFFFF;
- tsprintf (buffer, "!immedword", v);
+ tsprintf (buffer, sizeof(buffer), "!immedword", v);
return traceAlloc(&_G.trace.aops, Safe_strdup (buffer));
}