X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Fz80%2Fgen.c;h=cc4a1176a15123fde268a76fc8455533a6548d75;hb=0eb1a3560011bc606e56c3cfac53fd49c9e4fbba;hp=0782a420cd41d6de258f8052d67edee9279175fa;hpb=d5fff77ffc8d8bf19e26c1f1689d08325e9521e4;p=fw%2Fsdcc diff --git a/src/z80/gen.c b/src/z80/gen.c index 0782a420..cc4a1176 100644 --- a/src/z80/gen.c +++ b/src/z80/gen.c @@ -16,6 +16,7 @@ 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 Michael Hope 2000 Based on the mcs51 generator - Sandeep Dutta . sandeep.dutta@usa.net (1998) @@ -30,6 +31,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 @@ -59,6 +61,7 @@ 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 ; @@ -77,6 +80,31 @@ 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 ) @@ -94,23 +122,42 @@ unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0, unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01, 0x00}; -static int _lastStack = 0; -static int _pushed = 0; -static int _spoffset; - #define LSB 0 #define MSB16 1 #define MSB24 2 #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 offset; + } stack; + int frameId; +} _G; + +static char *aopGet(asmop *aop, int offset, bool bit16); + +static char *_strdup(const char *s) +{ + char *ret; + ALLOC_ATOMIC(ret, strlen(s)+1); + strcpy(ret, s); + return ret; +} + /*-----------------------------------------------------------------*/ /* emitcode - writes the code into a file : for now it is simple */ /*-----------------------------------------------------------------*/ @@ -139,6 +186,178 @@ void emitcode (const char *inst, const char *fmt, ...) va_end(ap); } +typedef struct { + const char *szName; + const char *szFormat; +} TOKEN; + +static TOKEN _tokens[] = { + { "area", ".area %s" }, + { "global", ".globl %s" }, + { "labeldef", "%s::" }, + { "tlabeldef", "%05d$:" }, + { "fileprelude", "; Generated using the default tokens." }, + { "functionheader", + "; ---------------------------------\n" + "; Function %s\n" + "; ---------------------------------" + }, + { "functionlabeldef", "%s:" }, + { "pusha", + "\tpush af\n" + "\tpush bc\n" + "\tpush de\n" + "\tpush hl" + }, + { "di", "\tdi" }, + { "adjustsp", "\tlda sp,-%d(sp)" }, + { "prelude", "\tpush bc" }, + { "leave", + "\tpop bc\n" + "\tret" + }, + { "leavex", + "\tlda sp,%d(sp)\n" + "\tpop bc\n" + "\tret" + }, + { "hli", "(hl+) ; 2" }, + { "*hl", "(hl) ; 1" }, + { "ldahlsp", "lda hl,%d(sp)" }, + { "ldaspsp", "lda sp,%d(sp)" }, +}; + +/* 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"); + } +} +*/ + +#define NUM_TOKENS (sizeof(_tokens)/sizeof(_tokens[0])) + +static const TOKEN *_findToken(const char *szName) +{ + int i; + for (i=0; i < NUM_TOKENS; i++) { + if (!strcmp(_tokens[i].szName, szName)) + return _tokens + i; + } + return NULL; +} + +static va_list _iprintf(char *pInto, const char *szFormat, va_list ap) +{ + char *pStart = pInto; + char *sz = _strdup(szFormat); + + while (*sz) { + if (*sz == '%') { + switch (*++sz) { + /* See if it's a special emitter */ + case 'r': + wassert(0); + break; + default: + { + /* Scan out the arg and pass it on to sprintf */ + char *p = sz-1, tmp; + while (isdigit(*sz)) + sz++; + /* Skip the format */ + tmp = *++sz; + *sz = '\0'; + vsprintf(pInto, p, ap); + /* PENDING: Assume that the arg length was an int */ + va_arg(ap, int); + *sz = tmp; + } + } + pInto = pStart + strlen(pStart); + } + else { + *pInto++ = *sz++; + } + } + *pInto = '\0'; + + return ap; +} + +static void vtprintf(char *buffer, const char *szFormat, va_list ap) +{ + char *sz = _strdup(szFormat); + char *pInto = buffer, *p; + + buffer[0] = '\0'; + + while (*sz) { + if (*sz == '!') { + /* Start of a token. Search until the first + [non alplha, *] and call it a token. */ + char old; + const TOKEN *t; + p = ++sz; + while (isalpha(*sz) || *sz == '*') { + sz++; + } + old = *sz; + *sz = '\0'; + /* Now find the token in the token list */ + if ((t = _findToken(p))) { + ap = _iprintf(pInto, t->szFormat, ap); + pInto = buffer + strlen(buffer); + } + else { + printf("Cant find token \"%s\"\n", p); + wassert(0); + } + } + else { + *pInto++ = *sz++; + } + } + *pInto = '\0'; +} + +static void tprintf(char *buffer, const char *szFormat, ...) +{ + va_list ap; + + va_start(ap, szFormat); + vtprintf(buffer, szFormat, ap); +} + +static void emit2(const char *szFormat, ...) +{ + char buffer[256]; + va_list ap; + + va_start(ap, szFormat); + + vtprintf(buffer, szFormat, ap); + + lineCurr = (lineCurr ? + connectLine(lineCurr,newLineNode(buffer)) : + (lineHead = newLineNode(buffer))); + + lineCurr->isInline = inLine; + lineCurr->isDebug = debugLine; +} + const char *getPairName(asmop *aop) { if (aop->type == AOP_REG) { @@ -167,46 +386,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 */ /*-----------------------------------------------------------------*/ @@ -235,7 +472,6 @@ static asmop *aopForSym (iCode *ic,symbol *sym,bool result) if (sym->onStack || sym->iaccess) { sym->aop = aop = newAsmop(AOP_STK); aop->size = getSize(sym->type); - aop->aopu.aop_stk = sym->stack; return aop; } @@ -249,6 +485,7 @@ static asmop *aopForSym (iCode *ic,symbol *sym,bool result) return aop; } +#if 0 if (IS_GB) { /* if it is in direct space */ if (IN_DIRSPACE(space)) { @@ -259,12 +496,16 @@ static asmop *aopForSym (iCode *ic,symbol *sym,bool result) return aop; } } +#endif /* only remaining is far space */ /* in which case DPTR gets the address */ - sym->aop = aop = newAsmop(AOP_IY); - if (!IS_GB) - emitcode ("ld","iy,#%s ; a", sym->rname); + if (IS_GB) { + sym->aop = aop = newAsmop(AOP_HL); + } + else { + sym->aop = aop = newAsmop(AOP_IY); + } aop->size = getSize(sym->type); aop->aopu.aop_dir = sym->rname; @@ -525,11 +766,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 ) { @@ -543,23 +779,39 @@ 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 + wassert(offset == 0); /* 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); strcpy(rs,s); return rs; - case AOP_LIT: { value * val = aop->aopu.aop_lit; /* if it is a float then it gets tricky */ @@ -571,27 +823,176 @@ char *aopGetWordLong(asmop *aop, int offset, bool with_hash) ALLOC_ATOMIC(rs,strlen(buffer)+1); return strcpy (rs,buffer); } - assert(0); + wassert(0); return NULL; } + default: + return NULL; } - return NULL; } char *aopGetWord(asmop *aop, int offset) { - return aopGetWordLong(aop, offset, TRUE); + return aopGetLitWordLong(aop, offset, TRUE); +} + +bool isPtr(const char *s) +{ + 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 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].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 = _strdup(l); + _G.pairs[pairId].offset = offset; + } + /* Both a lit on the right and a true symbol on the left */ + if (offset) + emitcode("ld", "%s,#%s + %d", pair, l, offset); + else + emitcode("ld", "%s,#%s", 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); + emit2("ld a,!hli"); + emit2("ld h,!*hl"); + emit2("ld l,a"); + } + 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: + 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; + assert(pairId == PAIR_HL); + /* In some cases we can still inc or dec hl */ + if (_G.pairs[pairId].last_type == AOP_STK && abs(_G.pairs[pairId].offset - abso) < 3) { + adjustPair(_pairs[pairId].name, &_G.pairs[pairId].offset, abso); + } + else { + emit2("!ldahlsp", aop->aopu.aop_stk+offset + _G.stack.pushed + _G.stack.offset); + } + _G.pairs[pairId].offset = abso; + break; + } + default: + wassert(0); + } + _G.pairs[pairId].last_type = aop->type; +} + +static void emitLabel(int key) +{ + emit2("!tlabeldef yeah?", 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; @@ -600,10 +1001,10 @@ static char *aopGet (asmop *aop, int offset, bool bit16) switch (aop->type) { case AOP_IMMD: if (bit16) - sprintf (s,"#%s",aop->aopu.aop_immd); + sprintf (s,"#%s ; 5",aop->aopu.aop_immd); else if (offset) { - assert(offset == 1); + wassert(offset == 1); sprintf(s,"#>%s", aop->aopu.aop_immd); } @@ -615,7 +1016,7 @@ static char *aopGet (asmop *aop, int offset, bool bit16) 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); @@ -625,29 +1026,35 @@ static char *aopGet (asmop *aop, int offset, bool bit16) case AOP_REG: return aop->aopu.aop_reg[offset]->name; + case AOP_HL: + wassert(IS_GB); + emitcode("", ";3"); + setupPair(PAIR_HL, aop, offset); + tprintf(s, "!*hl"); + return _strdup(s); + case AOP_IY: - sprintf(s,"%d(iy)", offset); + wassert(IS_Z80); + setupPair(PAIR_IY, aop, offset); + tprintf(s,"!*iyx", offset); ALLOC_ATOMIC(rs,strlen(s)+1); strcpy(rs,s); return rs; case AOP_STK: if (IS_GB) { - /* We cant really optimise this as we cant afford to - change the flags. - */ - emitcode("lda", "hl,%d+%d+%d(sp)", aop->aopu.aop_stk+offset, _pushed, _spoffset); - sprintf(s, "(hl)"); + setupPair(PAIR_HL, aop, offset); + tprintf(s, "!*hl"); } else { - sprintf(s,"%d(ix) ; %u", aop->aopu.aop_stk+offset, offset); + tprintf(s,"!*ixx", aop->aopu.aop_stk+offset); } ALLOC_ATOMIC(rs,strlen(s)+1); strcpy(rs,s); return rs; case AOP_CRY: - assert(0); + wassert(0); case AOP_ACC: if (!offset) { @@ -661,12 +1068,10 @@ 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); } @@ -683,7 +1088,7 @@ bool isRegString(char *s) return FALSE; } -bool isConstant(char *s) +bool isConstant(const char *s) { return (*s == '#'); } @@ -713,7 +1118,7 @@ static void aopPut (asmop *aop, char *s, int offset) switch (aop->type) { case AOP_DIR: /* Direct. Hmmm. */ - assert(IS_GB); + wassert(IS_GB); emitcode("ld", "a,%s", s); emitcode("ld", "(%s+%d),a", aop->aopu.aop_dir, offset); break; @@ -727,7 +1132,8 @@ static void aopPut (asmop *aop, char *s, int offset) 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); @@ -735,14 +1141,25 @@ static void aopPut (asmop *aop, char *s, int offset) else emitcode("ld", "%d(iy),%s", offset, s); break; - + + case AOP_HL: + wassert(IS_GB); + if (!strcmp(s, "(hl)")) { + emitcode("ld", "a,(hl)"); + s = "a"; + } + emitcode("", ";2"); + setupPair(PAIR_HL, aop, offset); + emitcode("ld", "(hl),%s", s); + break; + case AOP_STK: if (IS_GB) { if (!strcmp("(hl)", s)) { emitcode("ld", "a,(hl)"); s = "a"; } - emitcode("lda", "hl,%d+%d+%d(sp)", aop->aopu.aop_stk+offset, _pushed, _spoffset); + setupPair(PAIR_HL, aop, offset); if (!canAssignToPtr(s)) { emitcode("ld", "a,%s", s); emitcode("ld", "(hl),a"); @@ -767,7 +1184,7 @@ static void aopPut (asmop *aop, char *s, int offset) emitcode("rla", ""); } else { /* In bit space but not in C - cant happen */ - assert(0); + wassert(0); } break; @@ -813,7 +1230,7 @@ int getDataSize(operand *op) size = AOP_SIZE(op); if(size == 3) { /* pointer */ - assert(0); + wassert(0); } return size; } @@ -832,7 +1249,7 @@ static void movLeft2Result (operand *left, int offl, aopPut(AOP(result),l,offr); } else { - assert(0); + wassert(0); } } } @@ -905,12 +1322,12 @@ static void genNot (iCode *ic) /* 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)); @@ -944,7 +1361,7 @@ static void genCpl (iCode *ic) 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)); @@ -976,7 +1393,7 @@ static void genUminus (iCode *ic) case */ if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { - assert(0); + wassert(0); goto release; } @@ -985,7 +1402,7 @@ static void genUminus (iCode *ic) /* if float then do float stuff */ if (IS_FLOAT(optype)) { - assert(0); + wassert(0); goto release; } @@ -1015,42 +1432,34 @@ release: freeAsmop(IC_RESULT(ic),NULL,ic); } -static bool requiresHL(asmop *aop) -{ - switch (aop->type) { - case AOP_STK: - return TRUE; - default: - return FALSE; - } -} - /*-----------------------------------------------------------------*/ /* assignResultValue - */ /*-----------------------------------------------------------------*/ void assignResultValue(operand * oper) { - int offset = 0; int size = AOP_SIZE(oper); + bool topInA = 0; - assert(size <= 2); - - while (size--) { - aopPut(AOP(oper),_fReturn[offset],offset); - offset++; - } -} + wassert(size <= 4); + topInA = requiresHL(AOP(oper)); -static void fetchHL(asmop *aop) -{ - if (IS_GB && requiresHL(aop)) { - emitcode("ld", "a,%s", aopGet(aop, 0, FALSE)); - emitcode("ld", "h,%s", aopGet(aop, 1, FALSE)); - emitcode("ld", "l,a"); + if (!IS_GB) + wassert(size <= 2); + if (IS_GB && size == 4 && requiresHL(AOP(oper))) { + /* We do it the hard way here. */ + emitcode("push", "hl"); + _G.stack.pushed += 2; + 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); + } } } @@ -1075,7 +1484,7 @@ static void genIpush (iCode *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; @@ -1085,7 +1494,7 @@ static void genIpush (iCode *ic) emitcode("ld", "a,%s", l); emitcode("push", "af"); emitcode("inc", "sp"); - _pushed++; + _G.stack.pushed++; } } return ; @@ -1100,23 +1509,15 @@ static void genIpush (iCode *ic) 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 ; 2"); + spillPair(PAIR_HL); + _G.stack.pushed += 2; goto release; } offset = size; @@ -1125,7 +1526,7 @@ static void genIpush (iCode *ic) emitcode("ld", "a,%s", l); emitcode("push", "af"); emitcode("inc", "sp"); - _pushed++; + _G.stack.pushed++; } } release: @@ -1154,6 +1555,7 @@ static void genIpop (iCode *ic) while (size--) { emitcode("dec", "sp"); emitcode("pop", "hl"); + spillPair(PAIR_HL); aopPut(AOP(IC_LEFT(ic)), "l", offset--); } } @@ -1165,8 +1567,6 @@ static void genIpop (iCode *ic) */ static void emitCall (iCode *ic, bool ispcall) { - int isPrintf = 0; - /* if caller saves & we have not saved then */ if (!ic->regsSaved) { /* PENDING */ @@ -1195,18 +1595,25 @@ static void emitCall (iCode *ic, bool ispcall) } if (ispcall) { - symbol *rlbl = newiTempLabel(NULL); - - emitcode("ld", "hl,#" LABEL_STR, (rlbl->key+100)); - emitcode("push", "hl"); - aopOp(IC_LEFT(ic),ic,FALSE); - emitcode("ld", "l,%s", aopGet(AOP(IC_LEFT(ic)), 0,FALSE)); - emitcode("ld", "h,%s", aopGet(AOP(IC_LEFT(ic)), 1,FALSE)); + + 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); + emitcode("ld", "hl,#" LABEL_STR, (rlbl->key+100)); + emitcode("push", "hl"); + _G.stack.pushed += 2; + + fetchHL(AOP(IC_LEFT(ic))); + emitcode("jp", "(hl)"); + emitcode("","%05d$:",(rlbl->key+100)); + _G.stack.pushed -= 2; + } freeAsmop(IC_LEFT(ic),NULL,ic); - - emitcode("jp", "(hl)"); - emitcode("","%05d$:",(rlbl->key+100)); } else { /* make the call */ @@ -1214,10 +1621,8 @@ static void emitCall (iCode *ic, bool ispcall) OP_SYMBOL(IC_LEFT(ic))->rname : OP_SYMBOL(IC_LEFT(ic))->name; emitcode("call", "%s", name); - if (!strcmp(name, "__printf")) - isPrintf = 1; - } + spillCached(); /* if we need assign a result value */ if ((IS_ITEMP(IC_RESULT(ic)) && @@ -1237,22 +1642,26 @@ 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; - emitcode("", ";parmBytes = %u\n", i); - if (isPrintf) - i+=2; - _pushed -= i; - if (i>6) { - emitcode("ld", "hl,#%d", i); - emitcode("add", "hl,sp"); - emitcode("ld", "sp,hl"); + _G.stack.pushed -= i; + if (IS_GB) { + emit2("!ldaspsp", i); } else { - while (i>1) { - emitcode("pop", "hl"); - i-=2; + spillCached(); + if (i>6) { + emitcode("ld", "hl,#%d", i); + emitcode("add", "hl,sp"); + emitcode("ld", "sp,hl"); } - if (i) - emitcode("inc", "sp"); + else { + while (i>1) { + emitcode("pop", "hl"); + i-=2; + } + if (i) + emitcode("inc", "sp"); + } + spillCached(); } } @@ -1296,49 +1705,36 @@ static int resultRemat (iCode *ic) /*-----------------------------------------------------------------*/ static void genFunction (iCode *ic) { - symbol *sym; + symbol *sym = OP_SYMBOL(IC_LEFT(ic)); link *fetype; nregssaved = 0; /* create the function header */ - emitcode(";","-----------------------------------------"); - emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name); - emitcode(";","-----------------------------------------"); + emit2("!functionheader", sym->name); + emit2("!functionlabeldef", sym->rname); - emitcode("","%s:",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"); - } + emit2("!prelude"); - _lastStack = sym->stack; + _G.stack.last = sym->stack; if (sym->stack) { - emitcode("ld", "hl,#-%d", sym->stack); - emitcode("add", "hl,sp"); - emitcode("ld", "sp,hl"); + emit2("!adjustsp", sym->stack); } - _spoffset = sym->stack; + _G.stack.offset = sym->stack; } /*-----------------------------------------------------------------*/ @@ -1349,11 +1745,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 */ @@ -1369,23 +1765,13 @@ 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"); + else + emit2("!leave"); } - _pushed = 0; - _spoffset = 0; + _G.stack.pushed = 0; + _G.stack.offset = 0; } /*-----------------------------------------------------------------*/ @@ -1409,14 +1795,25 @@ static void genRet (iCode *ic) size = AOP_SIZE(IC_LEFT(ic)); if ((size == 2) && ((l = aopGetWord(AOP(IC_LEFT(ic)), 0)))) { + if (IS_GB) { + emitcode("ld", "de,%s", l); + } + else { emitcode("ld", "hl,%s", l); + } } 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); @@ -1439,7 +1836,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); } /*-----------------------------------------------------------------*/ @@ -1457,7 +1854,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 */ @@ -1467,55 +1865,54 @@ 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("jp", "nz," LABEL_STR ,tlbl->key+100); + emitcode(_shortJP, "nz," LABEL_STR ,tlbl->key+100); emitcode("inc","%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; } - /* 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 ) @@ -1542,12 +1939,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("jp","z," LABEL_STR ,tlbl->key+100); + emitcode(_shortJP,"z," LABEL_STR ,tlbl->key+100); emitcode("ld","a,%s",one); - emitcode("", LABEL_STR ":",tlbl->key+100); + emitLabel(tlbl->key+100); outAcc(result); } } @@ -1584,14 +1981,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 @@ -1605,8 +2002,8 @@ static void genPlus (iCode *ic) 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 */ @@ -1617,6 +2014,14 @@ 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; + } + while(size--) { if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) { MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE)); @@ -1642,12 +2047,12 @@ static void genPlus (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); if (AOP_SIZE(IC_RESULT(ic)) == 3 && AOP_SIZE(IC_RIGHT(ic)) == 3 && !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) - assert(0); + wassert(0); release: @@ -1688,9 +2093,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 @@ -1744,7 +2149,7 @@ static void genMinus (iCode *ic) /* 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 ; } @@ -1788,7 +2193,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); @@ -1802,7 +2207,7 @@ release: static void genMult (iCode *ic) { /* Shouldn't occur - all done through function calls */ - assert(0); + wassert(0); } /*-----------------------------------------------------------------*/ @@ -1811,7 +2216,7 @@ static void genMult (iCode *ic) static void genDiv (iCode *ic) { /* Shouldn't occur - all done through function calls */ - assert(0); + wassert(0); } /*-----------------------------------------------------------------*/ @@ -1820,7 +2225,7 @@ static void genDiv (iCode *ic) static void genMod (iCode *ic) { /* Shouldn't occur - all done through function calls */ - assert(0); + wassert(0); } /*-----------------------------------------------------------------*/ @@ -1887,7 +2292,7 @@ static void genCmp (operand *left,operand *right, 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 @@ -1962,15 +2367,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)); } } } @@ -2070,15 +2476,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++; - } + } + emitcode("jp", "nz," LABEL_STR, 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)); + emitcode("jp", "nz," LABEL_STR , 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 */ @@ -2101,9 +2523,8 @@ 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("cp", "%s ; 5", aopGet(AOP(left), offset, FALSE)); emitcode("jr", "nz," LABEL_STR, lbl->key+100); offset++; } @@ -2121,10 +2542,10 @@ static void gencjne(operand *left, operand *right, symbol *lbl) /* PENDING: ?? */ emitcode("ld","a,%s",one); - emitcode("jp", LABEL_STR ,tlbl->key+100); - emitcode("", LABEL_STR ":",lbl->key+100); + emitcode(_shortJP, LABEL_STR ,tlbl->key+100); + emitLabel(lbl->key+100); emitcode("xor","a,a"); - emitcode("", LABEL_STR ":",tlbl->key+100); + emitLabel(tlbl->key+100); } /*-----------------------------------------------------------------*/ @@ -2152,20 +2573,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); + emitLabel(tlbl->key+100); } else { /* PENDING: do this better */ symbol *lbl = newiTempLabel(NULL); - emitcode("jp", LABEL_STR ,lbl->key+100); - emitcode("", LABEL_STR ":",tlbl->key+100); + emitcode(_shortJP, LABEL_STR ,lbl->key+100); + emitLabel(tlbl->key+100); emitcode("jp", LABEL_STR ,IC_FALSE(ifx)->key+100); - emitcode("", LABEL_STR ":",lbl->key+100); + emitLabel(lbl->key+100); } } /* mark the icode as generated */ @@ -2176,11 +2597,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"); @@ -2239,13 +2660,13 @@ static void genAndOp (iCode *ic) /* 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("jp","z," LABEL_STR ,tlbl->key+100); + emitcode(_shortJP, "z," LABEL_STR ,tlbl->key+100); toBoolean(right); - emitcode("", LABEL_STR ":",tlbl->key+100); + emitLabel(tlbl->key+100); outBitAcc(result); } @@ -2272,13 +2693,13 @@ static void genOrOp (iCode *ic) /* 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("jp","nz," LABEL_STR,tlbl->key+100); + emitcode(_shortJP, "nz," LABEL_STR,tlbl->key+100); toBoolean(right); - emitcode("", LABEL_STR,tlbl->key+100); + emitLabel(tlbl->key+100); outBitAcc(result); } @@ -2307,6 +2728,26 @@ int isLiteralBit(unsigned long lit) return 0; } +/*-----------------------------------------------------------------*/ +/* jmpTrueOrFalse - */ +/*-----------------------------------------------------------------*/ +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); + emitLabel(tlbl->key+100); + emitcode("jp",LABEL_STR,IC_TRUE(ic)->key+100); + emitLabel(nlbl->key+100); + } + else{ + emitcode("jp", LABEL_STR, IC_FALSE(ic)->key+100); + emitLabel(tlbl->key+100); + } + ic->generated = 1; +} + /*-----------------------------------------------------------------*/ /* genAnd - code for and */ /*-----------------------------------------------------------------*/ @@ -2358,7 +2799,7 @@ static void genAnd (iCode *ic, iCode *ifx) size = AOP_SIZE(result); if (AOP_TYPE(left) == AOP_CRY){ - assert(0); + wassert(0); goto release ; } @@ -2374,7 +2815,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) @@ -2384,7 +2825,7 @@ static void genAnd (iCode *ic, iCode *ifx) genIfxJump(ifx, buffer); } else { - assert(0); + wassert(0); } goto release; } @@ -2392,7 +2833,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--){ @@ -2400,7 +2841,7 @@ 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{ @@ -2420,11 +2861,7 @@ static void genAnd (iCode *ic, iCode *ifx) // if(left & literal) else{ if(ifx) -#if 0 jmpTrueOrFalse(ifx, tlbl); -#else - assert(0); -#endif goto release ; } } @@ -2451,7 +2888,7 @@ static void genAnd (iCode *ic, iCode *ifx) } else { if (AOP_TYPE(left) == AOP_ACC) { - assert(0); + wassert(0); } else { MOVA(aopGet(AOP(right),offset,FALSE)); @@ -2463,7 +2900,7 @@ static void genAnd (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 @@ -2550,14 +2987,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 ; } @@ -2567,10 +3004,12 @@ 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), - aopGet(AOP(right),offset,FALSE)); + else { + MOVA(aopGet(AOP(right),offset,FALSE)); + emitcode("or","a,%s; 5", + aopGet(AOP(left),offset,FALSE)); + aopPut(AOP(result),"a ; 8", offset); + } } else { if (AOP_TYPE(left) == AOP_ACC) emitcode("or","a,%s ; 6",aopGet(AOP(right),offset,FALSE)); @@ -2578,14 +3017,14 @@ static void genOr (iCode *ic, iCode *ifx) MOVA(aopGet(AOP(right),offset,FALSE)); emitcode("or","a,%s ; 7", aopGet(AOP(left),offset,FALSE)); - aopPut(AOP(result),"a ; 8",0); + aopPut(AOP(result),"a ; 8", 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 @@ -2660,14 +3099,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 ; } @@ -2697,7 +3136,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 @@ -2769,7 +3208,7 @@ static void genInline (iCode *ic) /*-----------------------------------------------------------------*/ static void genRRC (iCode *ic) { - assert(0); + wassert(0); } /*-----------------------------------------------------------------*/ @@ -2777,7 +3216,7 @@ static void genRRC (iCode *ic) /*-----------------------------------------------------------------*/ static void genRLC (iCode *ic) { - assert(0); + wassert(0); } /*-----------------------------------------------------------------*/ @@ -2789,14 +3228,14 @@ static void shiftR2Left2Result (operand *left, int offl, { if(sameRegs(AOP(result), AOP(left)) && ((offl + MSB16) == offr)){ - assert(0); + wassert(0); } else { 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) {*/ @@ -2810,8 +3249,8 @@ static void shiftR2Left2Result (operand *left, int offl, emitcode("ld","a,#%u+1", shCount); tlbl = newiTempLabel(NULL); tlbl1 = newiTempLabel(NULL); - emitcode("jp", LABEL_STR ,tlbl1->key+100); - emitcode("", LABEL_STR ":",tlbl->key+100); + emitcode(_shortJP, LABEL_STR ,tlbl1->key+100); + emitLabel(tlbl->key+100); } emitcode("or", "a,a"); @@ -2821,9 +3260,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("jp","nz," LABEL_STR ,tlbl->key+100); + emitcode(_shortJP,"nz," LABEL_STR ,tlbl->key+100); } } } @@ -2836,7 +3275,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); @@ -2855,8 +3294,8 @@ static void shiftL2Left2Result (operand *left, int offl, emitcode("ld","a,#%u+1", shCount); tlbl = newiTempLabel(NULL); tlbl1 = newiTempLabel(NULL); - emitcode("jp", LABEL_STR ,tlbl1->key+100); - emitcode("", LABEL_STR ":",tlbl->key+100); + emitcode(_shortJP, LABEL_STR ,tlbl1->key+100); + emitLabel(tlbl->key+100); } emitcode("or", "a,a"); @@ -2865,9 +3304,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("jp","nz," LABEL_STR ,tlbl->key+100); + emitcode(_shortJP,"nz," LABEL_STR ,tlbl->key+100); } } } @@ -2957,7 +3396,7 @@ 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) { @@ -2979,7 +3418,7 @@ static void genlshTwo (operand *result,operand *left, int shCount) /* 1 <= shCount <= 7 */ else { if(size == 1) { - assert(0); + wassert(0); } else { shiftL2Left2Result(left, LSB, result, LSB, shCount); @@ -3020,7 +3459,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)) @@ -3035,10 +3474,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); @@ -3107,22 +3546,23 @@ static void genLeftShift (iCode *ic) offset = 0 ; tlbl1 = newiTempLabel(NULL); - emitcode("jp", LABEL_STR ,tlbl1->key+100); - emitcode("", LABEL_STR ":",tlbl->key+100); + emitcode(_shortJP, LABEL_STR ,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("jp","nz," LABEL_STR ,tlbl->key+100); + emitcode(_shortJP,"nz," LABEL_STR ,tlbl->key+100); freeAsmop(left,NULL,ic); freeAsmop(result,NULL,ic); } +/*-----------------------------------------------------------------*/ /* genlshTwo - left shift two bytes by known amount != 0 */ /*-----------------------------------------------------------------*/ static void genrshOne (operand *result,operand *left, int shCount) @@ -3131,8 +3571,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) { @@ -3177,7 +3617,7 @@ static void shiftR1Left2Result (operand *left, int offl, { MOVA(aopGet(AOP(left),offl,FALSE)); if (sign) { - assert(0); + wassert(0); } else { AccRsh(shCount); @@ -3195,7 +3635,7 @@ static void genrshTwo (operand *result,operand *left, if (shCount >= 8) { shCount -= 8 ; if (shCount) { - assert(0); + wassert(0); shiftR1Left2Result(left, MSB16, result, LSB, shCount, sign); } @@ -3233,7 +3673,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)) @@ -3249,10 +3689,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); @@ -3264,7 +3704,26 @@ static void genRightShiftLiteral (operand *left, /*-----------------------------------------------------------------*/ static void genRightShift (iCode *ic) { - operand *left,*right, *result; + operand *right, *left, *result; + 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); @@ -3275,12 +3734,56 @@ static void genRightShift (iCode *ic) /* 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); + aopOp(result,ic,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; + + emitcode(_shortJP, LABEL_STR, tlbl1->key+100); + emitcode("", LABEL_STR ":", 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); } + emitcode("", LABEL_STR ":", tlbl1->key+100); + emitcode("dec", "a"); + emitcode(_shortJP, "nz," LABEL_STR, tlbl->key+100); + + freeAsmop(left,NULL,ic); + freeAsmop(result,NULL,ic); } /*-----------------------------------------------------------------*/ @@ -3291,31 +3794,39 @@ static void genGenPointerGet (operand *left, { int size, offset ; link *retype = getSpec(operandType(result)); + int pair = PAIR_HL; + + if (IS_GB) + pair = PAIR_DE; aopOp(left,ic,FALSE); aopOp(result,ic,FALSE); - - if (isPair(AOP(left)) && (AOP_SIZE(result)==1)) { + + 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))) + { + sprintf(buffer, "(%s)", getPairName(AOP(left))); + aopPut(AOP(result), buffer, 0); + } + else { + emitcode("ld", "a,(%s)", 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","hl,%s",aopGet(AOP(left),0,TRUE)); - else { /* we need to get it byte by byte */ - 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); @@ -3323,15 +3834,15 @@ static void genGenPointerGet (operand *left, while (size--) { /* PENDING: make this better */ - if (AOP(result)->type == AOP_REG) { + if (!IS_GB && AOP(result)->type == AOP_REG) { aopPut(AOP(result),"(hl)",offset++); } else { - emitcode("ld", "a,(hl)", offset); + emitcode("ld", "a,(%s)", _pairs[pair].name, offset); aopPut(AOP(result),"a",offset++); } if (size) { - emitcode("inc", "hl"); + emitcode("inc", "%s", _pairs[pair].name); } } } @@ -3374,39 +3885,40 @@ static void genGenPointerSet (operand *right, { int size, offset ; link *retype = getSpec(operandType(right)); + PAIR_ID pairId = PAIR_HL; aopOp(result,ic,FALSE); aopOp(right,ic,FALSE); + if (IS_GB) + 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)) { + emitcode("ld", "(%s),%s", pair, l); + } + else { + MOVA(l); + emitcode("ld", "(%s),a ; 1", 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", "hl,%s", aopGet(AOP(result), 0, TRUE)); - } - else { /* we need to get it byte by byte */ - /* 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); @@ -3414,16 +3926,15 @@ static void genGenPointerSet (operand *right, while (size--) { char *l = aopGet(AOP(right),offset,FALSE); - - if (isRegOrLit(AOP(right))) { - emitcode("ld", "(hl),%s", l); + if (isRegOrLit(AOP(right)) && !IS_GB) { + emitcode("ld", "(%s),%s ; 2", _pairs[pairId].name, l); } else { MOVA(l); - emitcode("ld", "(hl),a", offset); + emitcode("ld", "(%s),a ; 3", _pairs[pairId].name, offset); } if (size) { - emitcode("inc", "hl"); + emitcode("inc", _pairs[pairId].name); } offset++; } @@ -3498,31 +4009,32 @@ static void genAddrOf (iCode *ic) /* 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(sp)", sym->stack, _spoffset); + if (IS_GB) { + if (sym->onStack) { + spillCached(); + emit2("!ldahlsp", sym->stack + _G.stack.pushed + _G.stack.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"); + emitcode("ld", "de,#%s", 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 */ + 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); } @@ -3557,7 +4069,7 @@ static void genAssign (iCode *ic) /* if the result is a bit */ if (AOP_TYPE(result) == AOP_CRY) { - assert(0); + wassert(0); } /* general case */ @@ -3566,7 +4078,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)) && AOP_TYPE(right) == AOP_LIT) { + emitcode("ld", "%s,%s", getPairName(AOP(result)), aopGetWord(AOP(right), 0)); + } + else if((size > 1) && (AOP_TYPE(result) != AOP_REG) && (AOP_TYPE(right) == AOP_LIT) && !IS_FLOAT(operandType(right)) && @@ -3595,6 +4110,13 @@ static void genAssign (iCode *ic) offset); offset++; } + } + else if (size == 2 && requiresHL(AOP(right)) && requiresHL(AOP(result))) { + /* 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)); + aopPut(AOP(result), "a", 0); + aopPut(AOP(result), "e", 1); } else { while (size--) { aopPut(AOP(result), @@ -3626,14 +4148,16 @@ static void genJumpTab (iCode *ic) emitcode("ld", "e,%s", l); emitcode("ld", "d,#0"); jtab = newiTempLabel(NULL); + spillCached(); emitcode("ld", "hl,#" LABEL_STR, 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); + emitLabel(jtab->key+100); /* now generate the jump labels */ for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab; jtab = setNextItem(IC_JTLABELS(ic))) @@ -3659,7 +4183,7 @@ static void genCast (iCode *ic) /* if the result is a bit */ if (AOP_TYPE(result) == AOP_CRY) { - assert(0); + wassert(0); } /* if they are the same size : or less */ @@ -3685,7 +4209,7 @@ static void genCast (iCode *ic) #if 0 /* if the result is of type pointer */ if (IS_PTR(ctype)) { - assert(0); + wassert(0); } #endif @@ -3732,7 +4256,7 @@ 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); @@ -3755,10 +4279,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"; } lineHead = lineCurr = NULL; @@ -3965,7 +4491,7 @@ void genZ80Code (iCode *lic) case GETHBIT: emitcode("", "; genHBIT"); - assert(0); + wassert(0); case LEFT_OP: emitcode("", "; genLeftShift");