Better reg packing, first peephole 20038 163 1873
With assign packing 19281 165 1849
5/3/00 17741 185 17B6
+ With reg params for mul and div 16234 202 162D
Michael Hope <michaelh@earthling.net> 2000
- Based on the mcs51 generator - Sandeep Dutta . sandeep.dutta@usa.net (1998)
- and - Jean-Louis VERN.jlvern@writeme.com (1999)
+ Based on the mcs51 generator -
+ Sandeep Dutta . sandeep.dutta@usa.net (1998)
+ and - Jean-Louis VERN.jlvern@writeme.com (1999)
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
struct {
int last;
int pushed;
+ int param_offset;
int offset;
+ int pushed_bc;
+ int pushed_de;
} stack;
int frameId;
+ bool flush_statics;
+ bool in_home;
} _G;
static char *aopGet(asmop *aop, int offset, bool bit16);
static asmop *aopForSym (iCode *ic,symbol *sym,bool result, bool requires_a)
{
asmop *aop;
- memmap *space= SPEC_OCLS(sym->etype);
+ memmap *space;
+
+ wassert(ic);
+ wassert(sym);
+ wassert(sym->etype);
+
+ space = SPEC_OCLS(sym->etype);
/* if already has one */
if (sym->aop)
/* if this is a true symbol */
if (IS_TRUE_SYMOP(op)) {
- op->aop = aopForSym(ic,OP_SYMBOL(op),result, requires_a);
+ op->aop = aopForSym(ic, OP_SYMBOL(op), result, requires_a);
return ;
}
/* otherwise it is fairly simple */
if (!IS_FLOAT(val->type)) {
unsigned long v = floatFromVal(val);
+
if (offset == 2)
v >>= 16;
+
if (with_hash)
tsprintf(buffer, "!immedword", v);
else
}
}
+static char *fetchLitSpecial(asmop *aop, bool negate, bool xor)
+{
+ unsigned long v;
+ value * val = aop->aopu.aop_lit;
+
+ wassert(aop->type == AOP_LIT);
+ wassert(!IS_FLOAT(val->type));
+
+ v = floatFromVal(val);
+
+ if (xor)
+ v ^= 0x8000;
+ if (negate)
+ v = -v;
+ v &= 0xFFFF;
+
+ tsprintf(buffer, "!immedword", v);
+ return gc_strdup(buffer);
+}
+
static void fetchLitPair(PAIR_ID pairId, asmop *left, int offset)
{
const char *l;
const char *pair = _pairs[pairId].name;
- l = aopGetLitWordLong(left, offset, FALSE);
+ l = aopGetLitWordLong(left, 0, FALSE);
wassert(l && pair);
if (isPtr(pair)) {
_G.pairs[pairId].lit = gc_strdup(l);
_G.pairs[pairId].offset = offset;
}
+ if (IS_GB && pairId == PAIR_DE && 0) {
+ if (_G.pairs[pairId].lit && !strcmp(_G.pairs[pairId].lit, l)) {
+ if (abs(_G.pairs[pairId].offset - offset) < 3) {
+ adjustPair(pair, &_G.pairs[pairId].offset, offset);
+ return;
+ }
+ }
+ _G.pairs[pairId].last_type = left->type;
+ _G.pairs[pairId].lit = gc_strdup(l);
+ _G.pairs[pairId].offset = offset;
+ }
/* Both a lit on the right and a true symbol on the left */
- /* PENDING: for re-target */
-#if 0
if (offset)
- emit2("ld %s,!hashedstr + %d", pair, l, offset);
- else
-#endif
+ emit2("ld %s,!hashedstr + %u", pair, l, offset);
+ else
emit2("ld %s,!hashedstr", pair, l);
}
else { /* we need to get it byte by byte */
if (pairId == PAIR_HL && IS_GB && requiresHL(aop)) {
aopGet(aop, offset, FALSE);
- emit2("!ldahli");
- emit2("ld h,!*hl");
- emit2("ld l,a");
+ switch (aop->size) {
+ case 1:
+ emit2("ld l,!*hl");
+ emit2("ld h,!immedbyte", 0);
+ break;
+ case 2:
+ emit2("!ldahli");
+ emit2("ld h,!*hl");
+ emit2("ld l,a");
+ break;
+ default:
+ emit2("; WARNING: mlh woosed out. This code is invalid.");
+ }
}
else if (IS_Z80 && aop->type == AOP_IY) {
/* Instead of fetching relative to IY, just grab directly
case AOP_STK: {
/* Doesnt include _G.stack.pushed */
int abso = aop->aopu.aop_stk + offset + _G.stack.offset;
+ if (aop->aopu.aop_stk > 0) {
+ abso += _G.stack.param_offset;
+ }
assert(pairId == PAIR_HL);
/* In some cases we can still inc or dec hl */
if (_G.pairs[pairId].last_type == AOP_STK && abs(_G.pairs[pairId].offset - abso) < 3) {
adjustPair(_pairs[pairId].name, &_G.pairs[pairId].offset, abso);
}
else {
- emit2("!ldahlsp", aop->aopu.aop_stk+offset + _G.stack.pushed + _G.stack.offset);
+ emit2("!ldahlsp", abso +_G.stack.pushed);
}
_G.pairs[pairId].offset = abso;
break;
if (bit16)
tsprintf (s,"!immedwords", aop->aopu.aop_immd);
else
- if (offset) {
- wassert(offset == 1);
+ switch (offset) {
+ case 2:
+ tsprintf(s, "!bankimmeds", aop->aopu.aop_immd);
+ break;
+ case 1:
+ tsprintf(s, "!msbimmeds", aop->aopu.aop_immd);
+ break;
+ case 0:
tsprintf(s, "!lsbimmeds", aop->aopu.aop_immd);
+ break;
+ default:
+ wassert(0);
}
- else
- tsprintf(s, "!msbimmeds", aop->aopu.aop_immd);
ALLOC_ATOMIC(rs,strlen(s)+1);
strcpy(rs,s);
return rs;
tsprintf(s, "!*hl");
}
else {
- tsprintf(s,"!*ixx", aop->aopu.aop_stk+offset);
+ if (aop->aopu.aop_stk >= 0)
+ offset += _G.stack.param_offset;
+ tsprintf(s,"!*ixx ; x", aop->aopu.aop_stk+offset);
}
ALLOC_ATOMIC(rs,strlen(s)+1);
strcpy(rs,s);
exit(0);
}
-bool isRegString(char *s)
+bool isRegString(const char *s)
{
if (!strcmp(s, "b") ||
!strcmp(s, "c") ||
return (*s == '#' || *s == '$');
}
-bool canAssignToPtr(char *s)
+bool canAssignToPtr(const char *s)
{
if (isRegString(s))
return TRUE;
/*-----------------------------------------------------------------*/
/* aopPut - puts a string for a aop */
/*-----------------------------------------------------------------*/
-static void aopPut (asmop *aop, char *s, int offset)
+static void aopPut (asmop *aop, const char *s, int offset)
{
if (aop->size && offset > ( aop->size - 1)) {
werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
emit2("ld !*hl,a");
}
else
- emit2("ld !*hl,%s ; 3", s);
+ emit2("ld !*hl,%s", s);
}
else {
+ if (aop->aopu.aop_stk >= 0)
+ offset += _G.stack.param_offset;
if (!canAssignToPtr(s)) {
emit2("ld a,%s", s);
emit2("ld !*ixx,a", aop->aopu.aop_stk+offset);
#define AOP_SIZE(op) AOP(op)->size
#define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY))
+static void commitPair(asmop *aop, PAIR_ID id)
+{
+ if (id == PAIR_HL && requiresHL(aop)) {
+ emit2("ld a,l");
+ emit2("ld d,h");
+ aopPut(aop, "a", 0);
+ aopPut(aop, "d", 1);
+ }
+ else {
+ aopPut(aop, _pairs[id].l, 0);
+ aopPut(aop, _pairs[id].h, 1);
+ }
+}
+
/*-----------------------------------------------------------------*/
/* getDataSize - get the operand data size */
/*-----------------------------------------------------------------*/
/** Take the value in carry and put it into a register
*/
-void outBitC(operand *result)
+void outBitCLong(operand *result, bool swap_sense)
{
/* if the result is bit */
if (AOP_TYPE(result) == AOP_CRY) {
else {
emit2("ld a,!zero");
emit2("rla");
+ if (swap_sense)
+ emit2("xor a,!immedbyte", 1);
outAcc(result);
}
}
+void outBitC(operand *result)
+{
+ outBitCLong(result, FALSE);
+}
+
/*-----------------------------------------------------------------*/
/* toBoolean - emit code for orl a,operator(sizeop) */
/*-----------------------------------------------------------------*/
freeAsmop(IC_RESULT(ic),NULL,ic);
}
+static void _push(PAIR_ID pairId)
+{
+ emit2("push %s", _pairs[pairId].name);
+ _G.stack.pushed += 2;
+}
+
+static void _pop(PAIR_ID pairId)
+{
+ emit2("pop %s", _pairs[pairId].name);
+ _G.stack.pushed -= 2;
+}
+
+
/*-----------------------------------------------------------------*/
/* assignResultValue - */
/*-----------------------------------------------------------------*/
#endif
if (IS_GB && size == 4 && requiresHL(AOP(oper))) {
/* We do it the hard way here. */
- emitcode("push", "hl");
- _G.stack.pushed += 2;
+ _push(PAIR_HL);
aopPut(AOP(oper), _fReturn[0], 0);
aopPut(AOP(oper), _fReturn[1], 1);
emitcode("pop", "de");
int size, offset = 0 ;
char *l;
-
/* if this is not a parm push : ie. it is spill push
and spill push is always done on the local stack */
if (!ic->parmPush) {
freeAsmop(IC_LEFT(ic),NULL,ic);
}
+static int _isPairUsed(iCode *ic, PAIR_ID pairId)
+{
+ int ret = 0;
+ switch (pairId) {
+ case PAIR_DE:
+ if (bitVectBitValue(ic->rUsed, D_IDX))
+ ret++;
+ if (bitVectBitValue(ic->rUsed, E_IDX))
+ ret++;
+ break;
+ default:
+ wassert(0);
+ }
+ return ret;
+}
+
+static int _opUsesPair(operand *op, iCode *ic, PAIR_ID pairId)
+{
+ int ret = 0;
+ asmop *aop;
+ symbol *sym = OP_SYMBOL(op);
+
+ if (sym->isspilt || sym->nRegs == 0)
+ return 0;
+
+ aopOp(op, ic, FALSE, FALSE);
+
+ aop = AOP(op);
+ if (aop->type == AOP_REG) {
+ int i;
+ for (i=0; i < aop->size; i++) {
+ if (pairId == PAIR_DE) {
+ emit2("; name %s", aop->aopu.aop_reg[i]->name);
+ if (!strcmp(aop->aopu.aop_reg[i]->name, "e"))
+ ret++;
+ if (!strcmp(aop->aopu.aop_reg[i]->name, "d"))
+ ret++;
+ }
+ else {
+ wassert(0);
+ }
+ }
+ }
+
+ freeAsmop(IC_LEFT(ic),NULL,ic);
+ return ret;
+}
+
+/* This is quite unfortunate */
+static void setArea(int inHome)
+{
+ static int lastArea = 0;
+
+ /*
+ if (_G.in_home != inHome) {
+ if (inHome) {
+ const char *sz = port->mem.code_name;
+ port->mem.code_name = "HOME";
+ emit2("!area", CODE_NAME);
+ port->mem.code_name = sz;
+ }
+ else
+ emit2("!area", CODE_NAME);*/
+ _G.in_home = inHome;
+ // }
+}
+
+static bool isInHome(void)
+{
+ return _G.in_home;
+}
+
/** Emit the code for a call statement
*/
-static void emitCall (iCode *ic, bool ispcall)
+static void emitCall(iCode *ic, bool ispcall)
{
+ int pushed_de = 0;
+ link *detype = getSpec(operandType(IC_LEFT(ic)));
+
/* if caller saves & we have not saved then */
if (!ic->regsSaved) {
/* PENDING */
}
-
+
/* if send set is not empty then assign */
if (sendSet) {
- iCode *sic ;
- for (sic = setFirstItem(sendSet) ; sic ;
- sic = setNextItem(sendSet)) {
- int size, offset = 0;
- aopOp(IC_LEFT(sic),sic,FALSE, FALSE);
- size = AOP_SIZE(IC_LEFT(sic));
- while (size--) {
- char *l = aopGet(AOP(IC_LEFT(sic)),offset,
- FALSE);
- if (strcmp(l, _fReturn[offset]))
- emitcode("ld","%s,%s",
- _fReturn[offset],
- l);
- offset++;
+ iCode *sic;
+ int send = 0;
+ int n = elementsInSet(sendSet);
+ if (IS_Z80 && n == 2 && _isPairUsed(ic, PAIR_DE)) {
+ /* Only push de if it is used and if it's not used
+ in the return value */
+ /* Panic if partly used */
+ if (_opUsesPair(IC_RESULT(ic), ic, PAIR_DE) == 1) {
+ emit2("; Warning: de crossover");
}
+ else if (!_opUsesPair(IC_RESULT(ic), ic, PAIR_DE)) {
+ /* Store away de */
+ _push(PAIR_DE);
+ pushed_de = 1;
+ }
+ }
+ /* PENDING: HACK */
+ if (IS_Z80 && n == 2 ) {
+ /* Want to load HL first, then DE as HL may = DE */
+ sic = setFirstItem(sendSet);
+ sic = setNextItem(sendSet);
+ aopOp(IC_LEFT(sic),sic,FALSE, FALSE);
+ fetchPair(PAIR_HL, AOP(IC_LEFT(sic)));
+ send++;
freeAsmop (IC_LEFT(sic),NULL,sic);
+ sic = setFirstItem(sendSet);
+ aopOp(IC_LEFT(sic),sic,FALSE, FALSE);
+ fetchPair(PAIR_DE, AOP(IC_LEFT(sic)));
+ send++;
+ freeAsmop (IC_LEFT(sic),NULL,sic);
+ }
+ else {
+ for (sic = setFirstItem(sendSet) ; sic ;
+ sic = setNextItem(sendSet)) {
+ int size;
+ aopOp(IC_LEFT(sic),sic,FALSE, FALSE);
+ size = AOP_SIZE(IC_LEFT(sic));
+ wassert(size <= 2);
+ /* Always send in pairs */
+ switch (send) {
+ case 0:
+ if (IS_Z80 && n == 1)
+ fetchPair(PAIR_HL, AOP(IC_LEFT(sic)));
+ else
+ fetchPair(PAIR_DE, AOP(IC_LEFT(sic)));
+ break;
+ case 1:
+ fetchPair(PAIR_HL, AOP(IC_LEFT(sic)));
+ break;
+ default:
+ /* Send set too big */
+ wassert(0);
+ }
+ send++;
+ freeAsmop (IC_LEFT(sic),NULL,sic);
+ }
}
sendSet = NULL;
+ if (pushed_de) {
+ }
}
if (ispcall) {
+ if (IS_BANKEDCALL(detype)) {
+ werror(W_INDIR_BANKED);
+ }
aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
if (isLitWord(AOP(IC_LEFT(ic)))) {
else {
symbol *rlbl = newiTempLabel(NULL);
spillPair(PAIR_HL);
- emit2("ld hl,#!tlabel", (rlbl->key+100));
+ emit2("ld hl,!immed!tlabel", (rlbl->key+100));
emitcode("push", "hl");
_G.stack.pushed += 2;
freeAsmop(IC_LEFT(ic),NULL,ic);
}
else {
- /* make the call */
char *name = OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
OP_SYMBOL(IC_LEFT(ic))->rname :
OP_SYMBOL(IC_LEFT(ic))->name;
- emitcode("call", "%s", name);
+ if (IS_BANKEDCALL(detype)) {
+ emit2("call banked_call");
+ emit2("!dws", name);
+ emit2("!dw !bankimmeds", name);
+ }
+ else {
+ /* make the call */
+ emit2("call %s", name);
+ }
}
spillCached();
spillCached();
}
}
-
+ if (pushed_de)
+ _pop(PAIR_DE);
}
/*-----------------------------------------------------------------*/
/*-----------------------------------------------------------------*/
static void genCall (iCode *ic)
{
+ link *detype = getSpec(operandType(IC_LEFT(ic)));
emitCall(ic, FALSE);
}
return 0;
}
+extern set *publics;
+
/*-----------------------------------------------------------------*/
/* genFunction - generated code for function entry */
/*-----------------------------------------------------------------*/
link *fetype;
nregssaved = 0;
+ setArea(IS_NONBANKED(sym->etype));
+
+ /* PENDING: hack */
+ if (!IS_STATIC(sym->etype)) {
+ addSetIfnotP(&publics, sym);
+ }
+
/* create the function header */
emit2("!functionheader", sym->name);
/* PENDING: portability. */
emit2("__%s_start:", sym->rname);
emit2("!functionlabeldef", sym->rname);
-
+
fetype = getSpec(operandType(IC_LEFT(ic)));
-
+
/* if critical function then turn interrupts off */
if (SPEC_CRTCL(fetype))
emit2("!di");
}
/* PENDING: callee-save etc */
+ /* If BC or DE are used, then push */
+ _G.stack.pushed_bc = 0;
+ _G.stack.pushed_de = 0;
+ _G.stack.param_offset = 0;
+ if (sym->regsUsed) {
+ int i;
+ for ( i = 0 ; i < sym->regsUsed->size ; i++) {
+ if (bitVectBitValue(sym->regsUsed, i)) {
+ switch (i) {
+ case C_IDX:
+ case B_IDX:
+ _G.stack.pushed_bc = 1;
+ break;
+ case D_IDX:
+ case E_IDX:
+ if (IS_Z80)
+ _G.stack.pushed_de = 1;
+ break;
+ }
+ }
+ }
+ if (_G.stack.pushed_bc) {
+ emit2("push bc");
+ _G.stack.param_offset += 2;
+ }
+ if (_G.stack.pushed_de) {
+ emit2("push de");
+ _G.stack.param_offset += 2;
+ }
+ }
+
/* adjust the stack for the function */
_G.stack.last = sym->stack;
emit2("!leavex", _G.stack.offset);
else
emit2("!leave");
+
+ if (_G.stack.pushed_de)
+ emit2("pop de");
+ if (_G.stack.pushed_bc)
+ emit2("pop bc");
+ /* Both baned and non-banked just ret */
+ emit2("ret");
+
/* PENDING: portability. */
emit2("__%s_end:", sym->rname);
}
+ _G.flush_statics = 1;
_G.stack.pushed = 0;
_G.stack.offset = 0;
}
if (genPlusIncr (ic) == TRUE)
goto release;
+ emit2("; genPlusIncr failed");
+
size = getDataSize(IC_RESULT(ic));
/* Special case when left and right are constant */
goto release;
}
+ /* Special case:
+ ld hl,sp+n trashes C so we cant afford to do it during an
+ add with stack based varibles. Worst case is:
+ ld hl,sp+left
+ ld a,(hl)
+ ld hl,sp+right
+ add (hl)
+ ld hl,sp+result
+ ld (hl),a
+ ld hl,sp+left+1
+ ld a,(hl)
+ ld hl,sp+right+1
+ adc (hl)
+ ld hl,sp+result+1
+ ld (hl),a
+ So you cant afford to load up hl if either left, right, or result
+ is on the stack (*sigh*) The alt is:
+ ld hl,sp+left
+ ld de,(hl)
+ ld hl,sp+right
+ ld hl,(hl)
+ add hl,de
+ ld hl,sp+result
+ ld (hl),hl
+ Combinations in here are:
+ * If left or right are in bc then the loss is small - trap later
+ * If the result is in bc then the loss is also small
+ */
+ if (IS_GB) {
+ if (AOP_TYPE(IC_LEFT(ic)) == AOP_STK ||
+ AOP_TYPE(IC_RIGHT(ic)) == AOP_STK ||
+ AOP_TYPE(IC_RESULT(ic)) == AOP_STK) {
+ if ((AOP_SIZE(IC_LEFT(ic)) == 2 ||
+ AOP_SIZE(IC_RIGHT(ic)) == 2) &&
+ (AOP_SIZE(IC_LEFT(ic)) <= 2 &&
+ AOP_SIZE(IC_RIGHT(ic)) <= 2)) {
+ if (getPairId(AOP(IC_RIGHT(ic))) == PAIR_BC) {
+ /* Swap left and right */
+ operand *t = IC_RIGHT(ic);
+ IC_RIGHT(ic) = IC_LEFT(ic);
+ IC_LEFT(ic) = t;
+ }
+ if (getPairId(AOP(IC_LEFT(ic))) == PAIR_BC) {
+ fetchPair(PAIR_HL, AOP(IC_RIGHT(ic)));
+ emit2("add hl,bc");
+ }
+ else {
+ fetchPair(PAIR_DE, AOP(IC_LEFT(ic)));
+ fetchPair(PAIR_HL, AOP(IC_RIGHT(ic)));
+ emit2("add hl,de");
+ }
+ commitPair(AOP(IC_RESULT(ic)), PAIR_HL);
+ goto release;
+ }
+ else if (size == 4) {
+ emit2("; WARNING: This add is probably broken.\n");
+ }
+ }
+ }
+
while(size--) {
if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
if(offset == 0)
- emitcode("add","a,%s",
- aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
+ emit2("add a,%s",
+ aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
else
- emitcode("adc","a,%s",
- aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
+ emit2("adc a,%s",
+ aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
} else {
MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
if(offset == 0)
- emitcode("add","a,%s",
- aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
+ emit2("add a,%s",
+ aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
else
- emitcode("adc","a,%s",
- aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
+ emit2("adc a,%s",
+ aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
}
- aopPut(AOP(IC_RESULT(ic)),"a",offset++);
+ aopPut(AOP(IC_RESULT(ic)),"a",offset++);
}
-
- /* Some kind of pointer arith. */
- if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
- AOP_SIZE(IC_LEFT(ic)) == 3 &&
- !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
- wassert(0);
-
- if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
- AOP_SIZE(IC_RIGHT(ic)) == 3 &&
- !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
- wassert(0);
-
release:
freeAsmop(IC_LEFT(ic),NULL,ic);
lit = - (long)lit;
}
-
+ /* Same logic as genPlus */
+ if (IS_GB) {
+ if (AOP_TYPE(IC_LEFT(ic)) == AOP_STK ||
+ AOP_TYPE(IC_RIGHT(ic)) == AOP_STK ||
+ AOP_TYPE(IC_RESULT(ic)) == AOP_STK) {
+ if ((AOP_SIZE(IC_LEFT(ic)) == 2 ||
+ AOP_SIZE(IC_RIGHT(ic)) == 2) &&
+ (AOP_SIZE(IC_LEFT(ic)) <= 2 &&
+ AOP_SIZE(IC_RIGHT(ic)) <= 2)) {
+ PAIR_ID left = getPairId(AOP(IC_LEFT(ic)));
+ PAIR_ID right = getPairId(AOP(IC_RIGHT(ic)));
+
+ if (left == PAIR_INVALID && right == PAIR_INVALID) {
+ left = PAIR_DE;
+ right = PAIR_HL;
+ }
+ else if (right == PAIR_INVALID)
+ right = PAIR_DE;
+ else if (left == PAIR_INVALID)
+ left = PAIR_DE;
+
+ fetchPair(left, AOP(IC_LEFT(ic)));
+ /* Order is important. Right may be HL */
+ fetchPair(right, AOP(IC_RIGHT(ic)));
+
+ emit2("ld a,%s", _pairs[left].l);
+ emit2("sub a,%s", _pairs[right].l);
+ emit2("ld e,a");
+ emit2("ld a,%s", _pairs[left].h);
+ emit2("sbc a,%s", _pairs[right].h);
+
+ aopPut(AOP(IC_RESULT(ic)), "a", 1);
+ aopPut(AOP(IC_RESULT(ic)), "e", 0);
+ goto release;
+ }
+ else if (size == 4) {
+ emit2("; WARNING: This sub is probably broken.\n");
+ }
+ }
+ }
+
/* if literal, add a,#-lit, else normal subb */
while (size--) {
MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
/* if true label then we jump if condition
supplied is true */
- if ( IC_TRUE(ic) ) {
+ if (IC_TRUE(ic)) {
jlbl = IC_TRUE(ic);
if (!strcmp(jval, "a")) {
inst = "nz";
else if (!strcmp(jval, "c")) {
inst = "c";
}
+ else if (!strcmp(jval, "nc")) {
+ inst = "nc";
+ }
else {
/* The buffer contains the bit on A that we should test */
inst = "nz";
else if (!strcmp(jval, "c")) {
inst = "nc";
}
+ else if (!strcmp(jval, "nc")) {
+ inst = "c";
+ }
else {
/* The buffer contains the bit on A that we should test */
inst = "z";
}
else if (!strcmp(jval, "c")) {
}
+ else if (!strcmp(jval, "nc")) {
+ }
else {
emitcode("bit", "%s,a", jval);
}
ic->generated = 1;
}
+static const char *_getPairIdName(PAIR_ID id)
+{
+ return _pairs[id].name;
+}
+
/** Generic compare for > or <
*/
static void genCmp (operand *left,operand *right,
{
int size, offset = 0 ;
unsigned long lit = 0L;
+ bool swap_sense = FALSE;
/* if left & right are bit variables */
if (AOP_TYPE(left) == AOP_CRY &&
emitcode("cp", "%s", aopGet(AOP(right), offset, FALSE));
}
else {
+ /* Special cases:
+ On the GB:
+ If the left or the right is a lit:
+ Load -lit into HL, add to right via, check sense.
+ */
+ if (size == 2 && (AOP_TYPE(right) == AOP_LIT || AOP_TYPE(left) == AOP_LIT)) {
+ PAIR_ID id = PAIR_DE;
+ asmop *lit = AOP(right);
+ asmop *op = AOP(left);
+ swap_sense = TRUE;
+
+ if (AOP_TYPE(left) == AOP_LIT) {
+ swap_sense = FALSE;
+ lit = AOP(left);
+ op = AOP(right);
+ }
+ if (sign) {
+ emit2("ld e,%s", aopGet(op, 0, 0));
+ emit2("ld a,%s", aopGet(op, 1, 0));
+ emit2("xor a,!immedbyte", 0x80);
+ emit2("ld d,a");
+ }
+ else {
+ id = getPairId(op);
+ if (id == PAIR_INVALID) {
+ fetchPair(PAIR_DE, op);
+ id = PAIR_DE;
+ }
+ }
+ spillPair(PAIR_HL);
+ emit2("ld hl,%s", fetchLitSpecial(lit, TRUE, sign));
+ emit2("add hl,%s", _getPairIdName(id));
+ goto release;
+ }
if(AOP_TYPE(right) == AOP_LIT) {
lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
/* optimize if(x < 0) or if(x >= 0) */
release:
if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
- outBitC(result);
+ outBitCLong(result, swap_sense);
} else {
/* if the result is used in the next
ifx conditional branch then generate
code a little differently */
- if (ifx )
- genIfxJump (ifx,"c");
+ if (ifx)
+ genIfxJump(ifx, swap_sense ? "nc" : "c");
else
- outBitC(result);
+ outBitCLong(result, swap_sense);
/* leave the result in acc */
}
}
symbol *tlbl , *tlbl1;
char *l;
+ tlbl = newiTempLabel(NULL);
+ tlbl1 = newiTempLabel(NULL);
+
/* Left is already in result - so now do the shift */
if (shCount>1) {
emit2("ld a,!immedbyte+1", shCount);
- tlbl = newiTempLabel(NULL);
- tlbl1 = newiTempLabel(NULL);
emit2("!shortjp !tlabel", tlbl1->key+100);
emitLabel(tlbl->key+100);
}
symbol *tlbl , *tlbl1;
char *l;
+ tlbl = newiTempLabel(NULL);
+ tlbl1 = newiTempLabel(NULL);
+
/* Left is already in result - so now do the shift */
if (shCount>1) {
emit2("ld a,!immedbyte+1", shCount);
- tlbl = newiTempLabel(NULL);
- tlbl1 = newiTempLabel(NULL);
emit2("!shortjp !tlabel", tlbl1->key+100);
emitLabel(tlbl->key+100);
}
/*-----------------------------------------------------------------*/
static void AccLsh (int shCount)
{
- if(shCount != 0){
- if(shCount == 1)
- emitcode("add","a,a");
- else
- if(shCount == 2) {
+ if(shCount != 0) {
+ if(shCount == 1) {
emitcode("add","a,a");
- emitcode("add","a,a");
- } else {
- /* rotate left accumulator */
- AccRol(shCount);
- /* and kill the lower order bits */
- emit2("and a,!immedbyte", SLMask[shCount]);
- }
+ }
+ else if(shCount == 2) {
+ emitcode("add","a,a");
+ emitcode("add","a,a");
+ } else {
+ /* rotate left accumulator */
+ AccRol(shCount);
+ /* and kill the lower order bits */
+ emit2("and a,!immedbyte", SLMask[shCount]);
+ }
}
}
/* if shCount >= 8 */
if (shCount >= 8) {
shCount -= 8 ;
-
if (size > 1){
if (shCount) {
movLeft2Result(left, LSB, result, MSB16, 0);
aopPut(AOP(result),zero, 0);
- shiftL1Left2Result(left, MSB16, result, MSB16, shCount-8);
+ shiftL1Left2Result(left, MSB16, result, MSB16, shCount);
}
else {
movLeft2Result(left, LSB, result, MSB16, 0);
aopPut(AOP(result),zero, 0);
}
}
- aopPut(AOP(result),zero,LSB);
+ else {
+ aopPut(AOP(result),zero,LSB);
+ }
}
/* 1 <= shCount <= 7 */
else {
}
/*-----------------------------------------------------------------*/
-/* genlshTwo - left shift two bytes by known amount != 0 */
+/* genrshOne - left shift two bytes by known amount != 0 */
/*-----------------------------------------------------------------*/
static void genrshOne (operand *result,operand *left, int shCount)
{
static void AccRsh (int shCount)
{
if(shCount != 0){
- if(shCount == 1){
- CLRC;
- emitcode("rr","a");
- } else {
- /* rotate right accumulator */
- AccRol(8 - shCount);
- /* and kill the higher order bits */
- emit2("and a,!immedbyte", SRMask[shCount]);
- }
+ /* rotate right accumulator */
+ AccRol(8 - shCount);
+ /* and kill the higher order bits */
+ emit2("and a,!immedbyte", SRMask[shCount]);
}
}
{
/* if shCount >= 8 */
if (shCount >= 8) {
- shCount -= 8 ;
+ shCount -= 8;
if (shCount) {
shiftR1Left2Result(left, MSB16, result, LSB,
shCount, sign);
}
else {
movLeft2Result(left, MSB16, result, LSB, sign);
- aopPut(AOP(result),zero,1);
}
+ aopPut(AOP(result),zero,1);
}
/* 1 <= shCount <= 7 */
else {
}
/*-----------------------------------------------------------------*/
-/* genGenPointerGet - gget value from generic pointer space */
+/* genGenPointerGet - get value from generic pointer space */
/*-----------------------------------------------------------------*/
static void genGenPointerGet (operand *left,
operand *result, iCode *ic)
}
if (size) {
emit2("inc %s", _pairs[pair].name);
+ _G.pairs[pair].offset++;
}
}
}
}
if (size) {
emitcode("inc", _pairs[pairId].name);
+ _G.pairs[pairId].offset++;
}
offset++;
}
if (IS_GB) {
if (sym->onStack) {
spillCached();
- emit2("!ldahlsp", sym->stack + _G.stack.pushed + _G.stack.offset);
+ if (sym->stack <= 0) {
+ emit2("!ldahlsp", sym->stack + _G.stack.pushed + _G.stack.offset);
+ }
+ else {
+ emit2("!ldahlsp", sym->stack + _G.stack.pushed + _G.stack.offset + _G.stack.param_offset);
+ }
emitcode("ld", "d,h");
emitcode("ld", "e,l");
}
else {
- emitcode("ld", "de,#%s", sym->rname);
+ emit2("ld de,!hashedstr", sym->rname);
}
aopPut(AOP(IC_RESULT(ic)), "e", 0);
aopPut(AOP(IC_RESULT(ic)), "d", 1);
spillCached();
if (sym->onStack) {
/* if it has an offset then we need to compute it */
- emitcode("ld", "hl,#%d+%d+%d", sym->stack, _G.stack.pushed, _G.stack.offset);
+ if (sym->stack > 0)
+ emitcode("ld", "hl,#%d+%d+%d+%d", sym->stack, _G.stack.pushed, _G.stack.offset, _G.stack.param_offset);
+ else
+ emitcode("ld", "hl,#%d+%d+%d", sym->stack, _G.stack.pushed, _G.stack.offset);
emitcode("add", "hl,sp");
}
else {
if (!options.nopeep)
peepHole (&lineHead);
+ /* This is unfortunate */
/* now do the actual printing */
- printLine (lineHead,codeOutFile);
- return;
+ {
+ FILE *fp = codeOutFile;
+ if (isInHome() && codeOutFile == code->oFile)
+ codeOutFile = home->oFile;
+ printLine (lineHead, codeOutFile);
+ if (_G.flush_statics) {
+ flushStatics();
+ _G.flush_statics = 0;
+ }
+ codeOutFile = fp;
+ }
}