X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Fz80%2Fgen.c;h=7a2984eb996c5ccb7df662f48cb7f52e142691d8;hb=aed2b39c46fcdfdd017adbf9e50c254efc5dea42;hp=a46c959d975a03c6b3332235feb6aacfeaacefcc;hpb=d935ec1dfcf761b5f0790fce80953d7b80d99252;p=fw%2Fsdcc diff --git a/src/z80/gen.c b/src/z80/gen.c index a46c959d..7a2984eb 100644 --- a/src/z80/gen.c +++ b/src/z80/gen.c @@ -16,10 +16,13 @@ Slightly better genCmp(signed) 20597 159 195B 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 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 @@ -30,6 +33,7 @@ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software @@ -51,23 +55,27 @@ #endif #include "z80.h" +#include "SDCCglobl.h" #include "SDCCpeeph.h" #include "gen.h" #include "SDCCglue.h" +#include "newalloc.h" /* this is the down and dirty file with all kinds of kludgy & hacky stuff. This is what it is all about CODE GENERATION for a specific MCU. Some of the routines may be reusable, will have to see */ -static char *zero = "#0x00"; -static char *one = "#0x01"; static char *spname ; static char *_z80_return[] = {"l", "h", "e", "d" }; static char *_gbz80_return[] = { "e", "d", "l", "h" }; static char **_fReturn; static char **_fTmp; +/* PENDING: messy */ +static char zero[20]; + static char *accUse[] = {"a" }; +static char *hlUse[] = { "l", "h" }; short rbank = -1; short accInUse = 0 ; short inLine = 0; @@ -77,8 +85,30 @@ extern int ptrRegReq ; extern int nRegs; extern FILE *codeOutFile; set *sendSet = NULL; -const char *_shortJP = "jp"; +typedef enum { + PAIR_INVALID, + PAIR_BC, + PAIR_DE, + PAIR_HL, + PAIR_IY, + PAIR_IX, + NUM_PAIRS +} PAIR_ID; + +static struct { + const char *name; + const char *l; + const char *h; +} _pairs[NUM_PAIRS] = { + { "??", "?", "?" }, + { "bc", "c", "b" }, + { "de", "e", "d" }, + { "hl", "l", "h" }, + { "iy", "iy.l?", "iy.h?" }, + { "ix", "ix.l?", "ix.h?" } +}; + #define RESULTONSTACK(x) \ (IC_RESULT(x) && IC_RESULT(x)->aop && \ IC_RESULT(x)->aop->type == AOP_STK ) @@ -86,21 +116,13 @@ const char *_shortJP = "jp"; #define MOVA(x) if (strcmp(x,"a")) emitcode("ld","a,%s",x); #define CLRC emitcode("xor","a,a"); -#define LABEL_STR "%05d$" - lineNode *lineHead = NULL; lineNode *lineCurr = NULL; -unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0, -0xE0, 0xC0, 0x80, 0x00}; -unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F, -0x07, 0x03, 0x01, 0x00}; - -static int _lastStack = 0; -static int _pushed = 0; -static int _spoffset; -static int _lastHLOff = 0; -static asmop *_lastHL; +static const unsigned char SLMask[] = +{0xFF ,0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80, 0x00}; +static const unsigned char SRMask[] = +{0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01, 0x00}; #define LSB 0 #define MSB16 1 @@ -108,13 +130,70 @@ static asmop *_lastHL; #define MSB32 3 /* Stack frame: - IX+4 param0 LH IX+2 ret LH IX+0 ix LH IX-2 temp0 LH */ +static struct { + struct { + AOP_TYPE last_type; + const char *lit; + int offset; + } pairs[NUM_PAIRS]; + 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 void _tidyUp(char *buf) +{ + /* Clean up the line so that it is 'prettier' */ + if (strchr(buf, ':')) { + /* Is a label - cant do anything */ + return; + } + /* Change the first (and probably only) ' ' to a tab so + everything lines up. + */ + while (*buf) { + if (*buf == ' ') { + *buf = '\t'; + return; + } + buf++; + } +} + +static void emit2(const char *szFormat, ...) +{ + char buffer[256]; + va_list ap; + + va_start(ap, szFormat); + + tvsprintf(buffer, szFormat, ap); + + _tidyUp(buffer); + lineCurr = (lineCurr ? + connectLine(lineCurr,newLineNode(buffer)) : + (lineHead = newLineNode(buffer))); + + lineCurr->isInline = inLine; + lineCurr->isDebug = debugLine; +} + /*-----------------------------------------------------------------*/ /* emitcode - writes the code into a file : for now it is simple */ /*-----------------------------------------------------------------*/ @@ -143,6 +222,26 @@ void emitcode (const char *inst, const char *fmt, ...) va_end(ap); } +/* Z80: + { "adjustsp", + "\tld hl,#-%d\n" + "\tadd hl,sp\n" + "\tld sp,hl" + } + { "prelude", + "push bc" + "push de" + "push ix" + "ld ix,#0" + "add ix,sp" + { "leave" + emitcode("ld", "sp,ix"); + emitcode("pop", "ix"); + emitcode("pop", "de"); + } +} +*/ + const char *getPairName(asmop *aop) { if (aop->type == AOP_REG) { @@ -171,46 +270,64 @@ const char *getPairName(asmop *aop) break; } } - assert(0); + wassert(0); return NULL; } -/** Returns TRUE if the registers used in aop form a pair (BC, DE, HL) */ -bool isPair(asmop *aop) +static PAIR_ID getPairId(asmop *aop) { if (aop->size == 2) { if (aop->type == AOP_REG) { if ((aop->aopu.aop_reg[0]->rIdx == C_IDX)&&(aop->aopu.aop_reg[1]->rIdx == B_IDX)) { - return TRUE; + return PAIR_BC; } if ((aop->aopu.aop_reg[0]->rIdx == E_IDX)&&(aop->aopu.aop_reg[1]->rIdx == D_IDX)) { - return TRUE; + return PAIR_DE; } if ((aop->aopu.aop_reg[0]->rIdx == L_IDX)&&(aop->aopu.aop_reg[1]->rIdx == H_IDX)) { - return TRUE; + return PAIR_HL; } } if (aop->type == AOP_STR) { if (!strcmp(aop->aopu.aop_str[0], "c")&&!strcmp(aop->aopu.aop_str[1], "b")) { - return TRUE; + return PAIR_BC; } if (!strcmp(aop->aopu.aop_str[0], "e")&&!strcmp(aop->aopu.aop_str[1], "d")) { - return TRUE; + return PAIR_DE; } if (!strcmp(aop->aopu.aop_str[0], "l")&&!strcmp(aop->aopu.aop_str[1], "h")) { - return TRUE; + return PAIR_HL; } } } - return FALSE; + return PAIR_INVALID; } +/** Returns TRUE if the registers used in aop form a pair (BC, DE, HL) */ +bool isPair(asmop *aop) +{ + return (getPairId(aop) != PAIR_INVALID); +} + +bool isPtrPair(asmop *aop) +{ + PAIR_ID pairId = getPairId(aop); + switch (pairId) { + case PAIR_HL: + case PAIR_IY: + case PAIR_IX: + return TRUE; + default: + return FALSE; + } +} /** Push a register pair onto the stack */ void genPairPush(asmop *aop) { emitcode("push", "%s", getPairName(aop)); } + /*-----------------------------------------------------------------*/ /* newAsmop - creates a new asmOp */ /*-----------------------------------------------------------------*/ @@ -218,7 +335,7 @@ static asmop *newAsmop (short type) { asmop *aop; - ALLOC(aop,sizeof(asmop)); + aop = Safe_calloc(sizeof(asmop)); aop->type = type; return aop; } @@ -226,10 +343,16 @@ static asmop *newAsmop (short type) /*-----------------------------------------------------------------*/ /* aopForSym - for a true symbol */ /*-----------------------------------------------------------------*/ -static asmop *aopForSym (iCode *ic,symbol *sym,bool result) +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) @@ -237,9 +360,9 @@ static asmop *aopForSym (iCode *ic,symbol *sym,bool result) /* Assign depending on the storage class */ if (sym->onStack || sym->iaccess) { + emitcode("", "; AOP_STK for %s", sym->rname); sym->aop = aop = newAsmop(AOP_STK); aop->size = getSize(sym->type); - _lastHL = NULL; aop->aopu.aop_stk = sym->stack; return aop; } @@ -247,34 +370,31 @@ static asmop *aopForSym (iCode *ic,symbol *sym,bool result) /* special case for a function */ if (IS_FUNC(sym->type)) { sym->aop = aop = newAsmop(AOP_IMMD); - ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1); + aop->aopu.aop_immd = Safe_calloc(strlen(sym->rname)+1); strcpy(aop->aopu.aop_immd,sym->rname); aop->size = 2; return aop; } -#if 0 if (IS_GB) { /* if it is in direct space */ - if (IN_DIRSPACE(space)) { - sym->aop = aop = newAsmop (AOP_DIR); + if (IN_REGSP(space) && !requires_a) { + sym->aop = aop = newAsmop (AOP_SFR); aop->aopu.aop_dir = sym->rname ; aop->size = getSize(sym->type); - emitcode("", "; AOP_DIR for %s", sym->rname); + emitcode("", "; AOP_SFR for %s", sym->rname); return aop; } } -#endif /* only remaining is far space */ /* in which case DPTR gets the address */ if (IS_GB) { + emitcode("", "; AOP_HL for %s", sym->rname); sym->aop = aop = newAsmop(AOP_HL); - _lastHL = NULL; } else { sym->aop = aop = newAsmop(AOP_IY); - emitcode ("ld","iy,#%s ; a", sym->rname); } aop->size = getSize(sym->type); aop->aopu.aop_dir = sym->rname; @@ -298,6 +418,7 @@ static asmop *aopForRemat (symbol *sym) while (1) { /* if plus or minus print the right hand side */ if (ic->op == '+' || ic->op == '-') { + /* PENDING: for re-target */ sprintf(s,"0x%04x %c ",(int) operandLitValue(IC_RIGHT(ic)), ic->op ); s += strlen(s); @@ -309,7 +430,7 @@ static asmop *aopForRemat (symbol *sym) break; } - ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1); + aop->aopu.aop_immd = Safe_calloc(strlen(buffer)+1); strcpy(aop->aopu.aop_immd,buffer); return aop; } @@ -401,12 +522,16 @@ bool sameRegs (asmop *aop1, asmop *aop2 ) { int i; - if (aop1 == aop2) - return TRUE ; + if (aop1->type == AOP_SFR || + aop2->type == AOP_SFR) + return FALSE; + + if (aop1 == aop2) + return TRUE; if (aop1->type != AOP_REG || aop2->type != AOP_REG ) - return FALSE ; + return FALSE; if (aop1->size != aop2->size) return FALSE ; @@ -422,7 +547,7 @@ bool sameRegs (asmop *aop1, asmop *aop2 ) /*-----------------------------------------------------------------*/ /* aopOp - allocates an asmop for an operand : */ /*-----------------------------------------------------------------*/ -static void aopOp (operand *op, iCode *ic, bool result) +static void aopOp (operand *op, iCode *ic, bool result, bool requires_a) { asmop *aop; symbol *sym; @@ -451,7 +576,7 @@ static void aopOp (operand *op, iCode *ic, bool result) /* if this is a true symbol */ if (IS_TRUE_SYMOP(op)) { - op->aop = aopForSym(ic,OP_SYMBOL(op),result); + op->aop = aopForSym(ic, OP_SYMBOL(op), result, requires_a); return ; } @@ -486,11 +611,22 @@ static void aopOp (operand *op, iCode *ic, bool result) if (sym->accuse) { int i; - aop = op->aop = sym->aop = newAsmop(AOP_ACC); - aop->size = getSize(sym->type); - for ( i = 0 ; i < 2 ; i++ ) - aop->aopu.aop_str[i] = accUse[i]; - return; + if (sym->accuse == ACCUSE_A) { + aop = op->aop = sym->aop = newAsmop(AOP_ACC); + aop->size = getSize(sym->type); + for ( i = 0 ; i < 2 ; i++ ) + aop->aopu.aop_str[i] = accUse[i]; + } + else if (sym->accuse == ACCUSE_HL) { + wassert(!IS_GB); + aop = op->aop = sym->aop = newAsmop(AOP_HLREG); + aop->size = getSize(sym->type); + for ( i = 0 ; i < 2 ; i++ ) + aop->aopu.aop_str[i] = hlUse[i]; + } + else + wassert(0); + return; } if (sym->ruonly ) { @@ -504,7 +640,7 @@ static void aopOp (operand *op, iCode *ic, bool result) /* else spill location */ sym->aop = op->aop = aop = - aopForSym(ic,sym->usl.spillLoc,result); + aopForSym(ic,sym->usl.spillLoc,result, requires_a); aop->size = getSize(sym->type); return; } @@ -536,11 +672,6 @@ static void freeAsmop (operand *op, asmop *aaop, iCode *ic) aop->freed = 1; - switch (aop->type) { - case AOP_STK : - break; - } - dealloc: /* all other cases just dealloc */ if (op ) { @@ -554,23 +685,41 @@ dealloc: } } -char *aopGetWordLong(asmop *aop, int offset, bool with_hash) +bool isLitWord(asmop *aop) +{ + /* if (aop->size != 2) + return FALSE;*/ + switch (aop->type) { + case AOP_IMMD: + case AOP_LIT: + return TRUE; + default: + return FALSE; + } +} + +char *aopGetLitWordLong(asmop *aop, int offset, bool with_hash) { char *s = buffer ; char *rs; - if (aop->size != 2) +#if 0 + if (aop->size != 2 && aop->type != AOP_HL) return NULL; - assert(offset == 0); - +#endif /* depending on type */ switch (aop->type) { + case AOP_HL: + case AOP_IY: case AOP_IMMD: - sprintf (s,"%s%s",with_hash ? "#" : "", aop->aopu.aop_immd); - ALLOC_ATOMIC(rs,strlen(s)+1); + /* PENDING: for re-target */ + if (with_hash) + tsprintf(s, "!hashedstr + %d", aop->aopu.aop_immd, offset); + else + tsprintf(s, "%s + %d", aop->aopu.aop_immd, offset); + rs = Safe_calloc(strlen(s)+1); strcpy(rs,s); return rs; - case AOP_LIT: { value * val = aop->aopu.aop_lit; /* if it is a float then it gets tricky */ @@ -578,60 +727,250 @@ char *aopGetWordLong(asmop *aop, int offset, bool with_hash) if (!IS_FLOAT(val->type)) { unsigned long v = floatFromVal(val); - sprintf(buffer,"%s0x%04lx", with_hash ? "#" : "", v); - ALLOC_ATOMIC(rs,strlen(buffer)+1); + if (offset == 2) + v >>= 16; + + if (with_hash) + tsprintf(buffer, "!immedword", v); + else + tsprintf(buffer, "!constword", v); + rs = Safe_calloc(strlen(buffer)+1); + return strcpy (rs,buffer); + } + else { + /* A float */ + Z80_FLOAT f; + convertFloat(&f, floatFromVal(val)); + if (with_hash) + tsprintf(buffer, "!immedword", f.w[offset/2]); + else + tsprintf(buffer, "!constword", f.w[offset/2]); + rs = Safe_calloc(strlen(buffer)+1); return strcpy (rs,buffer); } - assert(0); - return NULL; } + default: + return NULL; } - return NULL; } char *aopGetWord(asmop *aop, int offset) { - return aopGetWordLong(aop, offset, TRUE); + return aopGetLitWordLong(aop, offset, TRUE); } -static void setupHL(asmop *aop, int offset) +bool isPtr(const char *s) { - if (_lastHL != aop) { - switch (aop->type) { - case AOP_HL: - emitcode("ld", "hl,#%s+%d", aop->aopu.aop_dir, offset); - break; - case AOP_STK: - /* In some cases we can still inc or dec hl */ - emitcode("lda", "hl,%d+%d+%d(sp)", aop->aopu.aop_stk+offset, _pushed, _spoffset); - break; - default: - assert(0); + if (!strcmp(s, "hl")) + return TRUE; + if (!strcmp(s, "ix")) + return TRUE; + if (!strcmp(s, "iy")) + return TRUE; + return FALSE; +} + +static void adjustPair(const char *pair, int *pold, int new) +{ + wassert(pair); + + while (*pold < new) { + emitcode("inc", "%s", pair); + (*pold)++; + } + while (*pold > new) { + emitcode("dec", "%s", pair); + (*pold)--; + } +} + +static void spillPair(PAIR_ID pairId) +{ + _G.pairs[pairId].last_type = AOP_INVALID; + _G.pairs[pairId].lit = NULL; +} + +static void spillCached(void) +{ + spillPair(PAIR_HL); + spillPair(PAIR_IY); +} + +static bool requiresHL(asmop *aop) +{ + switch (aop->type) { + case AOP_HL: + case AOP_STK: + return TRUE; + default: + return FALSE; + } +} + +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, 0, FALSE); + wassert(l && pair); + + if (isPtr(pair)) { + if (pairId == PAIR_HL || pairId == PAIR_IY) { + if (_G.pairs[pairId].last_type == left->type) { + if (_G.pairs[pairId].lit && !strcmp(_G.pairs[pairId].lit, l)) { + if (pairId == PAIR_HL && abs(_G.pairs[pairId].offset - offset) < 3) { + adjustPair(pair, &_G.pairs[pairId].offset, offset); + return; + } + if (pairId == PAIR_IY && abs(offset)<127) { + return; + } + } + } + } + _G.pairs[pairId].last_type = left->type; + _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; + } } - _lastHL = aop; - _lastHLOff = offset; + _G.pairs[pairId].last_type = left->type; + _G.pairs[pairId].lit = gc_strdup(l); + _G.pairs[pairId].offset = offset; } - else { - while (offset < _lastHLOff) { - emitcode("dec", "hl"); - _lastHLOff--; + /* Both a lit on the right and a true symbol on the left */ + if (offset) + emit2("ld %s,!hashedstr + %u", pair, l, offset); + else + emit2("ld %s,!hashedstr", pair, l); +} + +static void fetchPairLong(PAIR_ID pairId, asmop *aop, int offset) +{ + /* if this is remateriazable */ + if (isLitWord(aop)) { + fetchLitPair(pairId, aop, offset); + } + else { /* we need to get it byte by byte */ + if (pairId == PAIR_HL && IS_GB && requiresHL(aop)) { + aopGet(aop, offset, FALSE); + 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 + from the address IY refers to */ + char *l = aopGetLitWordLong(aop, offset, FALSE); + wassert(l); + emit2("ld %s,(%s)", _pairs[pairId].name, l); + } + else { + emitcode("ld", "%s,%s", _pairs[pairId].l, aopGet(aop, offset, FALSE)); + emitcode("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); +} + +static void fetchHL(asmop *aop) +{ + fetchPair(PAIR_HL, aop); +} + +static void setupPair(PAIR_ID pairId, asmop *aop, int offset) +{ + assert(pairId == PAIR_HL || pairId == PAIR_IY); + + switch (aop->type) { + case AOP_IY: + fetchLitPair(pairId, aop, 0); + break; + case AOP_HL: + fetchLitPair(pairId, aop, offset); + _G.pairs[pairId].offset = offset; + break; + 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; } - while (offset > _lastHLOff) { - emitcode("inc", "hl"); - _lastHLOff++; + 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", abso +_G.stack.pushed); } + _G.pairs[pairId].offset = abso; + break; + } + default: + wassert(0); } + _G.pairs[pairId].last_type = aop->type; +} + +static void emitLabel(int key) +{ + emit2("!tlabeldef", key); + spillCached(); } /*-----------------------------------------------------------------*/ /* aopGet - for fetching value of the aop */ /*-----------------------------------------------------------------*/ -static char *aopGet (asmop *aop, int offset, bool bit16) +static char *aopGet(asmop *aop, int offset, bool bit16) { char *s = buffer ; char *rs; /* 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) return zero; @@ -639,66 +978,86 @@ static char *aopGet (asmop *aop, int offset, bool bit16) /* depending on type */ switch (aop->type) { case AOP_IMMD: + /* PENDING: re-target */ if (bit16) - sprintf (s,"#%s",aop->aopu.aop_immd); + tsprintf (s,"!immedwords", aop->aopu.aop_immd); else - if (offset) { - assert(offset == 1); - sprintf(s,"#>%s", - aop->aopu.aop_immd); + 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 - sprintf(s,"#<%s", - aop->aopu.aop_immd); - ALLOC_ATOMIC(rs,strlen(s)+1); + rs = Safe_calloc(strlen(s)+1); strcpy(rs,s); return rs; case AOP_DIR: - assert(IS_GB); + wassert(IS_GB); emitcode("ld", "a,(%s+%d) ; x", aop->aopu.aop_dir, offset); sprintf(s, "a"); - ALLOC_ATOMIC(rs,strlen(s)+1); + rs = Safe_calloc(strlen(s)+1); strcpy(rs,s); return rs; + case AOP_SFR: + wassert(IS_GB); + emitcode("ldh", "a,(%s+%d) ; x", aop->aopu.aop_dir, offset); + sprintf(s, "a"); + rs = Safe_calloc(strlen(s)+1); + strcpy(rs,s); + return rs; + case AOP_REG: return aop->aopu.aop_reg[offset]->name; case AOP_HL: - assert(IS_GB); - setupHL(aop, offset); - sprintf(s, "(hl)"); - ALLOC_ATOMIC(rs, strlen(s)+1); - strcpy(rs,s); - return rs; + wassert(IS_GB); + setupPair(PAIR_HL, aop, offset); + tsprintf(s, "!*hl"); + return gc_strdup(s); case AOP_IY: - sprintf(s,"%d(iy)", offset); - ALLOC_ATOMIC(rs,strlen(s)+1); + wassert(IS_Z80); + setupPair(PAIR_IY, aop, offset); + tsprintf(s,"!*iyx", offset); + rs = Safe_calloc(strlen(s)+1); strcpy(rs,s); return rs; case AOP_STK: if (IS_GB) { - setupHL(aop, offset); - sprintf(s, "(hl)"); + setupPair(PAIR_HL, aop, offset); + tsprintf(s, "!*hl"); } else { - sprintf(s,"%d(ix) ; %u", aop->aopu.aop_stk+offset, 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); + rs = Safe_calloc(strlen(s)+1); strcpy(rs,s); return rs; case AOP_CRY: - assert(0); + wassert(0); case AOP_ACC: if (!offset) { return "a"; } - return "#0x00"; + return "!zero"; + + case AOP_HLREG: + wassert(offset < 2); + return aop->aopu.aop_str[offset]; case AOP_LIT: return aopLiteral (aop->aopu.aop_lit,offset); @@ -706,16 +1065,14 @@ static char *aopGet (asmop *aop, int offset, bool bit16) case AOP_STR: aop->coff = offset; return aop->aopu.aop_str[offset]; + default: + break; } - - fprintf(stderr, "Type %u\n", aop->type); - - werror(E_INTERNAL_ERROR,__FILE__,__LINE__, - "aopget got unsupported aop->type"); + wassertl(0, "aopget got unsupported aop->type"); exit(0); } -bool isRegString(char *s) +bool isRegString(const char *s) { if (!strcmp(s, "b") || !strcmp(s, "c") || @@ -728,12 +1085,13 @@ bool isRegString(char *s) return FALSE; } -bool isConstant(char *s) +bool isConstant(const char *s) { - return (*s == '#'); + /* This is a bit of a hack... */ + return (*s == '#' || *s == '$'); } -bool canAssignToPtr(char *s) +bool canAssignToPtr(const char *s) { if (isRegString(s)) return TRUE; @@ -745,7 +1103,7 @@ bool canAssignToPtr(char *s) /*-----------------------------------------------------------------*/ /* 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__, @@ -758,71 +1116,85 @@ static void aopPut (asmop *aop, char *s, int offset) switch (aop->type) { case AOP_DIR: /* Direct. Hmmm. */ - assert(IS_GB); - emitcode("ld", "a,%s", s); + wassert(IS_GB); + if (strcmp(s, "a")) + emitcode("ld", "a,%s", s); emitcode("ld", "(%s+%d),a", aop->aopu.aop_dir, offset); break; + case AOP_SFR: + wassert(IS_GB); + if (strcmp(s, "a")) + emitcode("ld", "a,%s", s); + emitcode("ldh", "(%s+%d),a", aop->aopu.aop_dir, offset); + break; + case AOP_REG: - /* Dont bother if it's a ld x,x */ - if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { - emitcode("ld","%s,%s", - aop->aopu.aop_reg[offset]->name,s); - } + if (!strcmp(s, "!*hl")) + emit2("ld %s,!*hl", aop->aopu.aop_reg[offset]->name); + else + emit2("ld %s,%s", + aop->aopu.aop_reg[offset]->name, s); break; case AOP_IY: - assert(!IS_GB); + wassert(!IS_GB); + setupPair(PAIR_IY, aop, offset); if (!canAssignToPtr(s)) { - emitcode("ld", "a,%s", s); - emitcode("ld", "%d(iy),a", offset); + emit2("ld a,%s", s); + emit2("ld !*iyx,a", offset); } else - emitcode("ld", "%d(iy),%s", offset, s); + emit2("ld !*iyx,%s", offset, s); break; case AOP_HL: - assert(IS_GB); - if (!strcmp(s, "(hl)")) { - emitcode("ld", "a,(hl)"); + wassert(IS_GB); + /* PENDING: for re-target */ + if (!strcmp(s, "!*hl") || !strcmp(s, "(hl)") || !strcmp(s, "[hl]")) { + emit2("ld a,!*hl"); s = "a"; } - setupHL(aop, offset); - emitcode("ld", "(hl),%s", s); + setupPair(PAIR_HL, aop, offset); + + emit2("ld !*hl,%s", s); break; case AOP_STK: if (IS_GB) { - if (!strcmp("(hl)", s)) { - emitcode("ld", "a,(hl)"); + /* PENDING: re-target */ + if (!strcmp(s, "!*hl") || !strcmp(s, "(hl)") || !strcmp(s, "[hl]")) { + emit2("ld a,!*hl"); s = "a"; } - setupHL(aop, offset); + setupPair(PAIR_HL, aop, offset); if (!canAssignToPtr(s)) { - emitcode("ld", "a,%s", s); - emitcode("ld", "(hl),a"); + emit2("ld a,%s", s); + emit2("ld !*hl,a"); } else - emitcode("ld", "(hl),%s", s); + emit2("ld !*hl,%s", s); } else { + if (aop->aopu.aop_stk >= 0) + offset += _G.stack.param_offset; if (!canAssignToPtr(s)) { - emitcode("ld", "a,%s", s); - emitcode("ld", "%d(ix),a", aop->aopu.aop_stk+offset); + emit2("ld a,%s", s); + emit2("ld !*ixx,a", aop->aopu.aop_stk+offset); } else - emitcode("ld", "%d(ix),%s", aop->aopu.aop_stk+offset, s); + emit2("ld !*ixx,%s", aop->aopu.aop_stk+offset, s); } break; case AOP_CRY: /* if bit variable */ if (!aop->aopu.aop_dir) { - emitcode("ld", "a,#0"); - emitcode("rla", ""); + emit2("ld a,#0"); + emit2("rla"); } else { /* In bit space but not in C - cant happen */ - assert(0); + wassert(0); } break; @@ -847,6 +1219,11 @@ static void aopPut (asmop *aop, char *s, int offset) } break; + case AOP_HLREG: + wassert(offset < 2); + emit2("ld %s,%s", aop->aopu.aop_str[offset], s); + break; + default : werror(E_INTERNAL_ERROR,__FILE__,__LINE__, "aopPut got unsupported aop->type"); @@ -859,6 +1236,20 @@ static void aopPut (asmop *aop, char *s, int 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 */ /*-----------------------------------------------------------------*/ @@ -868,7 +1259,7 @@ int getDataSize(operand *op) size = AOP_SIZE(op); if(size == 3) { /* pointer */ - assert(0); + wassert(0); } return size; } @@ -887,7 +1278,7 @@ static void movLeft2Result (operand *left, int offl, aopPut(AOP(result),l,offr); } else { - assert(0); + wassert(0); } } } @@ -905,14 +1296,14 @@ void outAcc(operand *result) offset = 1; /* unsigned or positive */ while (size--){ - aopPut(AOP(result),zero,offset++); + aopPut(AOP(result), zero, offset++); } } } /** 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) { @@ -920,12 +1311,19 @@ void outBitC(operand *result) aopPut(AOP(result),"blah",0); } else { - emitcode("ld", "a,#0"); - emitcode("rla", ""); + 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) */ /*-----------------------------------------------------------------*/ @@ -952,20 +1350,20 @@ void toBoolean(operand *oper) /*-----------------------------------------------------------------*/ static void genNot (iCode *ic) { - link *optype = operandType(IC_LEFT(ic)); + sym_link *optype = operandType(IC_LEFT(ic)); /* assign asmOps to operand & result */ - aopOp (IC_LEFT(ic),ic,FALSE); - aopOp (IC_RESULT(ic),ic,TRUE); + aopOp (IC_LEFT(ic),ic,FALSE, TRUE); + aopOp (IC_RESULT(ic),ic,TRUE, FALSE); /* if in bit space then a special case */ if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) { - assert(0); + wassert(0); } /* if type float then do float */ if (IS_FLOAT(optype)) { - assert(0); + wassert(0); } toBoolean(IC_LEFT(ic)); @@ -974,7 +1372,7 @@ static void genNot (iCode *ic) If A == 0, !A = 1 else A = 0 So if A = 0, A-1 = 0xFF and C is set, rotate C into reg. */ - emitcode("sub", "a,#0x01"); + emit2("sub a,!one"); outBitC(IC_RESULT(ic)); /* release the aops */ @@ -992,14 +1390,14 @@ static void genCpl (iCode *ic) /* assign asmOps to operand & result */ - aopOp (IC_LEFT(ic),ic,FALSE); - aopOp (IC_RESULT(ic),ic,TRUE); + aopOp (IC_LEFT(ic),ic,FALSE, FALSE); + aopOp (IC_RESULT(ic),ic,TRUE, FALSE); /* if both are in bit space then a special case */ if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { - assert(0); + wassert(0); } size = AOP_SIZE(IC_RESULT(ic)); @@ -1021,17 +1419,17 @@ static void genCpl (iCode *ic) static void genUminus (iCode *ic) { int offset ,size ; - link *optype, *rtype; + sym_link *optype, *rtype; /* assign asmops */ - aopOp(IC_LEFT(ic),ic,FALSE); - aopOp(IC_RESULT(ic),ic,TRUE); + aopOp(IC_LEFT(ic),ic,FALSE, FALSE); + aopOp(IC_RESULT(ic),ic,TRUE, FALSE); /* if both in bit space then special case */ if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { - assert(0); + wassert(0); goto release; } @@ -1040,7 +1438,7 @@ static void genUminus (iCode *ic) /* if float then do float stuff */ if (IS_FLOAT(optype)) { - assert(0); + wassert(0); goto release; } @@ -1050,16 +1448,16 @@ static void genUminus (iCode *ic) CLRC ; while(size--) { char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE); - emitcode("ld", "a,#0"); - emitcode("sbc","a,%s",l); + emit2("ld a,!zero"); + emit2("sbc a,%s",l); aopPut(AOP(IC_RESULT(ic)),"a",offset++); } /* if any remaining bytes in the result */ /* we just need to propagate the sign */ if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) { - emitcode("rlc","a"); - emitcode("sbc","a,a"); + emit2("rlc a"); + emit2("sbc a,a"); while (size--) aopPut(AOP(IC_RESULT(ic)),"a",offset++); } @@ -1070,44 +1468,48 @@ release: freeAsmop(IC_RESULT(ic),NULL,ic); } -static bool requiresHL(asmop *aop) +static void _push(PAIR_ID pairId) { - switch (aop->type) { - case AOP_HL: - case AOP_STK: - return TRUE; - default: - return FALSE; - } + 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 - */ /*-----------------------------------------------------------------*/ void assignResultValue(operand * oper) { - int offset = 0; int size = AOP_SIZE(oper); + bool topInA = 0; - assert(size <= 2); + wassert(size <= 4); + topInA = requiresHL(AOP(oper)); - while (size--) { - aopPut(AOP(oper),_fReturn[offset],offset); - offset++; - } -} - -static void fetchHL(asmop *aop) -{ - if (IS_GB && requiresHL(aop)) { - aopGet(aop, 0, FALSE); - emitcode("ld", "a,(hl+)"); - emitcode("ld", "h,(hl)"); - emitcode("ld", "l,a"); +#if 0 + if (!IS_GB) + wassert(size <= 2); +#endif + if (IS_GB && size == 4 && requiresHL(AOP(oper))) { + /* We do it the hard way here. */ + _push(PAIR_HL); + aopPut(AOP(oper), _fReturn[0], 0); + aopPut(AOP(oper), _fReturn[1], 1); + emitcode("pop", "de"); + _G.stack.pushed -= 2; + aopPut(AOP(oper), _fReturn[0], 2); + aopPut(AOP(oper), _fReturn[1], 3); } else { - emitcode("ld", "l,%s", aopGet(aop, 0, FALSE)); - emitcode("ld", "h,%s", aopGet(aop, 1, FALSE)); + while (size--) { + aopPut(AOP(oper), _fReturn[size], size); + } } } @@ -1119,7 +1521,6 @@ static void genIpush (iCode *ic) 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) { @@ -1127,22 +1528,29 @@ static void genIpush (iCode *ic) if (OP_SYMBOL(IC_LEFT(ic))->isspilt) return ; - aopOp(IC_LEFT(ic),ic,FALSE); + aopOp(IC_LEFT(ic),ic,FALSE, FALSE); size = AOP_SIZE(IC_LEFT(ic)); /* push it on the stack */ if (isPair(AOP(IC_LEFT(ic)))) { emitcode("push", getPairName(AOP(IC_LEFT(ic)))); - _pushed += 2; + _G.stack.pushed += 2; } else { offset = size; while (size--) { - l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE); /* Simple for now - load into A and PUSH AF */ - emitcode("ld", "a,%s", l); - emitcode("push", "af"); - emitcode("inc", "sp"); - _pushed++; + if (AOP(IC_LEFT(ic))->type == AOP_IY) { + char *l = aopGetLitWordLong(AOP(IC_LEFT(ic)), --offset, FALSE); + wassert(l); + emit2("ld a,(%s)", l); + } + else { + l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE); + emit2("ld a,%s", l); + } + emit2("push af"); + emit2("inc sp"); + _G.stack.pushed++; } } return ; @@ -1152,37 +1560,47 @@ static void genIpush (iCode *ic) at this point? */ /* then do the push */ - aopOp(IC_LEFT(ic),ic,FALSE); + aopOp(IC_LEFT(ic),ic,FALSE, FALSE); size = AOP_SIZE(IC_LEFT(ic)); if (isPair(AOP(IC_LEFT(ic)))) { - _pushed+=2; + _G.stack.pushed+=2; emitcode("push", "%s", getPairName(AOP(IC_LEFT(ic)))); } else { if (size == 2) { - char *s = aopGetWord(AOP(IC_LEFT(ic)), 0); - if (s) { - emitcode("ld", "hl,%s", s); - emitcode("push", "hl"); - _pushed+=2; - } - else { - /* Optimise here - load into HL then push HL */ - fetchHL(AOP(IC_LEFT(ic))); - emitcode("push", "hl"); - _pushed += 2; - } + fetchHL(AOP(IC_LEFT(ic))); + emitcode("push", "hl"); + spillPair(PAIR_HL); + _G.stack.pushed += 2; + goto release; + } + if (size == 4) { + fetchPairLong(PAIR_HL, AOP(IC_LEFT(ic)), 2); + emitcode("push", "hl"); + spillPair(PAIR_HL); + _G.stack.pushed += 2; + fetchPairLong(PAIR_HL, AOP(IC_LEFT(ic)), 0); + emitcode("push", "hl"); + spillPair(PAIR_HL); + _G.stack.pushed += 2; goto release; } offset = size; while (size--) { - l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE); - emitcode("ld", "a,%s", l); + if (AOP(IC_LEFT(ic))->type == AOP_IY) { + char *l = aopGetLitWordLong(AOP(IC_LEFT(ic)), --offset, FALSE); + wassert(l); + emit2("ld a,(%s)", l); + } + else { + l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE); + emit2("ld a,%s", l); + } emitcode("push", "af"); emitcode("inc", "sp"); - _pushed++; + _G.stack.pushed++; } } release: @@ -1201,7 +1619,7 @@ static void genIpop (iCode *ic) if (OP_SYMBOL(IC_LEFT(ic))->isspilt) return ; - aopOp(IC_LEFT(ic),ic,FALSE); + aopOp(IC_LEFT(ic),ic,FALSE, FALSE); size = AOP_SIZE(IC_LEFT(ic)); offset = (size-1); if (isPair(AOP(IC_LEFT(ic)))) { @@ -1211,6 +1629,7 @@ static void genIpop (iCode *ic) while (size--) { emitcode("dec", "sp"); emitcode("pop", "hl"); + spillPair(PAIR_HL); aopPut(AOP(IC_LEFT(ic)), "l", offset--); } } @@ -1218,59 +1637,193 @@ static void genIpop (iCode *ic) 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; + sym_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); - 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) { - symbol *rlbl = newiTempLabel(NULL); - - emitcode("ld", "hl,#" LABEL_STR, (rlbl->key+100)); - emitcode("push", "hl"); - _pushed += 2; + if (IS_BANKEDCALL(detype)) { + werror(W_INDIR_BANKED); + } + aopOp(IC_LEFT(ic),ic,FALSE, FALSE); - aopOp(IC_LEFT(ic),ic,FALSE); - fetchHL(AOP(IC_LEFT(ic))); + if (isLitWord(AOP(IC_LEFT(ic)))) { + emitcode("", "; Special case where the pCall is to a constant"); + emitcode("call", aopGetLitWordLong(AOP(IC_LEFT(ic)), 0, FALSE)); + } + else { + symbol *rlbl = newiTempLabel(NULL); + spillPair(PAIR_HL); + emit2("ld hl,!immed!tlabel", (rlbl->key+100)); + emitcode("push", "hl"); + _G.stack.pushed += 2; + + fetchHL(AOP(IC_LEFT(ic))); + emit2("jp !*hl"); + emit2("!tlabeldef", (rlbl->key+100)); + _G.stack.pushed -= 2; + } freeAsmop(IC_LEFT(ic),NULL,ic); - - emitcode("jp", "(hl)"); - emitcode("","%05d$:",(rlbl->key+100)); - _pushed -= 2; } 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(); /* if we need assign a result value */ if ((IS_ITEMP(IC_RESULT(ic)) && @@ -1279,7 +1832,7 @@ static void emitCall (iCode *ic, bool ispcall) IS_TRUE_SYMOP(IC_RESULT(ic)) ) { accInUse++; - aopOp(IC_RESULT(ic),ic,FALSE); + aopOp(IC_RESULT(ic),ic,FALSE, FALSE); accInUse--; assignResultValue(IC_RESULT(ic)); @@ -1290,11 +1843,12 @@ static void emitCall (iCode *ic, bool ispcall) /* adjust the stack for parameters if required */ if (IC_LEFT(ic)->parmBytes) { int i = IC_LEFT(ic)->parmBytes; - _pushed -= i; + _G.stack.pushed -= i; if (IS_GB) { - emitcode("lda", "sp,%d(sp)", i); + emit2("!ldaspsp", i); } else { + spillCached(); if (i>6) { emitcode("ld", "hl,#%d", i); emitcode("add", "hl,sp"); @@ -1308,9 +1862,11 @@ static void emitCall (iCode *ic, bool ispcall) if (i) emitcode("inc", "sp"); } + spillCached(); } } - + if (pushed_de) + _pop(PAIR_DE); } /*-----------------------------------------------------------------*/ @@ -1318,6 +1874,7 @@ static void emitCall (iCode *ic, bool ispcall) /*-----------------------------------------------------------------*/ static void genCall (iCode *ic) { + sym_link *detype = getSpec(operandType(IC_LEFT(ic))); emitCall(ic, FALSE); } @@ -1346,59 +1903,82 @@ static int resultRemat (iCode *ic) return 0; } +extern set *publics; + /*-----------------------------------------------------------------*/ /* genFunction - generated code for function entry */ /*-----------------------------------------------------------------*/ static void genFunction (iCode *ic) { - symbol *sym; - link *fetype; + symbol *sym = OP_SYMBOL(IC_LEFT(ic)); + sym_link *fetype; nregssaved = 0; - /* create the function header */ - emitcode(";","-----------------------------------------"); - emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name); - emitcode(";","-----------------------------------------"); + setArea(IS_NONBANKED(sym->etype)); - emitcode("","%s:",sym->rname); - fetype = getSpec(operandType(IC_LEFT(ic))); + /* 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)) - emitcode("di",""); + emit2("!di"); /* if this is an interrupt service routine then save acc, b, dpl, dph */ if (IS_ISR(sym->etype)) { - emitcode("push", "af"); - emitcode("push", "bc"); - emitcode("push", "de"); - emitcode("push", "hl"); + emit2("!pusha"); } /* PENDING: callee-save etc */ - /* adjust the stack for the function */ - emitcode("push", "bc"); - if (!IS_GB) { - emitcode("push", "de"); - emitcode("push", "ix"); - emitcode("ld", "ix,#0"); - emitcode("add", "ix,sp"); - } - - _lastStack = sym->stack; - - if (sym->stack) { - if (IS_GB) { - emitcode("lda", "sp,-%d(sp)", sym->stack); + /* 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; + } + } } - else { - emitcode("ld", "hl,#-%d", sym->stack); - emitcode("add", "hl,sp"); - emitcode("ld", "sp,hl"); + 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; } } - _spoffset = sym->stack; + + /* adjust the stack for the function */ + _G.stack.last = sym->stack; + + if (sym->stack) + emit2("!enterx", sym->stack); + else + emit2("!enter"); + _G.stack.offset = sym->stack; } /*-----------------------------------------------------------------*/ @@ -1409,11 +1989,11 @@ static void genEndFunction (iCode *ic) symbol *sym = OP_SYMBOL(IC_LEFT(ic)); if (IS_ISR(sym->etype)) { - assert(0); + wassert(0); } else { if (SPEC_CRTCL(sym->etype)) - emitcode("ei", ""); + emit2("!ei"); /* PENDING: calleeSave */ @@ -1429,23 +2009,24 @@ static void genEndFunction (iCode *ic) emitcode("","XG$%s$0$0 ==.",currFunc->name); debugLine = 0; } - if (!IS_GB) { - emitcode("ld", "sp,ix"); - emitcode("pop", "ix"); - emitcode("pop", "de"); - } - else { - if (_spoffset) { - emitcode("ld", "hl,#%d", _spoffset); - emitcode("add", "hl,sp"); - emitcode("ld", "sp,hl"); - } - } - emitcode("pop", "bc"); - emitcode("ret", ""); + if (_G.stack.offset) + 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); } - _pushed = 0; - _spoffset = 0; + _G.flush_statics = 1; + _G.stack.pushed = 0; + _G.stack.offset = 0; } /*-----------------------------------------------------------------*/ @@ -1465,7 +2046,7 @@ static void genRet (iCode *ic) /* we have something to return then move the return value into place */ - aopOp(IC_LEFT(ic),ic,FALSE); + aopOp(IC_LEFT(ic),ic,FALSE, FALSE); size = AOP_SIZE(IC_LEFT(ic)); if ((size == 2) && ((l = aopGetWord(AOP(IC_LEFT(ic)), 0)))) { @@ -1477,11 +2058,17 @@ static void genRet (iCode *ic) } } else { - while (size--) { - l = aopGet(AOP(IC_LEFT(ic)),offset, - FALSE); - if (strcmp(_fReturn[offset],l)) - emitcode("ld","%s,%s", _fReturn[offset++],l); + 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); + } + else { + while (size--) { + l = aopGet(AOP(IC_LEFT(ic)),offset, + FALSE); + if (strcmp(_fReturn[offset],l)) + emitcode("ld","%s,%s", _fReturn[offset++],l); + } } } freeAsmop (IC_LEFT(ic),NULL,ic); @@ -1492,7 +2079,7 @@ static void genRet (iCode *ic) if (!(ic->next && ic->next->op == LABEL && IC_LABEL(ic->next) == returnLabel)) - emitcode("jp", LABEL_STR ,(returnLabel->key+100)); + emit2("jp !tlabel", returnLabel->key+100); } /*-----------------------------------------------------------------*/ @@ -1504,7 +2091,7 @@ static void genLabel (iCode *ic) if (IC_LABEL(ic) == entryLabel) return ; - emitcode("", LABEL_STR ":",(IC_LABEL(ic)->key+100)); + emitLabel(IC_LABEL(ic)->key+100); } /*-----------------------------------------------------------------*/ @@ -1512,7 +2099,7 @@ static void genLabel (iCode *ic) /*-----------------------------------------------------------------*/ static void genGoto (iCode *ic) { - emitcode ("jp", LABEL_STR ,(IC_LABEL(ic)->key+100)); + emit2("jp !tlabel", IC_LABEL(ic)->key+100); } /*-----------------------------------------------------------------*/ @@ -1522,7 +2109,8 @@ static bool genPlusIncr (iCode *ic) { unsigned int icount ; unsigned int size = getDataSize(IC_RESULT(ic)); - + PAIR_ID resultId = getPairId(AOP(IC_RESULT(ic))); + /* will try to generate an increment */ /* if the right side is not a literal we cannot */ @@ -1532,55 +2120,56 @@ static bool genPlusIncr (iCode *ic) emitcode("", "; genPlusIncr"); icount = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit); - + /* If result is a pair */ - if (isPair(AOP(IC_RESULT(ic)))) { - char *left = aopGetWordLong(AOP(IC_LEFT(ic)), 0, FALSE); - if (left) { - /* Both a lit on the right and a true symbol on the left */ - emitcode("ld", "%s,#%s + %d", getPairName(AOP(IC_RESULT(ic))), left, icount); + if (resultId != PAIR_INVALID) { + if (isLitWord(AOP(IC_LEFT(ic)))) { + fetchLitPair(getPairId(AOP(IC_RESULT(ic))), AOP(IC_LEFT(ic)), icount); + return TRUE; + } + if (isPair(AOP(IC_LEFT(ic))) && resultId == PAIR_HL && icount > 2) { + fetchPair(resultId, AOP(IC_RIGHT(ic))); + emitcode("add", "hl,%s", getPairName(AOP(IC_LEFT(ic)))); return TRUE; } + if (icount > 5) + return FALSE; + /* Inc a pair */ + if (!sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) { + if (icount > 2) + return FALSE; + movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0); + movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0); + } + while (icount--) { + emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic)))); + } + return TRUE; } /* if the literal value of the right hand side is greater than 4 then it is not worth it */ if (icount > 4) - return FALSE ; + return FALSE; - /* Inc a pair */ - if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) && - isPair(AOP(IC_RESULT(ic)))) { - while (icount--) { - emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic)))); - } - return TRUE; - } /* if increment 16 bits in register */ if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) && - (size > 1) && - (icount == 1)) { - symbol *tlbl = newiTempLabel(NULL); - emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE)); - emitcode(_shortJP, "nz," LABEL_STR ,tlbl->key+100); - - emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE)); - if(size == 4) { - assert(0); + size > 1 && + icount == 1 + ) { + int offset = 0; + symbol *tlbl = NULL; + tlbl = newiTempLabel(NULL); + while (size--) { + emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)), offset++, FALSE)); + if (size) { + emit2("!shortjp nz,!tlabel", tlbl->key+100); + } } - emitcode("", LABEL_STR ":",tlbl->key+100); + emitLabel(tlbl->key+100); return TRUE; } - /* If result is a pair */ - if (isPair(AOP(IC_RESULT(ic)))) { - movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0); - movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0); - while (icount--) - emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic)))); - return TRUE; - } - /* if the sizes are greater than 1 then we cannot */ if (AOP_SIZE(IC_RESULT(ic)) > 1 || AOP_SIZE(IC_LEFT(ic)) > 1 ) @@ -1592,7 +2181,6 @@ static bool genPlusIncr (iCode *ic) if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) { while (icount--) emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0, FALSE)); - return TRUE ; } @@ -1607,12 +2195,12 @@ void outBitAcc(operand *result) symbol *tlbl = newiTempLabel(NULL); /* if the result is a bit */ if (AOP_TYPE(result) == AOP_CRY){ - assert(0); + wassert(0); } else { - emitcode(_shortJP,"z," LABEL_STR ,tlbl->key+100); - emitcode("ld","a,%s",one); - emitcode("", LABEL_STR ":",tlbl->key+100); + emit2("!shortjp z,!tlabel", tlbl->key+100); + emit2("ld a,!one"); + emitLabel(tlbl->key+100); outAcc(result); } } @@ -1626,9 +2214,9 @@ static void genPlus (iCode *ic) /* special cases :- */ - aopOp (IC_LEFT(ic),ic,FALSE); - aopOp (IC_RIGHT(ic),ic,FALSE); - aopOp (IC_RESULT(ic),ic,TRUE); + aopOp (IC_LEFT(ic),ic,FALSE, FALSE); + aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); + aopOp (IC_RESULT(ic),ic,TRUE, FALSE); /* Swap the left and right operands if: @@ -1649,14 +2237,14 @@ static void genPlus (iCode *ic) if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY && AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) { /* Cant happen */ - assert(0); + wassert(0); } /* if left in bit space & right literal */ if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY && AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) { /* Can happen I guess */ - assert(0); + wassert(0); } /* if I can do an increment instead @@ -1664,14 +2252,16 @@ static void genPlus (iCode *ic) if (genPlusIncr (ic) == TRUE) goto release; + emit2("; genPlusIncr failed"); + size = getDataSize(IC_RESULT(ic)); /* Special case when left and right are constant */ if (isPair(AOP(IC_RESULT(ic)))) { char *left, *right; - left = aopGetWordLong(AOP(IC_LEFT(ic)), 0, FALSE); - right = aopGetWordLong(AOP(IC_RIGHT(ic)), 0, FALSE); + left = aopGetLitWordLong(AOP(IC_LEFT(ic)), 0, FALSE); + right = aopGetLitWordLong(AOP(IC_RIGHT(ic)), 0, FALSE); if (left && right) { /* It's a pair */ /* PENDING: fix */ @@ -1682,38 +2272,94 @@ static void genPlus (iCode *ic) } } + if (isPair(AOP(IC_RIGHT(ic))) && getPairId(AOP(IC_RESULT(ic))) == PAIR_HL) { + /* Fetch into HL then do the add */ + spillPair(PAIR_HL); + fetchPair(PAIR_HL, AOP(IC_LEFT(ic))); + emitcode("add", "hl,%s", getPairName(AOP(IC_RIGHT(ic)))); + 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_RIGHT(ic)),offset,FALSE)); + MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE)); if(offset == 0) - emitcode("add","a,%s", - aopGet(AOP(IC_LEFT(ic)),offset,FALSE)); + emit2("add a,%s", + aopGet(AOP(IC_RIGHT(ic)),offset,FALSE)); else - emitcode("adc","a,%s", - aopGet(AOP(IC_LEFT(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)))) - assert(0); - - if (AOP_SIZE(IC_RESULT(ic)) == 3 && - AOP_SIZE(IC_RIGHT(ic)) == 3 && - !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) - assert(0); - release: freeAsmop(IC_LEFT(ic),NULL,ic); @@ -1753,9 +2399,9 @@ static bool genMinusDec (iCode *ic) emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE)); if(size == 4) { - assert(0); + wassert(0); } - emitcode("", LABEL_STR ":",tlbl->key+100); + emitLabel(tlbl->key+100); return TRUE; } #endif @@ -1801,15 +2447,15 @@ static void genMinus (iCode *ic) int size, offset = 0; unsigned long lit = 0L; - aopOp (IC_LEFT(ic),ic,FALSE); - aopOp (IC_RIGHT(ic),ic,FALSE); - aopOp (IC_RESULT(ic),ic,TRUE); + aopOp (IC_LEFT(ic),ic,FALSE, FALSE); + aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); + aopOp (IC_RESULT(ic),ic,TRUE, FALSE); /* special cases :- */ /* if both left & right are in bit space */ if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY && AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) { - assert(0); + wassert(0); goto release ; } @@ -1826,7 +2472,47 @@ static void genMinus (iCode *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)); @@ -1841,11 +2527,9 @@ static void genMinus (iCode *ic) else{ /* first add without previous c */ if (!offset) - emitcode("add","a,#0x%02x", - (unsigned int)(lit & 0x0FFL)); + emit2("add a,!immedbyte", (unsigned int)(lit & 0x0FFL)); else - emitcode("adc","a,#0x%02x", - (unsigned int)((lit >> (offset*8)) & 0x0FFL)); + emit2("adc a,!immedbyte", (unsigned int)((lit >> (offset*8)) & 0x0FFL)); } aopPut(AOP(IC_RESULT(ic)),"a",offset++); } @@ -1853,7 +2537,7 @@ static void genMinus (iCode *ic) if (AOP_SIZE(IC_RESULT(ic)) == 3 && AOP_SIZE(IC_LEFT(ic)) == 3 && !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic)))) - assert(0); + wassert(0); release: freeAsmop(IC_LEFT(ic),NULL,ic); @@ -1867,7 +2551,7 @@ release: static void genMult (iCode *ic) { /* Shouldn't occur - all done through function calls */ - assert(0); + wassert(0); } /*-----------------------------------------------------------------*/ @@ -1876,7 +2560,7 @@ static void genMult (iCode *ic) static void genDiv (iCode *ic) { /* Shouldn't occur - all done through function calls */ - assert(0); + wassert(0); } /*-----------------------------------------------------------------*/ @@ -1885,7 +2569,7 @@ static void genDiv (iCode *ic) static void genMod (iCode *ic) { /* Shouldn't occur - all done through function calls */ - assert(0); + wassert(0); } /*-----------------------------------------------------------------*/ @@ -1898,7 +2582,7 @@ static void genIfxJump (iCode *ic, char *jval) /* 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"; @@ -1906,6 +2590,9 @@ static void genIfxJump (iCode *ic, char *jval) 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"; @@ -1920,6 +2607,9 @@ static void genIfxJump (iCode *ic, char *jval) 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"; @@ -1931,15 +2621,22 @@ static void genIfxJump (iCode *ic, char *jval) } else if (!strcmp(jval, "c")) { } + else if (!strcmp(jval, "nc")) { + } else { emitcode("bit", "%s,a", jval); } - emitcode("jp", "%s," LABEL_STR , inst, jlbl->key+100); + emit2("jp %s,!tlabel", inst, jlbl->key+100); /* mark the icode as generated */ 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, @@ -1947,12 +2644,13 @@ 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 && AOP_TYPE(right) == AOP_CRY ) { /* Cant happen on the Z80 */ - assert(0); + wassert(0); } else { /* subtract right from left if at the end the carry flag is set then we know that @@ -1964,13 +2662,47 @@ static void genCmp (operand *left,operand *right, (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){ emitcode("ld", "a,%s", aopGet(AOP(left), offset, FALSE)); if (sign) { - emitcode("xor", "a,#0x80"); - emitcode("cp", "%s^0x80", aopGet(AOP(right), offset, FALSE)); + emit2("xor a,!immedbyte", 0x80); + emit2("cp %s^!constbyte", aopGet(AOP(right), offset, FALSE), 0x80); } else - emitcode("cp", "%s ; 7", aopGet(AOP(right), offset, FALSE)); + 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) */ @@ -1998,24 +2730,24 @@ static void genCmp (operand *left,operand *right, if (AOP_TYPE(left) == AOP_LIT){ unsigned long lit = (unsigned long) floatFromVal(AOP(left)->aopu.aop_lit); - emitcode("ld", "%s,#0x%02x", _fTmp[0], + emit2("ld %s,!immedbyte", _fTmp[0], 0x80 ^ (unsigned int)((lit >> ((size-1)*8)) & 0x0FFL)); } else { emitcode("ld", "a,%s", aopGet(AOP(left), size-1, FALSE)); - emitcode("xor", "a,#0x80"); + emit2("xor a,!immedbyte", 0x80); emitcode("ld", "%s,a", _fTmp[0]); fDidXor = TRUE; } if (AOP_TYPE(right) == AOP_LIT) { unsigned long lit = (unsigned long) floatFromVal(AOP(right)->aopu.aop_lit); - emitcode("ld", "%s,#0x%02x", _fTmp[1], + emit2("ld %s,!immedbyte", _fTmp[1], 0x80 ^ (unsigned int)((lit >> ((size-1)*8)) & 0x0FFL)); } else { emitcode("ld", "a,%s", aopGet(AOP(right), size-1, FALSE)); - emitcode("xor", "a,#0x80"); + emit2("xor a,!immedbyte", 0x80); emitcode("ld", "%s,a", _fTmp[1]); fDidXor = TRUE; } @@ -2027,15 +2759,16 @@ static void genCmp (operand *left,operand *right, } while (size--) { /* Do a long subtract */ - if (!sign || size) + if (!sign || size ) { MOVA(aopGet(AOP(left),offset,FALSE)); + } if (sign && size == 0) { emitcode("ld", "a,%s", _fTmp[0]); emitcode("sbc", "a,%s", _fTmp[1]); } else { /* Subtract through, propagating the carry */ - emitcode("sbc","a,%s",aopGet(AOP(right),offset++,FALSE)); + emitcode("sbc","a,%s ; 2",aopGet(AOP(right),offset++,FALSE)); } } } @@ -2043,15 +2776,15 @@ static void genCmp (operand *left,operand *right, 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 */ } } @@ -2062,7 +2795,7 @@ release: static void genCmpGt (iCode *ic, iCode *ifx) { operand *left, *right, *result; - link *letype , *retype; + sym_link *letype , *retype; int sign ; left = IC_LEFT(ic); @@ -2073,9 +2806,9 @@ static void genCmpGt (iCode *ic, iCode *ifx) 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); + aopOp (left,ic,FALSE, FALSE); + aopOp (right,ic,FALSE, FALSE); + aopOp (result,ic,TRUE, FALSE); genCmp(right, left, result, ifx, sign); @@ -2090,7 +2823,7 @@ static void genCmpGt (iCode *ic, iCode *ifx) static void genCmpLt (iCode *ic, iCode *ifx) { operand *left, *right, *result; - link *letype , *retype; + sym_link *letype , *retype; int sign ; left = IC_LEFT(ic); @@ -2102,9 +2835,9 @@ static void genCmpLt (iCode *ic, iCode *ifx) sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype)); /* assign the amsops */ - aopOp (left,ic,FALSE); - aopOp (right,ic,FALSE); - aopOp (result,ic,TRUE); + aopOp (left,ic,FALSE, FALSE); + aopOp (right,ic,FALSE, FALSE); + aopOp (result,ic,TRUE, FALSE); genCmp(left, right, result, ifx, sign); @@ -2135,15 +2868,31 @@ static void gencjneshort(operand *left, operand *right, symbol *lbl) /* if the right side is a literal then anything goes */ if (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR ) { - while (size--) { - emitcode("ld", "a,%s ; 2", aopGet(AOP(left),offset,FALSE)); - if ((AOP_TYPE(right) == AOP_LIT) && lit == 0) + if (lit == 0) { + emitcode("ld", "a,%s", aopGet(AOP(left), offset, FALSE)); + if (size > 1) { + size--; + offset++; + while (size--) { + emitcode("or", "a,%s", aopGet(AOP(left), offset, FALSE)); + } + } + else { emitcode("or", "a,a"); - else - emitcode("cp", "a,%s", aopGet(AOP(right),offset,FALSE)); - emitcode("jp", "nz," LABEL_STR , lbl->key+100); - offset++; - } + } + emit2("jp nz,!tlabel", lbl->key+100); + } + else { + while (size--) { + emitcode("ld", "a,%s ; 2", aopGet(AOP(left),offset,FALSE)); + if ((AOP_TYPE(right) == AOP_LIT) && lit == 0) + emitcode("or", "a,a"); + else + emitcode("cp", "a,%s", aopGet(AOP(right),offset,FALSE)); + emit2("jp nz,!tlabel", lbl->key+100); + offset++; + } + } } /* if the right side is in a register or in direct space or if the left is a pointer register & right is not */ @@ -2155,10 +2904,10 @@ static void gencjneshort(operand *left, operand *right, symbol *lbl) if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) && ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0)) /* PENDING */ - emitcode("jp","nz," LABEL_STR ,lbl->key+100); + emit2("jp nz,!tlabel", lbl->key+100); else { emitcode("cp", "%s ; 4", aopGet(AOP(right),offset,FALSE)); - emitcode("jp", "nz," LABEL_STR , lbl->key+100); + emit2("jp nz,!tlabel", lbl->key+100); } offset++; } @@ -2166,10 +2915,9 @@ static void gencjneshort(operand *left, operand *right, symbol *lbl) /* right is a pointer reg need both a & b */ /* PENDING: is this required? */ while(size--) { - char *l = aopGet(AOP(left),offset,FALSE); MOVA(aopGet(AOP(right),offset,FALSE)); - emitcode("cp", "%s ; 5", l); - emitcode("jr", "nz," LABEL_STR, lbl->key+100); + emitcode("cp", "%s ; 5", aopGet(AOP(left), offset, FALSE)); + emit2("!shortjp nz,!tlabel", lbl->key+100); offset++; } } @@ -2185,11 +2933,11 @@ static void gencjne(operand *left, operand *right, symbol *lbl) gencjneshort(left, right, lbl); /* PENDING: ?? */ - emitcode("ld","a,%s",one); - emitcode(_shortJP, LABEL_STR ,tlbl->key+100); - emitcode("", LABEL_STR ":",lbl->key+100); + emit2("ld a,!one"); + emit2("!shortjp !tlabel", tlbl->key+100); + emitLabel(lbl->key+100); emitcode("xor","a,a"); - emitcode("", LABEL_STR ":",tlbl->key+100); + emitLabel(tlbl->key+100); } /*-----------------------------------------------------------------*/ @@ -2199,9 +2947,9 @@ static void genCmpEq (iCode *ic, iCode *ifx) { operand *left, *right, *result; - aopOp((left=IC_LEFT(ic)),ic,FALSE); - aopOp((right=IC_RIGHT(ic)),ic,FALSE); - aopOp((result=IC_RESULT(ic)),ic,TRUE); + aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE); + aopOp((right=IC_RIGHT(ic)),ic,FALSE, FALSE); + aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE); /* Swap operands if it makes the operation easier. ie if: 1. Left is a literal. @@ -2217,20 +2965,20 @@ static void genCmpEq (iCode *ic, iCode *ifx) /* if they are both bit variables */ if (AOP_TYPE(left) == AOP_CRY && ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) { - assert(0); + wassert(0); } else { tlbl = newiTempLabel(NULL); gencjneshort(left, right, tlbl); if ( IC_TRUE(ifx) ) { - emitcode("jp", LABEL_STR ,IC_TRUE(ifx)->key+100); - emitcode("", LABEL_STR ":",tlbl->key+100); + emit2("jp !tlabel", IC_TRUE(ifx)->key+100); + emitLabel(tlbl->key+100); } else { /* PENDING: do this better */ symbol *lbl = newiTempLabel(NULL); - emitcode(_shortJP, LABEL_STR ,lbl->key+100); - emitcode("", LABEL_STR ":",tlbl->key+100); - emitcode("jp", LABEL_STR ,IC_FALSE(ifx)->key+100); - emitcode("", LABEL_STR ":",lbl->key+100); + emit2("!shortjp !tlabel", lbl->key+100); + emitLabel(tlbl->key+100); + emit2("jp !tlabel", IC_FALSE(ifx)->key+100); + emitLabel(lbl->key+100); } } /* mark the icode as generated */ @@ -2241,11 +2989,11 @@ static void genCmpEq (iCode *ic, iCode *ifx) /* if they are both bit variables */ if (AOP_TYPE(left) == AOP_CRY && ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) { - assert(0); + wassert(0); } else { gencjne(left,right,newiTempLabel(NULL)); if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) { - assert(0); + wassert(0); } if (ifx) { genIfxJump(ifx,"a"); @@ -2297,20 +3045,20 @@ static void genAndOp (iCode *ic) /* note here that && operations that are in an if statement are taken away by backPatchLabels only those used in arthmetic operations remain */ - aopOp((left=IC_LEFT(ic)),ic,FALSE); - aopOp((right=IC_RIGHT(ic)),ic,FALSE); - aopOp((result=IC_RESULT(ic)),ic,FALSE); + aopOp((left=IC_LEFT(ic)),ic,FALSE, TRUE); + aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE); + aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE); /* if both are bit variables */ if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY ) { - assert(0); + wassert(0); } else { tlbl = newiTempLabel(NULL); toBoolean(left); - emitcode(_shortJP, "z," LABEL_STR ,tlbl->key+100); + emit2("!shortjp z,!tlabel", tlbl->key+100); toBoolean(right); - emitcode("", LABEL_STR ":",tlbl->key+100); + emitLabel(tlbl->key+100); outBitAcc(result); } @@ -2330,20 +3078,20 @@ static void genOrOp (iCode *ic) /* note here that || operations that are in an if statement are taken away by backPatchLabels only those used in arthmetic operations remain */ - aopOp((left=IC_LEFT(ic)),ic,FALSE); - aopOp((right=IC_RIGHT(ic)),ic,FALSE); - aopOp((result=IC_RESULT(ic)),ic,FALSE); + aopOp((left=IC_LEFT(ic)),ic,FALSE, TRUE); + aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE); + aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE); /* if both are bit variables */ if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY ) { - assert(0); + wassert(0); } else { tlbl = newiTempLabel(NULL); toBoolean(left); - emitcode(_shortJP, "nz," LABEL_STR,tlbl->key+100); + emit2("!shortjp nz,!tlabel", tlbl->key+100); toBoolean(right); - emitcode("", LABEL_STR ":",tlbl->key+100); + emitLabel(tlbl->key+100); outBitAcc(result); } @@ -2380,14 +3128,14 @@ static void jmpTrueOrFalse (iCode *ic, symbol *tlbl) // ugly but optimized by peephole if(IC_TRUE(ic)){ symbol *nlbl = newiTempLabel(NULL); - emitcode("jp", LABEL_STR, nlbl->key+100); - emitcode("", LABEL_STR ":",tlbl->key+100); - emitcode("jp",LABEL_STR,IC_TRUE(ic)->key+100); - emitcode("", LABEL_STR ":",nlbl->key+100); + emit2("jp !tlabel", nlbl->key+100); + emitLabel(tlbl->key+100); + emit2("jp !tlabel", IC_TRUE(ic)->key+100); + emitLabel(nlbl->key+100); } else{ - emitcode("jp", LABEL_STR, IC_FALSE(ic)->key+100); - emitcode("", LABEL_STR ":",tlbl->key+100); + emit2("jp !tlabel", IC_FALSE(ic)->key+100); + emitLabel(tlbl->key+100); } ic->generated = 1; } @@ -2402,9 +3150,9 @@ static void genAnd (iCode *ic, iCode *ifx) unsigned long lit = 0L; int bytelit = 0; - aopOp((left = IC_LEFT(ic)),ic,FALSE); - aopOp((right= IC_RIGHT(ic)),ic,FALSE); - aopOp((result=IC_RESULT(ic)),ic,TRUE); + aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE); + aopOp((right= IC_RIGHT(ic)),ic,FALSE, FALSE); + aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE); #ifdef DEBUG_TYPE emitcode("","; Type res[%d] = l[%d]&r[%d]", @@ -2443,7 +3191,7 @@ static void genAnd (iCode *ic, iCode *ifx) size = AOP_SIZE(result); if (AOP_TYPE(left) == AOP_CRY){ - assert(0); + wassert(0); goto release ; } @@ -2459,7 +3207,7 @@ static void genAnd (iCode *ic, iCode *ifx) MOVA(aopGet(AOP(left),posbit>>3,FALSE)); // bit = left & 2^n if(size) { - assert(0); + wassert(0); emitcode("mov","c,acc.%d",posbit&0x07); } // if(left & 2^n) @@ -2469,7 +3217,7 @@ static void genAnd (iCode *ic, iCode *ifx) genIfxJump(ifx, buffer); } else { - assert(0); + wassert(0); } goto release; } @@ -2477,7 +3225,7 @@ static void genAnd (iCode *ic, iCode *ifx) symbol *tlbl = newiTempLabel(NULL); int sizel = AOP_SIZE(left); if(size) { - assert(0); + wassert(0); emitcode("setb","c"); } while(sizel--){ @@ -2485,14 +3233,17 @@ static void genAnd (iCode *ic, iCode *ifx) MOVA( aopGet(AOP(left),offset,FALSE)); // byte == 2^n ? if((posbit = isLiteralBit(bytelit)) != 0) { - assert(0); + wassert(0); emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100); } else{ if(bytelit != 0x0FFL) emitcode("and","a,%s", aopGet(AOP(right),offset,FALSE)); - emitcode("jr","nz, %05d$",tlbl->key+100); + else + /* For the flags */ + emit2("or a,a"); + emit2("!shortjp nz,!tlabel", tlbl->key+100); } } offset++; @@ -2500,7 +3251,7 @@ static void genAnd (iCode *ic, iCode *ifx) // bit = left & literal if (size){ emitcode("clr","c"); - emitcode("","%05d$:",tlbl->key+100); + emit2("!tlabeldef", tlbl->key+100); } // if(left & literal) else{ @@ -2526,25 +3277,26 @@ static void genAnd (iCode *ic, iCode *ifx) MOVA(aopGet(AOP(left),offset,FALSE)); emitcode("and","a,%s", aopGet(AOP(right),offset,FALSE)); - emitcode("ld", "%s,a", aopGet(AOP(left),offset,FALSE)); + aopPut(AOP(left), "a", offset); } } } else { if (AOP_TYPE(left) == AOP_ACC) { - assert(0); + wassert(0); } else { - MOVA(aopGet(AOP(right),offset,FALSE)); - emitcode("and","%s,a", - aopGet(AOP(left),offset,FALSE)); + MOVA(aopGet(AOP(left),offset,FALSE)); + emitcode("and","a,%s", + aopGet(AOP(right),offset,FALSE)); + aopPut(AOP(left), "a", offset); } } } } else { // left & result in different registers if(AOP_TYPE(result) == AOP_CRY){ - assert(0); + wassert(0); } else { for(;(size--);offset++) { // normal case @@ -2565,9 +3317,9 @@ static void genAnd (iCode *ic, iCode *ifx) if (AOP_TYPE(left) == AOP_ACC) emitcode("and","a,%s",aopGet(AOP(right),offset,FALSE)); else { - MOVA(aopGet(AOP(right),offset,FALSE)); + MOVA(aopGet(AOP(left),offset,FALSE)); emitcode("and","a,%s", - aopGet(AOP(left),offset,FALSE)); + aopGet(AOP(right),offset,FALSE)); } aopPut(AOP(result),"a",offset); } @@ -2590,9 +3342,9 @@ static void genOr (iCode *ic, iCode *ifx) int size, offset=0; unsigned long lit = 0L; - aopOp((left = IC_LEFT(ic)),ic,FALSE); - aopOp((right= IC_RIGHT(ic)),ic,FALSE); - aopOp((result=IC_RESULT(ic)),ic,TRUE); + aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE); + aopOp((right= IC_RIGHT(ic)),ic,FALSE, FALSE); + aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE); #if 1 emitcode("","; Type res[%d] = l[%d]&r[%d]", @@ -2631,14 +3383,14 @@ static void genOr (iCode *ic, iCode *ifx) size = AOP_SIZE(result); if (AOP_TYPE(left) == AOP_CRY){ - assert(0); + wassert(0); goto release ; } if((AOP_TYPE(right) == AOP_LIT) && (AOP_TYPE(result) == AOP_CRY) && (AOP_TYPE(left) != AOP_CRY)){ - assert(0); + wassert(0); goto release ; } @@ -2648,25 +3400,27 @@ static void genOr (iCode *ic, iCode *ifx) if(AOP_TYPE(right) == AOP_LIT){ if(((lit >> (offset*8)) & 0x0FFL) == 0x00L) continue; - else - emitcode("or","%s,%s; 5", - aopGet(AOP(left),offset,FALSE), + else { + MOVA(aopGet(AOP(left),offset,FALSE)); + emitcode("or","a,%s", aopGet(AOP(right),offset,FALSE)); + aopPut(AOP(result),"a", offset); + } } else { if (AOP_TYPE(left) == AOP_ACC) - emitcode("or","a,%s ; 6",aopGet(AOP(right),offset,FALSE)); + emitcode("or","a,%s",aopGet(AOP(right),offset,FALSE)); else { - MOVA(aopGet(AOP(right),offset,FALSE)); - emitcode("or","a,%s ; 7", - aopGet(AOP(left),offset,FALSE)); - aopPut(AOP(result),"a ; 8", offset); + MOVA(aopGet(AOP(left),offset,FALSE)); + emitcode("or","a,%s", + aopGet(AOP(right),offset,FALSE)); + aopPut(AOP(result),"a", offset); } } } } else { // left & result in different registers if(AOP_TYPE(result) == AOP_CRY){ - assert(0); + wassert(0); } else for(;(size--);offset++){ // normal case // result = left & right @@ -2683,9 +3437,9 @@ static void genOr (iCode *ic, iCode *ifx) if (AOP_TYPE(left) == AOP_ACC) emitcode("or","a,%s",aopGet(AOP(right),offset,FALSE)); else { - MOVA(aopGet(AOP(right),offset,FALSE)); + MOVA(aopGet(AOP(left),offset,FALSE)); emitcode("or","a,%s", - aopGet(AOP(left),offset,FALSE)); + aopGet(AOP(right),offset,FALSE)); } aopPut(AOP(result),"a",offset); /* PENDING: something weird is going on here. Add exception. */ @@ -2709,9 +3463,9 @@ static void genXor (iCode *ic, iCode *ifx) int size, offset=0; unsigned long lit = 0L; - aopOp((left = IC_LEFT(ic)),ic,FALSE); - aopOp((right= IC_RIGHT(ic)),ic,FALSE); - aopOp((result=IC_RESULT(ic)),ic,TRUE); + aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE); + aopOp((right= IC_RIGHT(ic)),ic,FALSE, FALSE); + aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE); /* if left is a literal & right is not then exchange them */ if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) || @@ -2741,14 +3495,14 @@ static void genXor (iCode *ic, iCode *ifx) size = AOP_SIZE(result); if (AOP_TYPE(left) == AOP_CRY){ - assert(0); + wassert(0); goto release ; } if((AOP_TYPE(right) == AOP_LIT) && (AOP_TYPE(result) == AOP_CRY) && (AOP_TYPE(left) != AOP_CRY)){ - assert(0); + wassert(0); goto release ; } @@ -2778,7 +3532,7 @@ static void genXor (iCode *ic, iCode *ifx) } else { // left & result in different registers if(AOP_TYPE(result) == AOP_CRY){ - assert(0); + wassert(0); } else for(;(size--);offset++){ // normal case // result = left & right @@ -2850,7 +3604,7 @@ static void genInline (iCode *ic) /*-----------------------------------------------------------------*/ static void genRRC (iCode *ic) { - assert(0); + wassert(0); } /*-----------------------------------------------------------------*/ @@ -2858,7 +3612,7 @@ static void genRRC (iCode *ic) /*-----------------------------------------------------------------*/ static void genRLC (iCode *ic) { - assert(0); + wassert(0); } /*-----------------------------------------------------------------*/ @@ -2868,16 +3622,11 @@ static void shiftR2Left2Result (operand *left, int offl, operand *result, int offr, int shCount, int sign) { - if(sameRegs(AOP(result), AOP(left)) && - ((offl + MSB16) == offr)){ - assert(0); - } else { - movLeft2Result(left, offl, result, offr, 0); - movLeft2Result(left, offl+1, result, offr+1, 0); - } + movLeft2Result(left, offl, result, offr, 0); + movLeft2Result(left, offl+1, result, offr+1, 0); if (sign) { - assert(0); + wassert(0); } else { /* if (AOP(result)->type == AOP_REG) {*/ @@ -2886,13 +3635,14 @@ static void shiftR2Left2Result (operand *left, int offl, symbol *tlbl , *tlbl1; char *l; + tlbl = newiTempLabel(NULL); + tlbl1 = newiTempLabel(NULL); + /* Left is already in result - so now do the shift */ if (shCount>1) { - emitcode("ld","a,#%u+1", shCount); - tlbl = newiTempLabel(NULL); - tlbl1 = newiTempLabel(NULL); - emitcode(_shortJP, LABEL_STR ,tlbl1->key+100); - emitcode("", LABEL_STR ":",tlbl->key+100); + emit2("ld a,!immedbyte+1", shCount); + emit2("!shortjp !tlabel", tlbl1->key+100); + emitLabel(tlbl->key+100); } emitcode("or", "a,a"); @@ -2902,9 +3652,9 @@ static void shiftR2Left2Result (operand *left, int offl, emitcode("rr","%s", l); } if (shCount>1) { - emitcode("", LABEL_STR ":",tlbl1->key+100); + emitLabel(tlbl1->key+100); emitcode("dec", "a"); - emitcode(_shortJP,"nz," LABEL_STR ,tlbl->key+100); + emit2("!shortjp nz,!tlabel", tlbl->key+100); } } } @@ -2917,7 +3667,7 @@ static void shiftL2Left2Result (operand *left, int offl, { if(sameRegs(AOP(result), AOP(left)) && ((offl + MSB16) == offr)){ - assert(0); + wassert(0); } else { /* Copy left into result */ movLeft2Result(left, offl, result, offr, 0); @@ -2931,13 +3681,14 @@ static void shiftL2Left2Result (operand *left, int offl, symbol *tlbl , *tlbl1; char *l; + tlbl = newiTempLabel(NULL); + tlbl1 = newiTempLabel(NULL); + /* Left is already in result - so now do the shift */ if (shCount>1) { - emitcode("ld","a,#%u+1", shCount); - tlbl = newiTempLabel(NULL); - tlbl1 = newiTempLabel(NULL); - emitcode(_shortJP, LABEL_STR ,tlbl1->key+100); - emitcode("", LABEL_STR ":",tlbl->key+100); + emit2("ld a,!immedbyte+1", shCount); + emit2("!shortjp !tlabel", tlbl1->key+100); + emitLabel(tlbl->key+100); } emitcode("or", "a,a"); @@ -2946,9 +3697,9 @@ static void shiftL2Left2Result (operand *left, int offl, emitcode("rl","%s", l); } if (shCount>1) { - emitcode("", LABEL_STR ":",tlbl1->key+100); + emitLabel(tlbl1->key+100); emitcode("dec", "a"); - emitcode(_shortJP,"nz," LABEL_STR ,tlbl->key+100); + emit2("!shortjp nz,!tlabel", tlbl->key+100); } } } @@ -3000,19 +3751,19 @@ static void AccRol (int shCount) /*-----------------------------------------------------------------*/ static void AccLsh (int shCount) { - if(shCount != 0){ - if(shCount == 1) + if(shCount != 0) { + if(shCount == 1) { emitcode("add","a,a"); - else - if(shCount == 2) { - emitcode("add","a,a"); - emitcode("add","a,a"); - } else { - /* rotate left accumulator */ - AccRol(shCount); - /* and kill the lower order bits */ - emitcode("and","a,#0x%02x", 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]); + } } } @@ -3038,29 +3789,30 @@ static void genlshTwo (operand *result,operand *left, int shCount) { int size = AOP_SIZE(result); - assert(size==2); + wassert(size==2); /* 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 { if(size == 1) { - assert(0); + wassert(0); } else { shiftL2Left2Result(left, LSB, result, LSB, shCount); @@ -3089,8 +3841,8 @@ static void genLeftShiftLiteral (operand *left, freeAsmop(right,NULL,ic); - aopOp(left,ic,FALSE); - aopOp(result,ic,FALSE); + aopOp(left,ic,FALSE, FALSE); + aopOp(result,ic,FALSE, FALSE); size = getSize(operandType(result)); @@ -3101,7 +3853,7 @@ static void genLeftShiftLiteral (operand *left, /* I suppose that the left size >= result size */ if (shCount == 0) { - assert(0); + wassert(0); } else if(shCount >= (size * 8)) @@ -3116,10 +3868,10 @@ static void genLeftShiftLiteral (operand *left, genlshTwo (result,left,shCount); break; case 4: - assert(0); + wassert(0); break; default: - assert(0); + wassert(0); } } freeAsmop(left,NULL,ic); @@ -3140,7 +3892,7 @@ static void genLeftShift (iCode *ic) left = IC_LEFT(ic); result = IC_RESULT(ic); - aopOp(right,ic,FALSE); + aopOp(right,ic,FALSE, FALSE); /* if the shift count is known then do it as efficiently as possible */ @@ -3156,8 +3908,8 @@ static void genLeftShift (iCode *ic) emitcode("ld","a,%s",aopGet(AOP(right),0,FALSE)); emitcode("inc","a"); freeAsmop (right,NULL,ic); - aopOp(left,ic,FALSE); - aopOp(result,ic,FALSE); + aopOp(left,ic,FALSE, FALSE); + aopOp(result,ic,FALSE, FALSE); /* now move the left to the result if they are not the same */ @@ -3188,23 +3940,24 @@ static void genLeftShift (iCode *ic) offset = 0 ; tlbl1 = newiTempLabel(NULL); - emitcode(_shortJP, LABEL_STR ,tlbl1->key+100); - emitcode("", LABEL_STR ":",tlbl->key+100); + emit2("!shortjp !tlabel", tlbl1->key+100); + emitLabel(tlbl->key+100); l = aopGet(AOP(result),offset,FALSE); emitcode("or", "a,a"); while (size--) { l = aopGet(AOP(result),offset++,FALSE); emitcode("rl","%s", l); } - emitcode("", LABEL_STR ":",tlbl1->key+100); + emitLabel(tlbl1->key+100); emitcode("dec", "a"); - emitcode(_shortJP,"nz," LABEL_STR ,tlbl->key+100); + emit2("!shortjp nz,!tlabel", tlbl->key+100); freeAsmop(left,NULL,ic); freeAsmop(result,NULL,ic); } -/* 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) { @@ -3212,8 +3965,8 @@ static void genrshOne (operand *result,operand *left, int shCount) int size = AOP_SIZE(result); char *l; - assert(size==1); - assert(shCount<8); + wassert(size==1); + wassert(shCount<8); l = aopGet(AOP(left),0,FALSE); if (AOP(result)->type == AOP_REG) { @@ -3237,15 +3990,10 @@ 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 */ - emitcode("and","a,#0x%02x", SRMask[shCount]); - } + /* rotate right accumulator */ + AccRol(8 - shCount); + /* and kill the higher order bits */ + emit2("and a,!immedbyte", SRMask[shCount]); } } @@ -3258,7 +4006,7 @@ static void shiftR1Left2Result (operand *left, int offl, { MOVA(aopGet(AOP(left),offl,FALSE)); if (sign) { - assert(0); + wassert(0); } else { AccRsh(shCount); @@ -3274,16 +4022,15 @@ static void genrshTwo (operand *result,operand *left, { /* if shCount >= 8 */ if (shCount >= 8) { - shCount -= 8 ; + shCount -= 8; if (shCount) { - assert(0); 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 { @@ -3304,8 +4051,8 @@ static void genRightShiftLiteral (operand *left, freeAsmop(right,NULL,ic); - aopOp(left,ic,FALSE); - aopOp(result,ic,FALSE); + aopOp(left,ic,FALSE, FALSE); + aopOp(result,ic,FALSE, FALSE); size = getSize(operandType(result)); @@ -3314,7 +4061,7 @@ static void genRightShiftLiteral (operand *left, /* I suppose that the left size >= result size */ if (shCount == 0) { - assert(0); + wassert(0); } else if(shCount >= (size * 8)) @@ -3330,10 +4077,10 @@ static void genRightShiftLiteral (operand *left, genrshTwo(result, left, shCount, FALSE); break; case 4: - assert(0); + wassert(0); break; default: - assert(0); + wassert(0); } } freeAsmop(left,NULL,ic); @@ -3345,67 +4092,129 @@ static void genRightShiftLiteral (operand *left, /*-----------------------------------------------------------------*/ static void genRightShift (iCode *ic) { - operand *left,*right, *result; + operand *right, *left, *result; + sym_link *retype ; + int size, offset, first = 1; + char *l; + bool is_signed; + + symbol *tlbl, *tlbl1 ; + + /* if signed then we do it the hard way preserve the + sign bit moving it inwards */ + retype = getSpec(operandType(IC_RESULT(ic))); + + is_signed = !SPEC_USIGN(retype); + + /* signed & unsigned types are treated the same : i.e. the + signed is NOT propagated inwards : quoting from the + ANSI - standard : "for E1 >> E2, is equivalent to division + by 2**E2 if unsigned or if it has a non-negative value, + otherwise the result is implementation defined ", MY definition + is that the sign does not get propagated */ right = IC_RIGHT(ic); left = IC_LEFT(ic); result = IC_RESULT(ic); - aopOp(right,ic,FALSE); + aopOp(right,ic,FALSE, FALSE); /* if the shift count is known then do it as efficiently as possible */ if (AOP_TYPE(right) == AOP_LIT) { - genRightShiftLiteral (left,right,result,ic); - return ; + genRightShiftLiteral(left,right,result,ic); + return; } - else { - assert(0); + + aopOp(left,ic,FALSE, FALSE); + aopOp(result,ic,FALSE, FALSE); + + /* now move the left to the result if they are not the + same */ + if (!sameRegs(AOP(left),AOP(result)) && + AOP_SIZE(result) > 1) { + + size = AOP_SIZE(result); + offset=0; + while (size--) { + l = aopGet(AOP(left),offset,FALSE); + aopPut(AOP(result),l,offset); + offset++; + } + } + + emitcode("ld", "a,%s",aopGet(AOP(right),0,FALSE)); + emitcode("inc","a"); + freeAsmop (right, NULL, ic); + + tlbl = newiTempLabel(NULL); + tlbl1= newiTempLabel(NULL); + size = AOP_SIZE(result); + offset = size - 1; + + emit2("!shortjp !tlabel", tlbl1->key+100); + emitLabel(tlbl->key+100); + while (size--) { + l = aopGet(AOP(result),offset--,FALSE); + if (first) { + if (is_signed) + emitcode("sra", "%s", l); + else + emitcode("srl", "%s", l); + first = 0; + } + else + emitcode("rr", "%s", l); } + emitLabel(tlbl1->key+100); + emitcode("dec", "a"); + emit2("!shortjp nz,!tlabel", tlbl->key+100); + + freeAsmop(left,NULL,ic); + freeAsmop(result,NULL,ic); } /*-----------------------------------------------------------------*/ -/* genGenPointerGet - gget value from generic pointer space */ +/* genGenPointerGet - get value from generic pointer space */ /*-----------------------------------------------------------------*/ static void genGenPointerGet (operand *left, operand *result, iCode *ic) { int size, offset ; - link *retype = getSpec(operandType(result)); - const char *ptr = "hl"; + sym_link *retype = getSpec(operandType(result)); + int pair = PAIR_HL; if (IS_GB) - ptr = "de"; + pair = PAIR_DE; - aopOp(left,ic,FALSE); - aopOp(result,ic,FALSE); - - if (isPair(AOP(left)) && (AOP_SIZE(result)==1)) { + aopOp(left,ic,FALSE, FALSE); + aopOp(result,ic,FALSE, FALSE); + + if (isPair(AOP(left)) && AOP_SIZE(result)==1) { /* Just do it */ - emitcode("ld", "a,(%s)", getPairName(AOP(left))); - aopPut(AOP(result),"a", 0); + if (isPtrPair(AOP(left))) + { + tsprintf(buffer, "!*pair", getPairName(AOP(left))); + aopPut(AOP(result), buffer, 0); + } + else { + emit2("ld a,!*pair", getPairName(AOP(left))); + aopPut(AOP(result),"a", 0); + } freeAsmop(left,NULL,ic); goto release; } /* For now we always load into IY */ /* if this is remateriazable */ - if (AOP_TYPE(left) == AOP_IMMD) - emitcode("ld","%s,%s", ptr, aopGet(AOP(left),0,TRUE)); - else { /* we need to get it byte by byte */ - if (IS_GB) { - emitcode("ld", "e,%s", aopGet(AOP(left), 0, FALSE)); - emitcode("ld", "d,%s", aopGet(AOP(left), 1, FALSE)); - } - else - fetchHL(AOP(left)); - } + fetchPair(pair, AOP(left)); + /* so iy now contains the address */ freeAsmop(left,NULL,ic); /* if bit then unpack */ if (IS_BITVAR(retype)) { - assert(0); + wassert(0); } else { size = AOP_SIZE(result); @@ -3414,14 +4223,15 @@ static void genGenPointerGet (operand *left, while (size--) { /* PENDING: make this better */ if (!IS_GB && AOP(result)->type == AOP_REG) { - aopPut(AOP(result),"(hl)",offset++); + aopPut(AOP(result), "!*hl", offset++); } else { - emitcode("ld", "a,(%s)", ptr, offset); + emit2("ld a,!*pair", _pairs[pair].name); aopPut(AOP(result),"a",offset++); } if (size) { - emitcode("inc", "%s", ptr); + emit2("inc %s", _pairs[pair].name); + _G.pairs[pair].offset++; } } } @@ -3436,7 +4246,7 @@ static void genGenPointerGet (operand *left, static void genPointerGet (iCode *ic) { operand *left, *result ; - link *type, *etype; + sym_link *type, *etype; left = IC_LEFT(ic); result = IC_RESULT(ic) ; @@ -3463,50 +4273,41 @@ static void genGenPointerSet (operand *right, operand *result, iCode *ic) { int size, offset ; - link *retype = getSpec(operandType(right)); - const char *ptr = "hl"; + sym_link *retype = getSpec(operandType(right)); + PAIR_ID pairId = PAIR_HL; - aopOp(result,ic,FALSE); - aopOp(right,ic,FALSE); + aopOp(result,ic,FALSE, FALSE); + aopOp(right,ic,FALSE, FALSE); if (IS_GB) - ptr = "de"; + pairId = PAIR_DE; /* Handle the exceptions first */ if (isPair(AOP(result)) && (AOP_SIZE(right)==1)) { /* Just do it */ char *l = aopGet(AOP(right), 0, FALSE); - MOVA(l); - emitcode("ld", "(%s),a", getPairName(AOP(result))); - freeAsmop(result,NULL,ic); + const char *pair = getPairName(AOP(result)); + if (canAssignToPtr(l) && isPtr(pair)) { + emit2("ld !*pair,%s", pair, l); + } + else { + MOVA(l); + emit2("ld !*pair,a", pair); + } goto release; } /* if the operand is already in dptr then we do nothing else we move the value to dptr */ if (AOP_TYPE(result) != AOP_STR) { - /* if this is remateriazable */ - if (AOP_TYPE(result) == AOP_IMMD) { - emitcode("", "; Error 2"); - emitcode("ld", "%s,%s", ptr, aopGet(AOP(result), 0, TRUE)); - } - else { /* we need to get it byte by byte */ - if (IS_GB) { - emitcode("ld", "e,%s", aopGet(AOP(result), 0, TRUE)); - emitcode("ld", "d,%s", aopGet(AOP(result), 1, TRUE)); - } - else { - /* PENDING: do this better */ - fetchHL(AOP(result)); - } - } + fetchPair(pairId, AOP(result)); } /* so hl know contains the address */ freeAsmop(result,NULL,ic); /* if bit then unpack */ if (IS_BITVAR(retype)) { - assert(0); + wassert(0); } else { size = AOP_SIZE(right); @@ -3515,14 +4316,15 @@ static void genGenPointerSet (operand *right, while (size--) { char *l = aopGet(AOP(right),offset,FALSE); if (isRegOrLit(AOP(right)) && !IS_GB) { - emitcode("ld", "(%s),%s", ptr, l); + emit2("ld !*pair,%s", _pairs[pairId].name, l); } else { MOVA(l); - emitcode("ld", "(%s),a", ptr, offset); + emit2("ld !*pair,a", _pairs[pairId].name); } if (size) { - emitcode("inc", ptr); + emitcode("inc", _pairs[pairId].name); + _G.pairs[pairId].offset++; } offset++; } @@ -3537,7 +4339,7 @@ static void genGenPointerSet (operand *right, static void genPointerSet (iCode *ic) { operand *right, *result ; - link *type, *etype; + sym_link *type, *etype; right = IC_RIGHT(ic); result = IC_RESULT(ic) ; @@ -3558,7 +4360,7 @@ static void genIfx (iCode *ic, iCode *popIc) operand *cond = IC_COND(ic); int isbit =0; - aopOp(cond,ic,FALSE); + aopOp(cond,ic,FALSE, TRUE); /* get the value into acc */ if (AOP_TYPE(cond) != AOP_CRY) @@ -3592,36 +4394,45 @@ static void genAddrOf (iCode *ic) { symbol *sym = OP_SYMBOL(IC_LEFT(ic)); - aopOp(IC_RESULT(ic),ic,FALSE); + aopOp(IC_RESULT(ic),ic,FALSE, FALSE); /* if the operand is on the stack then we need to get the stack offset of this variable */ - if (sym->onStack) { - /* if it has an offset then we need to compute it */ - if (IS_GB) { - emitcode("lda", "hl,%d+%d+%d(sp)", sym->stack, _pushed, _spoffset); + if (IS_GB) { + if (sym->onStack) { + spillCached(); + 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"); - aopPut(AOP(IC_RESULT(ic)), "e", 0); - aopPut(AOP(IC_RESULT(ic)), "d", 1); - goto end; } else { - emitcode("push", "de"); - emitcode("push", "ix"); - emitcode("pop", "hl"); - emitcode("ld", "de,#%d", sym->stack); - emitcode("add", "hl,de"); - emitcode("pop", "de"); + emit2("ld de,!hashedstr", sym->rname); } + aopPut(AOP(IC_RESULT(ic)), "e", 0); + aopPut(AOP(IC_RESULT(ic)), "d", 1); } else { - emitcode("ld", "hl,#%s", sym->rname); + spillCached(); + if (sym->onStack) { + /* if it has an offset then we need to compute it */ + 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 { + emitcode("ld", "hl,#%s", sym->rname); + } + aopPut(AOP(IC_RESULT(ic)), "l", 0); + aopPut(AOP(IC_RESULT(ic)), "h", 1); } - aopPut(AOP(IC_RESULT(ic)), "l", 0); - aopPut(AOP(IC_RESULT(ic)), "h", 1); -end: freeAsmop(IC_RESULT(ic),NULL,ic); } @@ -3645,8 +4456,8 @@ static void genAssign (iCode *ic) } #endif - aopOp(right,ic,FALSE); - aopOp(result,ic,TRUE); + aopOp(right,ic,FALSE, FALSE); + aopOp(result,ic,TRUE, FALSE); /* if they are the same registers */ if (sameRegs(AOP(right),AOP(result))) { @@ -3656,7 +4467,7 @@ static void genAssign (iCode *ic) /* if the result is a bit */ if (AOP_TYPE(result) == AOP_CRY) { - assert(0); + wassert(0); } /* general case */ @@ -3665,7 +4476,10 @@ static void genAssign (iCode *ic) if(AOP_TYPE(right) == AOP_LIT) lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit); - if((size > 1) && + if (isPair(AOP(result))) { + fetchPair(getPairId(AOP(result)), AOP(right)); + } + else if((size > 1) && (AOP_TYPE(result) != AOP_REG) && (AOP_TYPE(right) == AOP_LIT) && !IS_FLOAT(operandType(right)) && @@ -3685,7 +4499,7 @@ static void genAssign (iCode *ic) aopPut(AOP(result),"a",offset); } else { - aopPut(AOP(result), "#0", offset); + aopPut(AOP(result), zero, offset); } } else @@ -3695,7 +4509,7 @@ static void genAssign (iCode *ic) offset++; } } - else if (size == 2 && requiresHL(AOP(right)) && requiresHL(AOP(result))) { + else if (size == 2 && requiresHL(AOP(right)) && requiresHL(AOP(result)) && IS_GB) { /* Special case. Load into a and d, then load out. */ MOVA(aopGet(AOP(right), 0, FALSE)); emitcode("ld", "e,%s", aopGet(AOP(right), 1, FALSE)); @@ -3703,9 +4517,15 @@ static void genAssign (iCode *ic) aopPut(AOP(result), "e", 1); } else { while (size--) { - aopPut(AOP(result), - aopGet(AOP(right),offset,FALSE), - offset); + /* PENDING: do this check better */ + if (requiresHL(AOP(right)) && requiresHL(AOP(result))) { + MOVA(aopGet(AOP(right), offset, FALSE)); + aopPut(AOP(result), "a", offset); + } + else + aopPut(AOP(result), + aopGet(AOP(right),offset,FALSE), + offset); offset++; } } @@ -3723,28 +4543,28 @@ static void genJumpTab (iCode *ic) symbol *jtab; char *l; - aopOp(IC_JTCOND(ic),ic,FALSE); + aopOp(IC_JTCOND(ic),ic,FALSE, FALSE); /* get the condition into accumulator */ l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE); - MOVA(l); if (!IS_GB) emitcode("push", "de"); emitcode("ld", "e,%s", l); - emitcode("ld", "d,#0"); + emit2("ld d,!zero"); jtab = newiTempLabel(NULL); - emitcode("ld", "hl,#" LABEL_STR, jtab->key+100); + spillCached(); + emit2("ld hl,!immed!tlabel", jtab->key+100); emitcode("add", "hl,de"); emitcode("add", "hl,de"); emitcode("add", "hl,de"); freeAsmop(IC_JTCOND(ic),NULL,ic); if (!IS_GB) emitcode("pop", "de"); - emitcode("jp", "(hl)"); - emitcode("","%05d$:",jtab->key+100); + emit2("jp !*hl"); + emitLabel(jtab->key+100); /* now generate the jump labels */ for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab; jtab = setNextItem(IC_JTLABELS(ic))) - emitcode("jp", LABEL_STR, jtab->key+100); + emit2("jp !tlabel", jtab->key+100); } /*-----------------------------------------------------------------*/ @@ -3753,7 +4573,7 @@ static void genJumpTab (iCode *ic) static void genCast (iCode *ic) { operand *result = IC_RESULT(ic); - link *ctype = operandType(IC_LEFT(ic)); + sym_link *ctype = operandType(IC_LEFT(ic)); operand *right = IC_RIGHT(ic); int size, offset ; @@ -3761,12 +4581,12 @@ static void genCast (iCode *ic) if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic))) return ; - aopOp(right,ic,FALSE) ; - aopOp(result,ic,FALSE); + aopOp(right,ic,FALSE, FALSE); + aopOp(result,ic,FALSE, FALSE); /* if the result is a bit */ if (AOP_TYPE(result) == AOP_CRY) { - assert(0); + wassert(0); } /* if they are the same size : or less */ @@ -3792,7 +4612,7 @@ static void genCast (iCode *ic) #if 0 /* if the result is of type pointer */ if (IS_PTR(ctype)) { - assert(0); + wassert(0); } #endif @@ -3839,10 +4659,10 @@ static void genReceive (iCode *ic) if (isOperandInFarSpace(IC_RESULT(ic)) && ( OP_SYMBOL(IC_RESULT(ic))->isspilt || IS_TRUE_SYMOP(IC_RESULT(ic))) ) { - assert(0); + wassert(0); } else { accInUse++; - aopOp(IC_RESULT(ic),ic,FALSE); + aopOp(IC_RESULT(ic),ic,FALSE, FALSE); accInUse--; assignResultValue(IC_RESULT(ic)); } @@ -3862,13 +4682,12 @@ void genZ80Code (iCode *lic) if (IS_GB) { _fReturn = _gbz80_return; _fTmp = _gbz80_return; - _shortJP = "jr"; } else { _fReturn = _z80_return; _fTmp = _z80_return; - _shortJP = "jp"; } + tsprintf(zero, "!zero"); lineHead = lineCurr = NULL; @@ -4074,7 +4893,7 @@ void genZ80Code (iCode *lic) case GETHBIT: emitcode("", "; genHBIT"); - assert(0); + wassert(0); case LEFT_OP: emitcode("", "; genLeftShift"); @@ -4146,7 +4965,17 @@ void genZ80Code (iCode *lic) 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; + } }