X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Fz80%2Fgen.c;h=b45d7a8516c2fe621b1cb7e75ce53458700e8f8e;hb=7b43aada0d2aa8d2f4a6a4be856e57b3fd8e32f6;hp=2818150f3b63aedbdad12a2ea27e8d9239313ce5;hpb=67a7d48073f066e319f43a8e8e4e827d5c88afd3;p=fw%2Fsdcc diff --git a/src/z80/gen.c b/src/z80/gen.c index 2818150f..b45d7a85 100644 --- a/src/z80/gen.c +++ b/src/z80/gen.c @@ -1,6 +1,6 @@ /*------------------------------------------------------------------------- gen.c - Z80 specific code generator. - + Michael Hope 2000 Based on the mcs51 generator - Sandeep Dutta . sandeep.dutta@usa.net (1998) @@ -50,22 +50,22 @@ No asm strings Includes long mul/div in code 2. Optimised memcpy for acc use 32102 102 226B - 3. Optimised strcpy for acc use 27819 117 2237 + 3. Optimised strcpy for acc use 27819 117 2237 3a Optimised memcpy fun - 4. Optimised strcmp fun 21999 149 2294 - 5. Optimised strcmp further 21660 151 228C - 6. Optimised memcpy by unroling 20885 157 2201 - 7. After turning loop induction on 19862 165 236D - 8. Same as 7 but with more info - 9. With asm optimised strings 17030 192 2223 + 4. Optimised strcmp fun 21999 149 2294 + 5. Optimised strcmp further 21660 151 228C + 6. Optimised memcpy by unroling 20885 157 2201 + 7. After turning loop induction on 19862 165 236D + 8. Same as 7 but with more info + 9. With asm optimised strings 17030 192 2223 10 and below are with asm strings off. - 10 Mucho optimisations 13562 201 1FCC + 10 Mucho optimisations 13562 201 1FCC Apparent advantage of turning on regparams: 1. Cost of push - Decent case is push of a constant + Decent case is push of a constant - ld hl,#n; push hl: (10+11)*nargs 2. Cost of pull from stack Using asm with ld hl, etc @@ -74,8 +74,8 @@ 3. Cost of fixing stack - pop hl*nargs 10*nargs - - So cost is (10+11+7+6+7+10)*nargs+10+11 + + So cost is (10+11+7+6+7+10)*nargs+10+11 = 51*nargs+21 = 123 for mul, div, strcmp, strcpy Saving of (98298+32766+32766+32766)*123 = 24181308 @@ -87,12 +87,6 @@ #include #include -#if defined(__BORLANDC__) || defined(_MSC_VER) -#define STRCASECMP stricmp -#else -#define STRCASECMP strcasecmp -#endif - #include "z80.h" #include "SDCCglobl.h" #include "SDCCpeeph.h" @@ -121,23 +115,23 @@ area. ix-0 is the top most local variable. */ -enum +enum { /* Set to enable debugging trace statements in the output assembly code. */ DISABLE_DEBUG = 0 }; static char *_z80_return[] = -{"l", "h", "e", "d"}; + {"l", "h", "e", "d"}; static char *_gbz80_return[] = -{"e", "d", "l", "h"}; + {"e", "d", "l", "h"}; static char *_fReceive[] = { "c", "b", "e", "d" }; static char **_fReturn; static char **_fTmp; -extern FILE *codeOutFile; +extern struct dbuf_s *codeOutBuf; enum { @@ -175,9 +169,9 @@ static struct }; // PENDING -#define ACC_NAME _pairs[PAIR_AF].h +#define ACC_NAME _pairs[PAIR_AF].h -enum +enum { LSB, MSB16, @@ -187,18 +181,18 @@ enum /** Code generator persistent data. */ -static struct +static struct { /** Used to optimised setting up of a pair by remebering what it contains and adjusting instead of reloading where possible. */ - struct + struct { AOP_TYPE last_type; const char *base; int offset; } pairs[NUM_PAIRS]; - struct + struct { int last; int pushed; @@ -222,7 +216,7 @@ static struct const char *lastFunctionName; iCode *current_iCode; bool preserveCarry; - + set *sendSet; struct @@ -231,7 +225,7 @@ static struct bool saved; } saves; - struct + struct { lineNode *head; lineNode *current; @@ -333,9 +327,9 @@ static bool isPairInUseNotInRet(PAIR_ID id, iCode *ic) { bitVect *rInUse; - + rInUse = bitVectCplAnd (bitVectCopy (ic->rMask), ic->rUsed); - + if (id == PAIR_DE) { return bitVectBitValue (rInUse, D_IDX) || bitVectBitValue(rInUse, E_IDX); @@ -362,7 +356,7 @@ getFreePairId (iCode *ic) { return PAIR_INVALID; } -} +} static void _tidyUp (char *buf) @@ -388,7 +382,7 @@ _tidyUp (char *buf) } static lineNode * -_newLineNode (char *line) +_newLineNode (const char *line) { lineNode *pl; @@ -401,18 +395,26 @@ _newLineNode (char *line) static void _vemit2 (const char *szFormat, va_list ap) { - char buffer[INITIAL_INLINEASM]; + struct dbuf_s dbuf; + char *buffer; + + dbuf_init(&dbuf, INITIAL_INLINEASM); - tvsprintf (buffer, sizeof(buffer), szFormat, ap); + dbuf_tvprintf (&dbuf, szFormat, ap); + + buffer = (char *)dbuf_c_str(&dbuf); _tidyUp (buffer); _G.lines.current = (_G.lines.current ? - connectLine (_G.lines.current, _newLineNode (buffer)) : - (_G.lines.head = _newLineNode (buffer))); + connectLine (_G.lines.current, _newLineNode (buffer)) : + (_G.lines.head = _newLineNode (buffer))); _G.lines.current->isInline = _G.lines.isInline; _G.lines.current->isDebug = _G.lines.isDebug; _G.lines.current->ic = _G.current_iCode; + _G.lines.current->isComment = (*buffer == ';'); + + dbuf_destroy(&dbuf); } static void @@ -430,6 +432,8 @@ emit2 (const char *szFormat,...) static void emitDebug (const char *szFormat,...) { + if (!options.verboseAsm) + return; if (!DISABLE_DEBUG) { va_list ap; @@ -492,11 +496,11 @@ _emit2 (const char *inst, const char *fmt,...) static void _emitMove(const char *to, const char *from) { - if (STRCASECMP(to, from) != 0) + if (STRCASECMP(to, from) != 0) { emit2("ld %s,%s", to, from); } - else + else { // Optimise it out. // Could leave this to the peephole, but sometimes the peephole is inhibited. @@ -509,7 +513,7 @@ aopDump(const char *plabel, asmop *aop) int i; char regbuf[9]; char *rbp = regbuf; - + emitDebug("; Dump of %s: type %s size %u", plabel, aopNames[aop->type], aop->size); switch (aop->type) { @@ -525,7 +529,7 @@ aopDump(const char *plabel, asmop *aop) break; case AOP_PAIRPTR: emitDebug("; pairptr = (%s)", _pairs[aop->aopu.aop_pairId].name); - + default: /* No information. */ break; @@ -551,17 +555,17 @@ getPairName (asmop * aop) if (aop->type == AOP_REG) { switch (aop->aopu.aop_reg[0]->rIdx) - { - case C_IDX: - return "bc"; - break; - case E_IDX: - return "de"; - break; - case L_IDX: - return "hl"; - break; - } + { + case C_IDX: + return "bc"; + break; + case E_IDX: + return "de"; + break; + case L_IDX: + return "hl"; + break; + } } else if (aop->type == AOP_STR || aop->type == AOP_HLREG) { @@ -584,22 +588,22 @@ 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 PAIR_BC; - } - if ((aop->aopu.aop_reg[0]->rIdx == E_IDX) && (aop->aopu.aop_reg[1]->rIdx == D_IDX)) - { - return PAIR_DE; - } - if ((aop->aopu.aop_reg[0]->rIdx == L_IDX) && (aop->aopu.aop_reg[1]->rIdx == H_IDX)) - { - return PAIR_HL; - } - } + { + if ((aop->aopu.aop_reg[0]->rIdx == C_IDX) && (aop->aopu.aop_reg[1]->rIdx == B_IDX)) + { + return PAIR_BC; + } + if ((aop->aopu.aop_reg[0]->rIdx == E_IDX) && (aop->aopu.aop_reg[1]->rIdx == D_IDX)) + { + return PAIR_DE; + } + if ((aop->aopu.aop_reg[0]->rIdx == L_IDX) && (aop->aopu.aop_reg[1]->rIdx == H_IDX)) + { + return PAIR_HL; + } + } else if (aop->type == AOP_STR || aop->type == AOP_HLREG) - { + { int i; for (i = 0; i < NUM_PAIRS; i++) { @@ -661,7 +665,7 @@ spillPair (PAIR_ID pairId) /* Given a register name, spill the pair (if any) the register is part of */ static void spillPairReg (const char *regname) -{ +{ if (strlen(regname)==1) { switch (*regname) @@ -699,9 +703,12 @@ _push (PAIR_ID pairId) static void _pop (PAIR_ID pairId) { - emit2 ("pop %s", _pairs[pairId].name); - _G.stack.pushed -= 2; - spillPair (pairId); + if (pairId != PAIR_INVALID) + { + emit2 ("pop %s", _pairs[pairId].name); + _G.stack.pushed -= 2; + spillPair (pairId); + } } void @@ -813,7 +820,7 @@ aopForSym (iCode * ic, symbol * sym, bool result, bool requires_a) sym->aop = aop = newAsmop (AOP_SFR); aop->aopu.aop_dir = sym->rname; aop->size = getSize (sym->type); - emitDebug ("; AOP_SFR for %s", sym->rname); + emitDebug ("; AOP_SFR for %s", sym->rname); return aop; } } @@ -867,14 +874,14 @@ aopForRemat (symbol * sym) { /* 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); - ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode; - continue; - } + { + /* PENDING: for re-target */ + sprintf (s, "0x%04x %c ", (int) operandLitValue (IC_RIGHT (ic)), + ic->op); + s += strlen (s); + ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode; + continue; + } /* we reached the end */ sprintf (s, "%s", OP_SYMBOL (IC_LEFT (ic))->rname); break; @@ -907,16 +914,16 @@ regsInCommon (operand * op1, operand * op2) { int j; if (!sym1->regs[i]) - continue; + continue; for (j = 0; j < sym2->nRegs; j++) - { - if (!sym2->regs[j]) - continue; + { + if (!sym2->regs[j]) + continue; - if (sym2->regs[j] == sym1->regs[i]) - return TRUE; - } + if (sym2->regs[j] == sym1->regs[i]) + return TRUE; + } } return FALSE; @@ -992,7 +999,7 @@ sameRegs (asmop * aop1, asmop * aop2) for (i = 0; i < aop1->size; i++) if (aop1->aopu.aop_reg[i] != - aop2->aopu.aop_reg[i]) + aop2->aopu.aop_reg[i]) return FALSE; return TRUE; @@ -1075,69 +1082,77 @@ aopOp (operand * op, iCode * ic, bool result, bool requires_a) { /* rematerialize it NOW */ if (sym->remat) - { - sym->aop = op->aop = aop = - aopForRemat (sym); - aop->size = getSize (sym->type); - return; - } + { + sym->aop = op->aop = aop = + aopForRemat (sym); + aop->size = getSize (sym->type); + return; + } if (sym->ruonly) - { - int i; - aop = op->aop = sym->aop = newAsmop (AOP_STR); - aop->size = getSize (sym->type); - for (i = 0; i < 4; i++) - aop->aopu.aop_str[i] = _fReturn[i]; - return; - } + { + int i; + aop = op->aop = sym->aop = newAsmop (AOP_STR); + aop->size = getSize (sym->type); + for (i = 0; i < 4; i++) + aop->aopu.aop_str[i] = _fReturn[i]; + return; + } if (sym->accuse) - { - if (sym->accuse == ACCUSE_A) - { - aop = op->aop = sym->aop = newAsmop (AOP_ACC); - aop->size = getSize (sym->type); + { + if (sym->accuse == ACCUSE_A) + { + aop = op->aop = sym->aop = newAsmop (AOP_ACC); + aop->size = getSize (sym->type); wassertl(aop->size == 1, "Internal error: Caching in A, but too big to fit in A"); aop->aopu.aop_str[0] = _pairs[PAIR_AF].h; - } - else if (sym->accuse == ACCUSE_SCRATCH) - { - aop = op->aop = sym->aop = newAsmop (AOP_HLREG); - aop->size = getSize (sym->type); + } + else if (sym->accuse == ACCUSE_SCRATCH) + { + aop = op->aop = sym->aop = newAsmop (AOP_HLREG); + aop->size = getSize (sym->type); wassertl(aop->size <= 2, "Internal error: Caching in HL, but too big to fit in HL"); aop->aopu.aop_str[0] = _pairs[PAIR_HL].l; aop->aopu.aop_str[1] = _pairs[PAIR_HL].h; - } + } else if (sym->accuse == ACCUSE_IY) { - aop = op->aop = sym->aop = newAsmop (AOP_HLREG); - aop->size = getSize (sym->type); + aop = op->aop = sym->aop = newAsmop (AOP_HLREG); + aop->size = getSize (sym->type); wassertl(aop->size <= 2, "Internal error: Caching in IY, but too big to fit in IY"); aop->aopu.aop_str[0] = _pairs[PAIR_IY].l; aop->aopu.aop_str[1] = _pairs[PAIR_IY].h; } - else + else { wassertl (0, "Marked as being allocated into A or HL but is actually in neither"); } - return; - } + return; + } if (sym->usl.spillLoc) { - if (getSize(sym->type) != getSize(sym->usl.spillLoc->type)) + asmop *oldAsmOp = NULL; + + if (getSize(sym->type) != getSize(sym->usl.spillLoc->type)) + { + /* force a new aop if sizes differ */ + oldAsmOp = sym->usl.spillLoc->aop; + sym->usl.spillLoc->aop = NULL; + } + sym->aop = op->aop = aop = + aopForSym (ic, sym->usl.spillLoc, result, requires_a); + if (getSize(sym->type) != getSize(sym->usl.spillLoc->type)) { - /* force a new aop if sizes differ */ - sym->usl.spillLoc->aop = NULL; - } - sym->aop = op->aop = aop = - aopForSym (ic, sym->usl.spillLoc, result, requires_a); - aop->size = getSize (sym->type); - return; - } - + /* Don't reuse the new aop, go with the last one */ + sym->usl.spillLoc->aop = oldAsmOp; + } + aop->size = getSize (sym->type); + return; + } + /* else must be a dummy iTemp */ sym->aop = op->aop = aop = newAsmop (AOP_DUMMY); aop->size = getSize (sym->type); @@ -1188,12 +1203,12 @@ dealloc: { op->aop = NULL; if (IS_SYMOP (op)) - { - OP_SYMBOL (op)->aop = NULL; - /* if the symbol has a spill */ - if (SPIL_LOC (op)) - SPIL_LOC (op)->aop = NULL; - } + { + OP_SYMBOL (op)->aop = NULL; + /* if the symbol has a spill */ + if (SPIL_LOC (op)) + SPIL_LOC (op)->aop = NULL; + } } } @@ -1225,31 +1240,31 @@ aopGetLitWordLong (asmop * aop, int offset, bool with_hash) /* PENDING: for re-target */ if (with_hash) { - tsprintf (buffer, sizeof(buffer), - "!hashedstr + %d", aop->aopu.aop_immd, offset); + tsprintf (buffer, sizeof(buffer), + "!hashedstr + %d", aop->aopu.aop_immd, offset); } else if (offset == 0) { tsprintf (buffer, sizeof(buffer), - "%s", aop->aopu.aop_immd); + "%s", aop->aopu.aop_immd); } else { - tsprintf (buffer, sizeof(buffer), - "%s + %d", aop->aopu.aop_immd, offset); + tsprintf (buffer, sizeof(buffer), + "%s + %d", aop->aopu.aop_immd, offset); } return traceAlloc(&_G.trace.aops, Safe_strdup(buffer)); case AOP_LIT: { - value *val = aop->aopu.aop_lit; - /* if it is a float then it gets tricky */ - /* otherwise it is fairly simple */ - if (!IS_FLOAT (val->type)) - { - unsigned long v = (unsigned long) floatFromVal (val); - - if (offset == 2) + value *val = aop->aopu.aop_lit; + /* if it is a float then it gets tricky */ + /* otherwise it is fairly simple */ + if (!IS_FLOAT (val->type)) + { + unsigned long v = ulFromVal (val); + + if (offset == 2) { v >>= 16; } @@ -1257,20 +1272,20 @@ aopGetLitWordLong (asmop * aop, int offset, bool with_hash) { // OK } - else + else { wassertl(0, "Encountered an invalid offset while fetching a literal"); } - if (with_hash) - tsprintf (buffer, sizeof(buffer), "!immedword", v); - else - tsprintf (buffer, sizeof(buffer), "!constword", v); + if (with_hash) + tsprintf (buffer, sizeof(buffer), "!immedword", v); + else + tsprintf (buffer, sizeof(buffer), "!constword", v); return traceAlloc(&_G.trace.aops, Safe_strdup(buffer)); - } - else - { + } + else + { union { float f; unsigned char c[4]; @@ -1286,13 +1301,13 @@ aopGetLitWordLong (asmop * aop, int offset, bool with_hash) #else i = fl.c[offset] | (fl.c[offset+1]<<8); #endif - if (with_hash) - tsprintf (buffer, sizeof(buffer), "!immedword", i); - else - tsprintf (buffer, sizeof(buffer), "!constword", i); + if (with_hash) + tsprintf (buffer, sizeof(buffer), "!immedword", i); + else + tsprintf (buffer, sizeof(buffer), "!constword", i); return traceAlloc(&_G.trace.aops, Safe_strdup(buffer)); - } + } } default: return NULL; @@ -1369,29 +1384,63 @@ fetchLitPair (PAIR_ID pairId, asmop * left, int offset) if (isPtr (pair)) { if (pairId == PAIR_HL || pairId == PAIR_IY) - { - if (_G.pairs[pairId].last_type == left->type) - { - if (_G.pairs[pairId].base && !strcmp (_G.pairs[pairId].base, base)) - { - if (pairId == PAIR_HL && abs (_G.pairs[pairId].offset - offset) < 3) - { - adjustPair (pair, &_G.pairs[pairId].offset, offset); - return; - } - if (pairId == PAIR_IY && (offset >= INT8MIN && offset <= INT8MAX)) - { - return; - } - } - } - } + { + if ((_G.pairs[pairId].last_type == AOP_IMMD && left->type == AOP_IMMD) || + (_G.pairs[pairId].last_type == AOP_IY && left->type == AOP_IY)) + { + if (_G.pairs[pairId].base && !strcmp (_G.pairs[pairId].base, base)) + { + if (pairId == PAIR_HL && abs (_G.pairs[pairId].offset - offset) < 3) + { + adjustPair (pair, &_G.pairs[pairId].offset, offset); + goto adjusted; + } + if (pairId == PAIR_IY && (offset >= INT8MIN && offset <= INT8MAX)) + { + goto adjusted; + } + } + } + } + + if (pairId == PAIR_HL && left->type == AOP_LIT && _G.pairs[pairId].last_type == AOP_LIT && + !IS_FLOAT (left->aopu.aop_lit->type) && offset == 0 && _G.pairs[pairId].offset == 0) + { + unsigned new_low, new_high, old_low, old_high; + unsigned long v_new = ulFromVal (left->aopu.aop_lit); + unsigned long v_old = strtoul (_G.pairs[pairId].base, NULL, 0); + new_low = (v_new >> 0) & 0xff; + new_high = (v_new >> 8) & 0xff; + old_low = (v_old >> 0) & 0xff; + old_high = (v_old >> 8) & 0xff; + + /* Change lower byte only. */ + if(new_high == old_high) + { + emit2("ld l, %s", aopGet (left, 0, FALSE)); + goto adjusted; + } + /* Change upper byte only. */ + else if(new_low == old_low) + { + emit2("ld h, %s", aopGet (left, 1, FALSE)); + goto adjusted; + } + } + + _G.pairs[pairId].last_type = left->type; _G.pairs[pairId].base = traceAlloc(&_G.trace.aops, Safe_strdup (base)); _G.pairs[pairId].offset = offset; } /* Both a lit on the right and a true symbol on the left */ emit2 ("ld %s,!hashedstr", pair, l); + return; + +adjusted: + _G.pairs[pairId].last_type = left->type; + _G.pairs[pairId].base = traceAlloc(&_G.trace.aops, Safe_strdup (base)); + _G.pairs[pairId].offset = offset; } static PAIR_ID @@ -1429,7 +1478,7 @@ fetchPairLong (PAIR_ID pairId, asmop * aop, iCode *ic, int offset) if (isLitWord (aop)) { fetchLitPair (pairId, aop, offset); } - else + else { if (getPairId (aop) == pairId) { @@ -1493,10 +1542,20 @@ fetchPairLong (PAIR_ID pairId, asmop * aop, iCode *ic, int offset) emit2("push %s", _pairs[getPairId(aop)].name); emit2("pop %s", _pairs[pairId].name); } - else + else { - emit2 ("ld %s,%s", _pairs[pairId].l, aopGet (aop, offset, FALSE)); - emit2 ("ld %s,%s", _pairs[pairId].h, aopGet (aop, offset + 1, FALSE)); + /* Operand resides (partially) in the pair */ + if(!strcmp(aopGet (aop, offset + 1, FALSE), _pairs[pairId].l)) + { + emit2 ("ld a,%s", aopGet (aop, offset + 1, FALSE)); + emit2 ("ld %s,%s", _pairs[pairId].l, aopGet (aop, offset, FALSE)); + emit2 ("ld %s,a", _pairs[pairId].h); + } + else + { + emit2 ("ld %s,%s", _pairs[pairId].l, aopGet (aop, offset, FALSE)); + emit2 ("ld %s,%s", _pairs[pairId].h, aopGet (aop, offset + 1, FALSE)); + } } /* PENDING: check? */ if (pairId == PAIR_HL) @@ -1526,7 +1585,7 @@ setupPairFromSP (PAIR_ID id, int offset) _push (PAIR_AF); offset += 2; } - + if (offset < INT8MIN || offset > INT8MAX) { emit2 ("ld hl,!immedword", offset); @@ -1556,7 +1615,7 @@ setupPair (PAIR_ID pairId, asmop * aop, int offset) case AOP_HL: wassertl (pairId == PAIR_HL, "AOP_HL must be in HL"); - + fetchLitPair (pairId, aop, offset); _G.pairs[pairId].offset = offset; break; @@ -1566,7 +1625,7 @@ setupPair (PAIR_ID pairId, asmop * aop, int offset) wassertl (pairId == PAIR_IY || pairId == PAIR_HL, "The Z80 extended stack must be in IY or HL"); { - int offset = aop->aopu.aop_stk + _G.stack.offset; + int offset = aop->aopu.aop_stk + _G.stack.offset; if (_G.pairs[pairId].last_type == aop->type && _G.pairs[pairId].offset == offset) @@ -1591,25 +1650,25 @@ setupPair (PAIR_ID pairId, asmop * aop, int offset) case AOP_STK: { - /* Doesnt include _G.stack.pushed */ - int abso = aop->aopu.aop_stk + offset + _G.stack.offset; - - if (aop->aopu.aop_stk > 0) - { - abso += _G.stack.param_offset; - } - assert (pairId == PAIR_HL); - /* In some cases we can still inc or dec hl */ - if (_G.pairs[pairId].last_type == AOP_STK && abs (_G.pairs[pairId].offset - abso) < 3) - { - adjustPair (_pairs[pairId].name, &_G.pairs[pairId].offset, abso); - } - else - { + /* Doesnt include _G.stack.pushed */ + int abso = aop->aopu.aop_stk + offset + _G.stack.offset; + + if (aop->aopu.aop_stk > 0) + { + abso += _G.stack.param_offset; + } + assert (pairId == PAIR_HL); + /* In some cases we can still inc or dec hl */ + if (_G.pairs[pairId].last_type == AOP_STK && abs (_G.pairs[pairId].offset - abso) < 3) + { + adjustPair (_pairs[pairId].name, &_G.pairs[pairId].offset, abso); + } + else + { setupPairFromSP (PAIR_HL, abso + _G.stack.pushed); - } - _G.pairs[pairId].offset = abso; - break; + } + _G.pairs[pairId].offset = abso; + break; } case AOP_PAIRPTR: @@ -1617,17 +1676,26 @@ setupPair (PAIR_ID pairId, asmop * aop, int offset) genMovePairPair(aop->aopu.aop_pairId, pairId); adjustPair (_pairs[pairId].name, &_G.pairs[pairId].offset, offset); break; - + default: wassert (0); } _G.pairs[pairId].last_type = aop->type; } +/* Can be used for local labels where Code generation takes care of spilling */ +static void +emitLabelNoSpill (int key) +{ + emit2 ("!tlabeldef", key); + _G.lines.current->isLabel = 1; +} + static void emitLabel (int key) { emit2 ("!tlabeldef", key); + _G.lines.current->isLabel = 1; spillCached (); } @@ -1642,7 +1710,7 @@ aopGet (asmop * aop, int offset, bool bit16) /* 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) + aop->type != AOP_LIT) { tsprintf (buffer, sizeof(buffer), "!zero"); return traceAlloc(&_G.trace.aops, Safe_strdup(buffer)); @@ -1654,26 +1722,26 @@ aopGet (asmop * aop, int offset, bool bit16) case AOP_DUMMY: tsprintf (buffer, sizeof(buffer), "!zero"); return traceAlloc(&_G.trace.aops, Safe_strdup(buffer)); - + case AOP_IMMD: /* PENDING: re-target */ if (bit16) - tsprintf (buffer, sizeof(buffer), "!immedwords", aop->aopu.aop_immd); + tsprintf (buffer, sizeof(buffer), "!immedwords", aop->aopu.aop_immd); else - switch (offset) - { - case 2: - tsprintf (buffer, sizeof(buffer), "!bankimmeds", aop->aopu.aop_immd); - break; - case 1: - tsprintf (buffer, sizeof(buffer), "!msbimmeds", aop->aopu.aop_immd); - break; - case 0: - tsprintf (buffer, sizeof(buffer), "!lsbimmeds", aop->aopu.aop_immd); - break; - default: - wassertl (0, "Fetching from beyond the limits of an immediate value."); - } + switch (offset) + { + case 2: + tsprintf (buffer, sizeof(buffer), "!bankimmeds", aop->aopu.aop_immd); + break; + case 1: + tsprintf (buffer, sizeof(buffer), "!msbimmeds", aop->aopu.aop_immd); + break; + case 0: + tsprintf (buffer, sizeof(buffer), "!lsbimmeds", aop->aopu.aop_immd); + break; + default: + wassertl (0, "Fetching from beyond the limits of an immediate value."); + } return traceAlloc(&_G.trace.aops, Safe_strdup(buffer)); @@ -1697,9 +1765,9 @@ aopGet (asmop * aop, int offset, bool bit16) { /*.p.t.20030716 handling for i/o port read access for Z80 */ if( aop->paged ) { /* banked mode */ - /* reg A goes to address bits 15-8 during "in a,(x)" instruction */ - emit2( "ld a,!msbimmeds", aop->aopu.aop_dir); - emit2( "in a,(!lsbimmeds)", aop->aopu.aop_dir); + /* reg A goes to address bits 15-8 during "in a,(x)" instruction */ + emit2( "ld a,!msbimmeds", aop->aopu.aop_dir); + emit2( "in a,(!lsbimmeds)", aop->aopu.aop_dir); } else if( z80_opts.port_mode == 180 ) { /* z180 in0/out0 mode */ @@ -1709,7 +1777,7 @@ aopGet (asmop * aop, int offset, bool bit16) { /* 8 bit mode */ emit2( "in a,(%s)", aop->aopu.aop_dir ); } - + SNPRINTF (buffer, sizeof(buffer), "a"); return traceAlloc(&_G.trace.aops, Safe_strdup(buffer)); @@ -1741,17 +1809,17 @@ aopGet (asmop * aop, int offset, bool bit16) case AOP_STK: if (IS_GB) - { - setupPair (PAIR_HL, aop, offset); - tsprintf (buffer, sizeof(buffer), "!*hl"); - } + { + setupPair (PAIR_HL, aop, offset); + tsprintf (buffer, sizeof(buffer), "!*hl"); + } else - { - if (aop->aopu.aop_stk >= 0) - offset += _G.stack.param_offset; - tsprintf (buffer, sizeof(buffer), - "!*ixx", aop->aopu.aop_stk + offset); - } + { + if (aop->aopu.aop_stk >= 0) + offset += _G.stack.param_offset; + tsprintf (buffer, sizeof(buffer), + "!*ixx", aop->aopu.aop_stk + offset); + } return traceAlloc(&_G.trace.aops, Safe_strdup(buffer)); @@ -1760,9 +1828,9 @@ aopGet (asmop * aop, int offset, bool bit16) case AOP_ACC: if (!offset) - { - return "a"; - } + { + return "a"; + } else { tsprintf(buffer, sizeof(buffer), "!zero"); @@ -1779,11 +1847,11 @@ aopGet (asmop * aop, int offset, bool bit16) case AOP_SIMPLELIT: { unsigned long v = aop->aopu.aop_simplelit; - + v >>= (offset * 8); - tsprintf (buffer, sizeof(buffer), - "!immedbyte", (unsigned int) v & 0xff); - + tsprintf (buffer, sizeof(buffer), + "!immedbyte", (unsigned int) v & 0xff); + return traceAlloc(&_G.trace.aops, Safe_strdup(buffer)); } case AOP_STR: @@ -1793,14 +1861,12 @@ aopGet (asmop * aop, int offset, bool bit16) case AOP_PAIRPTR: setupPair (aop->aopu.aop_pairId, aop, offset); if (aop->aopu.aop_pairId==PAIR_IX) - SNPRINTF (buffer, sizeof(buffer), - "!*ixx", 0); + tsprintf (buffer, sizeof(buffer), "!*ixx", offset); else if (aop->aopu.aop_pairId==PAIR_IY) - SNPRINTF (buffer, sizeof(buffer), - "!*iyx", 0); + tsprintf (buffer, sizeof(buffer), "!*iyx", offset); else - SNPRINTF (buffer, sizeof(buffer), - "(%s)", _pairs[aop->aopu.aop_pairId].name); + SNPRINTF (buffer, sizeof(buffer), + "(%s)", _pairs[aop->aopu.aop_pairId].name); return traceAlloc(&_G.trace.aops, Safe_strdup(buffer)); @@ -1853,7 +1919,7 @@ aopPut (asmop * aop, const char *s, int offset) if (aop->size && offset > (aop->size - 1)) { werror (E_INTERNAL_ERROR, __FILE__, __LINE__, - "aopPut got offset > aop->size"); + "aopPut got offset > aop->size"); exit (0); } @@ -1868,78 +1934,76 @@ aopPut (asmop * aop, const char *s, int offset) case AOP_DUMMY: _moveA (s); /* in case s is volatile */ break; - + case AOP_DIR: /* Direct. Hmmm. */ wassert (IS_GB); if (strcmp (s, "a")) - emit2 ("ld a,%s", s); + emit2 ("ld a,%s", s); emit2 ("ld (%s+%d),a", aop->aopu.aop_dir, offset); break; case AOP_SFR: if( IS_GB ) - { - // wassert (IS_GB); - if (strcmp (s, "a")) - emit2 ("ld a,%s", s); - emit2 ("ldh (%s+%d),a", aop->aopu.aop_dir, offset); - } + { + // wassert (IS_GB); + if (strcmp (s, "a")) + emit2 ("ld a,%s", s); + emit2 ("ldh (%s+%d),a", aop->aopu.aop_dir, offset); + } else - { /*.p.t.20030716 handling for i/o port read access for Z80 */ - if( aop->paged ) - { /* banked mode */ - if( aop->bcInUse ) emit2( "push bc" ); + { /*.p.t.20030716 handling for i/o port read access for Z80 */ + if (aop->paged) + { /* banked mode */ + if (aop->bcInUse) + emit2( "push bc" ); + + if (strlen(s) != 1 + || (s[0] != 'a' && s[0] != 'd' && s[0] != 'e' + && s[0] != 'h' && s[0] != 'l')) + { + emit2( "ld a,%s", s ); + s = "a"; + } - emit2( "ld bc,#%s", aop->aopu.aop_dir ); + emit2( "ld bc,#%s", aop->aopu.aop_dir ); + emit2( "out (c),%s", s ); - if(( s[0] == '#' ) /* immediate number */ - ||( s[0] == '(' ) /* indirect register (ix or iy ??)*/ - ||( isdigit( s[0] )))/* indirect register with offset (ix or iy ??)*/ - { - emit2( "ld a,%s", s ); - emit2( "out (c),a" ); - } - else - { - emit2( "out (c),%s", s ); - } - - if( aop->bcInUse ) - emit2( "pop bc" ); + if( aop->bcInUse ) + emit2( "pop bc" ); + else + spillPair (PAIR_BC); + } + else if( z80_opts.port_mode == 180 ) + { /* z180 in0/out0 mode */ + emit2( "ld a,%s", s ); + emit2( "out0 (%s),a", aop->aopu.aop_dir ); + } else - spillPair (PAIR_BC); - } - else if( z80_opts.port_mode == 180 ) - { /* z180 in0/out0 mode */ - emit2( "ld a,%s", s ); - emit2( "out0 (%s),a", aop->aopu.aop_dir ); - } - else - { /* 8 bit mode */ - emit2( "ld a,%s", s ); - emit2( "out (%s),a", aop->aopu.aop_dir ); + { /* 8 bit mode */ + emit2( "ld a,%s", s ); + emit2( "out (%s),a", aop->aopu.aop_dir ); + } } - } break; case AOP_REG: if (!strcmp (s, "!*hl")) - emit2 ("ld %s,!*hl", aop->aopu.aop_reg[offset]->name); + emit2 ("ld %s,!*hl", aop->aopu.aop_reg[offset]->name); else - emit2 ("ld %s,%s", - aop->aopu.aop_reg[offset]->name, s); + emit2 ("ld %s,%s", + aop->aopu.aop_reg[offset]->name, s); spillPairReg(aop->aopu.aop_reg[offset]->name); break; case AOP_IY: wassert (!IS_GB); if (!canAssignToPtr (s)) - { - emit2 ("ld a,%s", s); + { + emit2 ("ld a,%s", s); setupPair (PAIR_IY, aop, offset); - emit2 ("ld !*iyx,a", offset); - } + emit2 ("ld !*iyx,a", offset); + } else { setupPair (PAIR_IY, aop, offset); @@ -1951,10 +2015,10 @@ aopPut (asmop * aop, const char *s, int offset) wassert (IS_GB); /* PENDING: for re-target */ if (!strcmp (s, "!*hl") || !strcmp (s, "(hl)") || !strcmp (s, "[hl]")) - { - emit2 ("ld a,!*hl"); - s = "a"; - } + { + emit2 ("ld a,!*hl"); + s = "a"; + } setupPair (PAIR_HL, aop, offset); emit2 ("ld !*hl,%s", s); @@ -1963,11 +2027,11 @@ aopPut (asmop * aop, const char *s, int offset) case AOP_EXSTK: wassert (!IS_GB); if (!canAssignToPtr (s)) - { - emit2 ("ld a,%s", s); + { + emit2 ("ld a,%s", s); setupPair (PAIR_IY, aop, offset); - emit2 ("ld !*iyx,a", offset); - } + emit2 ("ld !*iyx,a", offset); + } else { setupPair (PAIR_IY, aop, offset); @@ -1977,77 +2041,77 @@ aopPut (asmop * aop, const char *s, int offset) case AOP_STK: if (IS_GB) - { - /* PENDING: re-target */ - if (!strcmp (s, "!*hl") || !strcmp (s, "(hl)") || !strcmp (s, "[hl]")) - { - emit2 ("ld a,!*hl"); - s = "a"; - } - setupPair (PAIR_HL, aop, offset); - if (!canAssignToPtr (s)) - { - emit2 ("ld a,%s", s); - emit2 ("ld !*hl,a"); - } - else - emit2 ("ld !*hl,%s", s); - } + { + /* PENDING: re-target */ + if (!strcmp (s, "!*hl") || !strcmp (s, "(hl)") || !strcmp (s, "[hl]")) + { + emit2 ("ld a,!*hl"); + s = "a"; + } + setupPair (PAIR_HL, aop, offset); + if (!canAssignToPtr (s)) + { + emit2 ("ld a,%s", s); + emit2 ("ld !*hl,a"); + } + else + emit2 ("ld !*hl,%s", s); + } else - { - if (aop->aopu.aop_stk >= 0) - offset += _G.stack.param_offset; - if (!canAssignToPtr (s)) - { - emit2 ("ld a,%s", s); - emit2 ("ld !*ixx,a", aop->aopu.aop_stk + offset); - } - else + { + if (aop->aopu.aop_stk >= 0) + offset += _G.stack.param_offset; + if (!canAssignToPtr (s)) + { + emit2 ("ld a,%s", s); + emit2 ("ld !*ixx,a", aop->aopu.aop_stk + offset); + } + else { emit2 ("ld !*ixx,%s", aop->aopu.aop_stk + offset, s); } - } + } break; case AOP_CRY: /* if bit variable */ if (!aop->aopu.aop_dir) - { - emit2 ("ld a,!zero"); - emit2 ("rla"); - } + { + emit2 ("ld a,!zero"); + emit2 ("rla"); + } else - { - /* In bit space but not in C - cant happen */ - wassertl (0, "Tried to write into a bit variable"); - } + { + /* In bit space but not in C - cant happen */ + wassertl (0, "Tried to write into a bit variable"); + } break; case AOP_STR: aop->coff = offset; if (strcmp (aop->aopu.aop_str[offset], s)) - { - emit2 ("ld %s,%s", aop->aopu.aop_str[offset], s); - } + { + emit2 ("ld %s,%s", aop->aopu.aop_str[offset], s); + } spillPairReg(aop->aopu.aop_str[offset]); break; case AOP_ACC: aop->coff = offset; if (!offset && (strcmp (s, "acc") == 0)) - break; + break; if (offset > 0) - { + { wassertl (0, "Tried to access past the end of A"); - } + } else - { - if (strcmp (aop->aopu.aop_str[offset], s)) - { - emit2 ("ld %s,%s", aop->aopu.aop_str[offset], s); - spillPairReg(aop->aopu.aop_str[offset]); - } - } + { + if (strcmp (aop->aopu.aop_str[offset], s)) + { + emit2 ("ld %s,%s", aop->aopu.aop_str[offset], s); + spillPairReg(aop->aopu.aop_str[offset]); + } + } break; case AOP_HLREG: @@ -2061,14 +2125,14 @@ aopPut (asmop * aop, const char *s, int offset) if (aop->aopu.aop_pairId==PAIR_IX) emit2 ("ld !*ixx,%s", 0, s); else if (aop->aopu.aop_pairId==PAIR_IY) - emit2 ("ld !*ixy,%s", 0, s); + emit2 ("ld !*iyx,%s", 0, s); else emit2 ("ld (%s),%s", _pairs[aop->aopu.aop_pairId].name, s); break; default: werror (E_INTERNAL_ERROR, __FILE__, __LINE__, - "aopPut got unsupported aop->type"); + "aopPut got unsupported aop->type"); exit (0); } } @@ -2077,6 +2141,7 @@ aopPut (asmop * aop, const char *s, int offset) #define AOP_TYPE(op) AOP(op)->type #define AOP_SIZE(op) AOP(op)->size #define AOP_NEEDSACC(x) (AOP(x) && ((AOP_TYPE(x) == AOP_CRY) || (AOP_TYPE(x) == AOP_SFR))) +#define AOP_IS_PAIRPTR(x, p) (AOP_TYPE (x) == AOP_PAIRPTR && AOP (x)->aopu.aop_pairId == p) static void commitPair (asmop * aop, PAIR_ID id) @@ -2128,7 +2193,7 @@ getDataSize (operand * op) /*-----------------------------------------------------------------*/ static void movLeft2Result (operand * left, int offl, - operand * result, int offr, int sign) + operand * result, int offr, int sign) { const char *l; @@ -2137,23 +2202,23 @@ movLeft2Result (operand * left, int offl, l = aopGet (AOP (left), offl, FALSE); if (!sign) - { - aopPut (AOP (result), l, offr); - } + { + aopPut (AOP (result), l, offr); + } else - { + { if (getDataSize (left) == offl + 1) { emit2 ("ld a,%s", l); aopPut (AOP (result), "a", offr); } - } + } } } static void movLeft2ResultLong (operand * left, int offl, - operand * result, int offr, int sign, + operand * result, int offr, int sign, int size) { if (size == 1) @@ -2170,12 +2235,12 @@ movLeft2ResultLong (operand * left, int offl, emit2 ("ld a,%s", aopGet (AOP (left), LSB, FALSE)); emit2 ("ld h,%s", aopGet (AOP (left), MSB16, FALSE)); emit2 ("ld l,a"); - spillPair (PAIR_HL); + spillPair (PAIR_HL); } else if ( getPairId ( AOP (result)) == PAIR_IY) { PAIR_ID id = getPairId (AOP (left)); - if (id != PAIR_INVALID) + if (id != PAIR_INVALID) { emit2("push %s", _pairs[id].name); emit2("pop iy"); @@ -2208,38 +2273,31 @@ 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 -outBitCLong (operand * result, bool swap_sense) +outBitC (operand * result) { /* if the result is bit */ if (AOP_TYPE (result) == AOP_CRY) { - wassertl (0, "Tried to write carry to a bit"); + if (!IS_OP_RUONLY (result)) + aopPut (AOP (result), "c", 0); } else { emit2 ("ld a,!zero"); emit2 ("rla"); - if (swap_sense) - emit2 ("xor a,!immedbyte", 1); outAcc (result); } } -void -outBitC (operand * result) -{ - outBitCLong (result, FALSE); -} - /*-----------------------------------------------------------------*/ /* toBoolean - emit code for orl a,operator(sizeop) */ /*-----------------------------------------------------------------*/ @@ -2253,15 +2311,15 @@ _toBoolean (operand * oper) emit2 ("ld a,%s", aopGet (AOP (oper), offset++, FALSE)); size--; while (size--) - emit2 ("or a,%s", aopGet (AOP (oper), offset++, FALSE)); + emit2 ("or a,%s", aopGet (AOP (oper), offset++, FALSE)); } else { if (AOP (oper)->type != AOP_ACC) - { - _clearCarry(); - emit2 ("or a,%s", aopGet (AOP (oper), 0, FALSE)); - } + { + _clearCarry(); + emit2 ("or a,%s", aopGet (AOP (oper), 0, FALSE)); + } } } @@ -2397,7 +2455,7 @@ genUminusFloat (operand * op, operand * result) emitDebug("; genUminusFloat"); /* for this we just need to flip the - first it then copy the rest in place */ + first bit then copy the rest in place */ size = AOP_SIZE (op) - 1; _moveA(aopGet (AOP (op), MSB32, FALSE)); @@ -2474,7 +2532,7 @@ genUminus (iCode * ic) emit2 ("rlc a"); emit2 ("sbc a,a"); while (size--) - aopPut (AOP (IC_RESULT (ic)), "a", offset++); + aopPut (AOP (IC_RESULT (ic)), "a", offset++); } release: @@ -2507,10 +2565,20 @@ assignResultValue (operand * oper) } else { - while (size--) - { - aopPut (AOP (oper), _fReturn[size], size); - } + if ((AOP_TYPE (oper) == AOP_REG) && (AOP_SIZE (oper) == 4) && + !strcmp (AOP (oper)->aopu.aop_reg[size-1]->name, _fReturn[size-2])) + { + size--; + _emitMove ("a", _fReturn[size-1]); + _emitMove (_fReturn[size-1], _fReturn[size]); + _emitMove (_fReturn[size], "a"); + aopPut (AOP (oper), _fReturn[size], size-1); + size--; + } + while(size--) + { + aopPut (AOP (oper), _fReturn[size], size); + } } } @@ -2551,7 +2619,7 @@ _saveRegsForCall(iCode *ic, int sendSetSize) o Compute if DE and/or BC are used to hold the result value o If (DE is used, or in the send set) and is not used in the result, push. o If BC is used and is not in the result, push - o + o o If DE is used in the send set, fetch o If HL is used in the send set, fetch o Call @@ -2563,7 +2631,7 @@ _saveRegsForCall(iCode *ic, int sendSetSize) bool bcInRet = FALSE, deInRet = FALSE; bitVect *rInUse; - rInUse = bitVectCplAnd (bitVectCopy (ic->rMask), + rInUse = bitVectCplAnd (bitVectCopy (ic->rMask), z80_rUmaskForOp (IC_RESULT(ic))); deInUse = bitVectBitValue (rInUse, D_IDX) || bitVectBitValue(rInUse, E_IDX); @@ -2614,7 +2682,7 @@ genIpush (iCode * ic) */ int nAddSets = 0; iCode *walk = ic->next; - + while (walk) { if (walk->op == SEND) { nAddSets++; @@ -2647,43 +2715,50 @@ genIpush (iCode * ic) else { if (size == 2) - { - fetchHL (AOP (IC_LEFT (ic))); - emit2 ("push hl"); - spillPair (PAIR_HL); - _G.stack.pushed += 2; - goto release; - } + { + fetchHL (AOP (IC_LEFT (ic))); + emit2 ("push hl"); + _G.stack.pushed += 2; + goto release; + } if (size == 4) - { - fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), ic, 2); - emit2 ("push hl"); - spillPair (PAIR_HL); - _G.stack.pushed += 2; - fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), ic, 0); - emit2 ("push hl"); - spillPair (PAIR_HL); - _G.stack.pushed += 2; - goto release; - } + { + fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), ic, 2); + emit2 ("push hl"); + _G.stack.pushed += 2; + fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), ic, 0); + emit2 ("push hl"); + _G.stack.pushed += 2; + goto release; + } offset = size; while (size--) - { - 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++; - } + { + if (AOP (IC_LEFT (ic))->type == AOP_IY) + { + char *l = aopGetLitWordLong (AOP (IC_LEFT (ic)), --offset, FALSE); + wassert (l); + emit2 ("ld a,(%s)", l); + emit2 ("push af"); + } + else + { + l = aopGet (AOP (IC_LEFT (ic)), --offset, FALSE); + if (!strcmp(l, "b")) + emit2 ("push bc"); + else if (!strcmp(l, "d")) + emit2 ("push de"); + else if (!strcmp(l, "h")) + emit2 ("push hl"); + else + { + emit2 ("ld a,%s", l); + emit2 ("push af"); + } + } + emit2 ("inc sp"); + _G.stack.pushed++; + } } release: freeAsmop (IC_LEFT (ic), NULL, ic); @@ -2712,12 +2787,12 @@ genIpop (iCode * ic) else { while (size--) - { - emit2 ("dec sp"); - emit2 ("pop hl"); - spillPair (PAIR_HL); - aopPut (AOP (IC_LEFT (ic)), "l", offset--); - } + { + emit2 ("dec sp"); + emit2 ("pop hl"); + spillPair (PAIR_HL); + aopPut (AOP (IC_LEFT (ic)), "l", offset--); + } } freeAsmop (IC_LEFT (ic), NULL, ic); @@ -2766,28 +2841,28 @@ _opUsesPair (operand * op, iCode * ic, PAIR_ID pairId) { int i; for (i = 0; i < aop->size; i++) - { - if (pairId == PAIR_DE) - { - emitDebug ("; 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++; - } + { + if (pairId == PAIR_DE) + { + emitDebug ("; 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 if (pairId == PAIR_BC) { - emitDebug ("; name %s", aop->aopu.aop_reg[i]->name); - if (!strcmp (aop->aopu.aop_reg[i]->name, "c")) - ret++; - if (!strcmp (aop->aopu.aop_reg[i]->name, "b")) - ret++; + emitDebug ("; name %s", aop->aopu.aop_reg[i]->name); + if (!strcmp (aop->aopu.aop_reg[i]->name, "c")) + ret++; + if (!strcmp (aop->aopu.aop_reg[i]->name, "b")) + ret++; + } + else + { + wassert (0); } - else - { - wassert (0); - } - } + } } freeAsmop (IC_LEFT (ic), NULL, ic); @@ -2873,28 +2948,29 @@ emitCall (iCode * ic, bool ispcall) if (ispcall) { if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype))) - { - werror (W_INDIR_BANKED); - } + { + werror (W_INDIR_BANKED); + } aopOp (IC_LEFT (ic), ic, FALSE, FALSE); if (isLitWord (AOP (IC_LEFT (ic)))) - { - emit2 ("call %s", aopGetLitWordLong (AOP (IC_LEFT (ic)), 0, FALSE)); - } + { + emit2 ("call %s", aopGetLitWordLong (AOP (IC_LEFT (ic)), 0, FALSE)); + } else - { - symbol *rlbl = newiTempLabel (NULL); - spillPair (PAIR_HL); - emit2 ("ld hl,!immed!tlabel", (rlbl->key + 100)); - emit2 ("push hl"); - _G.stack.pushed += 2; - - fetchHL (AOP (IC_LEFT (ic))); - emit2 ("jp !*hl"); - emit2 ("!tlabeldef", (rlbl->key + 100)); - _G.stack.pushed -= 2; - } + { + symbol *rlbl = newiTempLabel (NULL); + spillPair (PAIR_HL); + emit2 ("ld hl,!immed!tlabel", (rlbl->key + 100)); + emit2 ("push hl"); + _G.stack.pushed += 2; + + fetchHL (AOP (IC_LEFT (ic))); + emit2 ("jp !*hl"); + emit2 ("!tlabeldef", (rlbl->key + 100)); + _G.lines.current->isLabel = 1; + _G.stack.pushed -= 2; + } freeAsmop (IC_LEFT (ic), NULL, ic); } else @@ -2903,36 +2979,22 @@ emitCall (iCode * ic, bool ispcall) OP_SYMBOL (IC_LEFT (ic))->rname : OP_SYMBOL (IC_LEFT (ic))->name; if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype))) - { - emit2 ("call banked_call"); - emit2 ("!dws", name); - emit2 ("!dw !bankimmeds", name); - } + { + emit2 ("call banked_call"); + emit2 ("!dws", name); + emit2 ("!dw !bankimmeds", name); + } else - { - /* make the call */ - emit2 ("call %s", name); - } + { + /* make the call */ + emit2 ("call %s", name); + } } spillCached (); - /* Mark the regsiters as restored. */ + /* Mark the registers as restored. */ _G.saves.saved = FALSE; - /* if we need assign a result value */ - if ((IS_ITEMP (IC_RESULT (ic)) && - (OP_SYMBOL (IC_RESULT (ic))->nRegs || - OP_SYMBOL (IC_RESULT (ic))->spildir)) || - IS_TRUE_SYMOP (IC_RESULT (ic))) - { - - aopOp (IC_RESULT (ic), ic, FALSE, FALSE); - - assignResultValue (IC_RESULT (ic)); - - freeAsmop (IC_RESULT (ic), NULL, ic); - } - /* adjust the stack for parameters if required */ if (ic->parmBytes) { @@ -2940,31 +3002,44 @@ emitCall (iCode * ic, bool ispcall) _G.stack.pushed -= i; if (IS_GB) - { - emit2 ("!ldaspsp", i); - } + { + emit2 ("!ldaspsp", i); + } else - { - spillCached (); - if (i > 8) - { - emit2 ("ld iy,!immedword", i); - emit2 ("add iy,sp"); - emit2 ("ld sp,iy"); - } - else - { - while (i > 1) - { - emit2 ("pop af"); - i -= 2; - } - if (i) + { + spillCached (); + if (i > 8) + { + emit2 ("ld iy,!immedword", i); + emit2 ("add iy,sp"); + emit2 ("ld sp,iy"); + } + else + { + while (i > 1) + { + emit2 ("pop af"); + i -= 2; + } + if (i) { emit2 ("inc sp"); } - } - } + } + } + } + + /* if we need assign a result value */ + if ((IS_ITEMP (IC_RESULT (ic)) && + (OP_SYMBOL (IC_RESULT (ic))->nRegs || + OP_SYMBOL (IC_RESULT (ic))->spildir)) || + IS_TRUE_SYMOP (IC_RESULT (ic))) + { + aopOp (IC_RESULT (ic), ic, FALSE, FALSE); + + assignResultValue (IC_RESULT (ic)); + + freeAsmop (IC_RESULT (ic), NULL, ic); } spillCached (); @@ -2984,7 +3059,7 @@ emitCall (iCode * ic, bool ispcall) eInRet = FALSE; } - if (_G.stack.pushedDE) + if (_G.stack.pushedDE) { if (dInRet && eInRet) { @@ -3009,8 +3084,8 @@ emitCall (iCode * ic, bool ispcall) } _G.stack.pushedDE = FALSE; } - - if (_G.stack.pushedBC) + + if (_G.stack.pushedBC) { if (bInRet && cInRet) { @@ -3068,7 +3143,7 @@ resultRemat (iCode * ic) { symbol *sym = OP_SYMBOL (IC_RESULT (ic)); if (sym->remat && !POINTER_SET (ic)) - return 1; + return 1; } return 0; @@ -3083,7 +3158,7 @@ static void genFunction (iCode * ic) { bool stackParm; - + symbol *sym = OP_SYMBOL (IC_LEFT (ic)); sym_link *ftype; @@ -3092,42 +3167,70 @@ genFunction (iCode * ic) setArea (IFFUNC_NONBANKED (sym->type)); - /* PENDING: Reset the receive offset as it doesn't seem to get reset anywhere - else. + /* PENDING: Reset the receive offset as it + doesn't seem to get reset anywhere else. */ _G.receiveOffset = 0; /* Record the last function name for debugging. */ _G.lastFunctionName = sym->rname; - + /* Create the function header */ emit2 ("!functionheader", sym->name); - sprintf (buffer, "%s_start", sym->rname); - emit2 ("!labeldef", buffer); - emit2 ("!functionlabeldef", sym->rname); - - if (options.profile) + if (!IS_STATIC(sym->etype)) { - emit2 ("!profileenter"); + sprintf (buffer, "%s_start", sym->rname); + emit2 ("!labeldef", buffer); + _G.lines.current->isLabel = 1; } + emit2 ("!functionlabeldef", sym->rname); + _G.lines.current->isLabel = 1; ftype = operandType (IC_LEFT (ic)); - /* if this is an interrupt service routine then save all potentially used registers. */ + if (IFFUNC_ISNAKED(ftype)) + { + emitDebug("; naked function: no prologue."); + return; + } + + /* if this is an interrupt service routine + then save all potentially used registers. */ if (IFFUNC_ISISR (sym->type)) { - if (!FUNC_ISNAKED( sym->type )) + /* If critical function then turn interrupts off */ + /* except when no interrupt number is given then it implies the NMI handler */ + if (IFFUNC_ISCRITICAL (sym->type) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC)) { - emit2 ("!pusha"); - } + emit2 ("!di"); + } + + emit2 ("!pusha"); } else { - /* if critical function then turn interrupts off */ + /* This is a non-ISR function. + If critical function then turn interrupts off */ if (IFFUNC_ISCRITICAL (sym->type)) { - emit2 ("!di"); - } + if (IS_GB) + { + emit2 ("!di"); + } + else + { + //get interrupt enable flag IFF2 into P/O + emit2 ("ld a,i"); + emit2 ("!di"); + //save P/O flag + emit2 ("push af"); + } + } + } + + if (options.profile) + { + emit2 ("!profileenter"); } /* PENDING: callee-save etc */ @@ -3144,30 +3247,30 @@ genFunction (iCode * ic) { int i; for (i = 0; i < sym->regsUsed->size; i++) - { - if (bitVectBitValue (sym->regsUsed, i)) - { - switch (i) - { - case C_IDX: - case B_IDX: + { + if (bitVectBitValue (sym->regsUsed, i)) + { + switch (i) + { + case C_IDX: + case B_IDX: bcInUse = TRUE; - break; - case D_IDX: - case E_IDX: - if (IS_Z80) { + break; + case D_IDX: + case E_IDX: + if (IS_Z80) { deInUse = TRUE; } else { /* Other systems use DE as a temporary. */ } - break; - } - } - } + break; + } + } + } } - if (bcInUse) + if (bcInUse) { emit2 ("push bc"); _G.stack.param_offset += 2; @@ -3185,7 +3288,7 @@ genFunction (iCode * ic) /* adjust the stack for the function */ _G.stack.last = sym->stack; - + stackParm = FALSE; for (sym = setFirstItem (istack->syms); sym; sym = setNextItem (istack->syms)) @@ -3197,7 +3300,7 @@ genFunction (iCode * ic) } } sym = OP_SYMBOL (IC_LEFT (ic)); - + _G.omitFramePtr = options.ommitFramePtr; if (IS_Z80 && !stackParm && !sym->stack) { @@ -3210,8 +3313,23 @@ genFunction (iCode * ic) else if (sym->stack && IS_GB && sym->stack > -INT8MIN) emit2 ("!enterxl", sym->stack); else if (sym->stack) - emit2 ("!enterx", sym->stack); - else if( !FUNC_ISNAKED( sym->type )) /*.p.t.20030716 - now supporting Naked funcitons */ + { + if ((optimize.codeSize && sym->stack <= 8) || sym->stack <= 4) + { + int stack = sym->stack; + emit2 ("!enter"); + while (stack > 1) + { + emit2 ("push af"); + stack -= 2; + } + if(stack > 0) + emit2 ("dec sp"); + } + else + emit2 ("!enterx", sym->stack); + } + else emit2 ("!enter"); _G.stack.offset = sym->stack; @@ -3225,6 +3343,11 @@ genEndFunction (iCode * ic) { symbol *sym = OP_SYMBOL (IC_LEFT (ic)); + if (IFFUNC_ISNAKED(sym->type)) + { + emitDebug("; naked function: no epilogue."); + return; + } /* PENDING: calleeSave */ if (IS_Z80 && _G.omitFramePtr) @@ -3240,52 +3363,75 @@ genEndFunction (iCode * ic) { emit2 ("!leavex", _G.stack.offset); } - else if( !FUNC_ISNAKED( sym->type )) /*.p.t.20030716 - now supporting Naked funcitons */ + else { emit2 ("!leave"); } - - if (_G.calleeSaves.pushedDE) + + if (_G.calleeSaves.pushedDE) { emit2 ("pop de"); _G.calleeSaves.pushedDE = FALSE; } - if (_G.calleeSaves.pushedBC) + if (_G.calleeSaves.pushedBC) { emit2 ("pop bc"); _G.calleeSaves.pushedBC = FALSE; } - if (options.profile) + if (options.profile) { emit2 ("!profileexit"); } - /* if this is an interrupt service routine then restore all potentially used registers. */ + /* if this is an interrupt service routine + then save all potentially used registers. */ if (IFFUNC_ISISR (sym->type)) { - if (!FUNC_ISNAKED( sym->type )) + emit2 ("!popa"); + + /* If critical function then turn interrupts back on */ + /* except when no interrupt number is given then it implies the NMI handler */ + if (IFFUNC_ISCRITICAL (sym->type) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC)) { - emit2 ("!popa"); + emit2 ("!ei"); } } else { - /* if critical function then turn interrupts back on */ + /* This is a non-ISR function. + If critical function then turn interrupts back on */ if (IFFUNC_ISCRITICAL (sym->type)) - emit2 ("!ei"); + { + if (IS_GB) + { + emit2 ("!ei"); + } + else + { + symbol *tlbl = newiTempLabel (NULL); + //restore P/O flag + emit2 ("pop af"); + //parity odd <==> P/O=0 <==> interrupt enable flag IFF2 was 0 <==> + //don't enable interrupts as they were off before + emit2 ("jp PO,!tlabel", tlbl->key + 100); + emit2 ("!ei"); + emit2 ("!tlabeldef", (tlbl->key + 100)); + _G.lines.current->isLabel = 1; + } + } } if (options.debug && currFunc) { debugFile->writeEndFunction (currFunc, ic, 1); } - + if (IFFUNC_ISISR (sym->type)) { /* "critical interrupt" is used to imply NMI handler */ - if (IS_Z80 && IFFUNC_ISCRITICAL (sym->type)) + if (IS_Z80 && IFFUNC_ISCRITICAL (sym->type) && FUNC_INTNO(sym->type) == INTNO_UNSPEC) emit2 ("retn"); else emit2 ("reti"); @@ -3295,10 +3441,14 @@ genEndFunction (iCode * ic) /* Both banked and non-banked just ret */ emit2 ("ret"); } - - sprintf (buffer, "%s_end", sym->rname); - emit2 ("!labeldef", buffer); - + + if (!IS_STATIC(sym->etype)) + { + sprintf (buffer, "%s_end", sym->rname); + emit2 ("!labeldef", buffer); + _G.lines.current->isLabel = 1; + } + _G.flushStatics = 1; _G.stack.pushed = 0; _G.stack.offset = 0; @@ -3327,17 +3477,17 @@ genRet (iCode * ic) aopDump("IC_LEFT", AOP(IC_LEFT(ic))); - #if 0 + #if 0 if ((size == 2) && ((l = aopGetWord (AOP (IC_LEFT (ic)), 0)))) { if (IS_GB) - { - emit2 ("ld de,%s", l); - } + { + emit2 ("ld de,%s", l); + } else - { - emit2 ("ld hl,%s", l); - } + { + emit2 ("ld hl,%s", l); + } } #endif if (size==2) @@ -3347,21 +3497,21 @@ genRet (iCode * ic) else { if (IS_GB && size == 4 && requiresHL (AOP (IC_LEFT (ic)))) - { - fetchPair (PAIR_DE, AOP (IC_LEFT (ic))); - fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), ic, 2); - } + { + fetchPair (PAIR_DE, AOP (IC_LEFT (ic))); + fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), ic, 2); + } else - { - while (size--) - { - l = aopGet (AOP (IC_LEFT (ic)), offset, - FALSE); - if (strcmp (_fReturn[offset], l)) - emit2 ("ld %s,%s", _fReturn[offset], l); + { + while (size--) + { + l = aopGet (AOP (IC_LEFT (ic)), offset, + FALSE); + if (strcmp (_fReturn[offset], l)) + emit2 ("ld %s,%s", _fReturn[offset], l); offset++; - } - } + } + } } freeAsmop (IC_LEFT (ic), NULL, ic); @@ -3369,7 +3519,7 @@ jumpret: /* generate a jump to the return label if the next is not the return statement */ if (!(ic->next && ic->next->op == LABEL && - IC_LABEL (ic->next) == returnLabel)) + IC_LABEL (ic->next) == returnLabel)) emit2 ("jp !tlabel", returnLabel->key + 100); } @@ -3414,18 +3564,18 @@ genPlusIncr (iCode * ic) emitDebug ("; genPlusIncr"); - icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit); + icount = (unsigned int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit); /* If result is a pair */ if (resultId != PAIR_INVALID) { if (isLitWord (AOP (IC_LEFT (ic)))) - { + { fetchLitPair (getPairId (AOP (IC_RESULT (ic))), AOP (IC_LEFT (ic)), icount); - return TRUE; - } + return TRUE; + } if (isPair (AOP (IC_LEFT (ic))) && resultId == PAIR_HL && icount > 2) - { + { if (getPairId (AOP (IC_LEFT (ic))) == PAIR_HL) { PAIR_ID freep = getFreePairId (ic); @@ -3442,20 +3592,20 @@ genPlusIncr (iCode * ic) emit2 ("add hl,%s", getPairName (AOP (IC_LEFT (ic)))); return TRUE; } - } + } if (icount > 5) - return FALSE; + return FALSE; /* Inc a pair */ if (!sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic)))) - { - if (icount > 2) - return FALSE; - movLeft2ResultLong (IC_LEFT (ic), 0, IC_RESULT (ic), 0, 0, 2); - } + { + if (icount > 2) + return FALSE; + movLeft2ResultLong (IC_LEFT (ic), 0, IC_RESULT (ic), 0, 0, 2); + } while (icount--) - { - emit2 ("inc %s", getPairName (AOP (IC_RESULT (ic)))); - } + { + emit2 ("inc %s", getPairName (AOP (IC_RESULT (ic)))); + } return TRUE; } @@ -3481,14 +3631,14 @@ genPlusIncr (iCode * ic) symbol *tlbl = NULL; tlbl = newiTempLabel (NULL); while (size--) - { - emit2 ("inc %s", aopGet (AOP (IC_RESULT (ic)), offset++, FALSE)); - if (size) - { - emit2 ("!shortjp nz,!tlabel", tlbl->key + 100); - } - } - emitLabel (tlbl->key + 100); + { + emit2 ("inc %s", aopGet (AOP (IC_RESULT (ic)), offset++, FALSE)); + if (size) + { + emit2 ("!shortjp NZ,!tlabel", tlbl->key + 100); + } + } + emitLabelNoSpill (tlbl->key + 100); return TRUE; } @@ -3538,9 +3688,9 @@ outBitAcc (operand * result) } else { - emit2 ("!shortjp z,!tlabel", tlbl->key + 100); + emit2 ("!shortjp Z,!tlabel", tlbl->key + 100); emit2 ("ld a,!one"); - emitLabel (tlbl->key + 100); + emitLabelNoSpill (tlbl->key + 100); outAcc (result); } } @@ -3566,30 +3716,27 @@ shiftIntoPair (int idx, asmop *aop) wassertl (IS_Z80, "Only implemented for the Z80"); // wassertl (aop->type == AOP_EXSTK, "Only implemented for EXSTK"); - switch (idx) + emitDebug ("; Shift into pair idx %u", idx); + + switch (idx) { case 0: id = PAIR_HL; + setupPair (PAIR_HL, aop, 0); break; case 1: id = PAIR_DE; _push (PAIR_DE); - break; - default: - wassertl (0, "Internal error - hit default case"); - } - - emitDebug ("; Shift into pair idx %u", idx); - - if (id == PAIR_HL) - { - setupPair (PAIR_HL, aop, 0); - } - else - { setupPair (PAIR_IY, aop, 0); emit2 ("push iy"); emit2 ("pop %s", _pairs[id].name); + break; + case 2: + id = PAIR_IY; + setupPair (PAIR_IY, aop, 0); + break; + default: + wassertl (0, "Internal error - hit default case"); } aop->type = AOP_PAIRPTR; @@ -3598,9 +3745,13 @@ shiftIntoPair (int idx, asmop *aop) _G.pairs[id].last_type = aop->type; } -static void -setupToPreserveCarry (asmop *result, asmop *left, asmop *right) +static void +setupToPreserveCarry (iCode * ic) { + asmop *left = AOP (IC_LEFT (ic)); + asmop *right = AOP (IC_RIGHT (ic)); + asmop *result = AOP (IC_RESULT (ic)); + wassert (left && right); if (IS_Z80) @@ -3610,7 +3761,12 @@ setupToPreserveCarry (asmop *result, asmop *left, asmop *right) shiftIntoPair (0, right); /* check result again, in case right == result */ if (couldDestroyCarry (result)) - shiftIntoPair (1, result); + { + if (!isPairInUse (PAIR_DE, ic)) + shiftIntoPair (1, result); + else + shiftIntoPair (2, result); + } } else if (couldDestroyCarry (right)) { @@ -3681,8 +3837,6 @@ genPlus (iCode * ic) if (genPlusIncr (ic) == TRUE) goto release; - emitDebug ("; Can't optimise plus by inc, falling back to the normal way"); - size = getDataSize (IC_RESULT (ic)); /* Special case when left and right are constant */ @@ -3694,14 +3848,14 @@ genPlus (iCode * ic) if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT && AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT && left && right) - { - /* It's a pair */ - /* PENDING: fix */ - char buffer[100]; - sprintf (buffer, "#(%s + %s)", left, right); - emit2 ("ld %s,%s", getPairName (AOP (IC_RESULT (ic))), buffer); - goto release; - } + { + /* It's a pair */ + /* PENDING: fix */ + char buffer[100]; + sprintf (buffer, "#(%s + %s)", left, right); + emit2 ("ld %s,%s", getPairName (AOP (IC_RESULT (ic))), buffer); + goto release; + } } if ((isPair (AOP (IC_RIGHT (ic))) || isPair (AOP (IC_LEFT (ic)))) && getPairId (AOP (IC_RESULT (ic))) == PAIR_HL) @@ -3711,7 +3865,7 @@ genPlus (iCode * ic) PAIR_ID right = getPairId (AOP (IC_RIGHT (ic))); spillPair (PAIR_HL); - + if (left == PAIR_HL && right != PAIR_INVALID) { emit2 ("add hl,%s", _pairs[right].name); @@ -3729,7 +3883,7 @@ genPlus (iCode * ic) goto release; } else if (left != PAIR_INVALID && left != PAIR_HL) - { + { fetchPair (PAIR_HL, AOP (IC_RIGHT (ic))); emit2 ("add hl,%s", getPairName (AOP (IC_LEFT (ic)))); goto release; @@ -3744,14 +3898,23 @@ genPlus (iCode * ic) { fetchPair (PAIR_HL, AOP (IC_LEFT (ic))); emit2 ("add hl,%s", getPairName (AOP (IC_RIGHT (ic)))); - spillCached(); + spillPair (PAIR_HL); + commitPair ( AOP (IC_RESULT (ic)), PAIR_HL); + goto release; + } + + if (isPair (AOP (IC_LEFT (ic))) && AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT && getPairId (AOP (IC_LEFT (ic))) != PAIR_HL) + { + fetchPair (PAIR_HL, AOP (IC_RIGHT (ic))); + emit2 ("add hl,%s", getPairName (AOP (IC_LEFT (ic)))); + spillPair (PAIR_HL); commitPair ( AOP (IC_RESULT (ic)), PAIR_HL); 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+n trashes C so we can't afford to do it during an + add with stack based variables. Worst case is: ld hl,sp+left ld a,(hl) ld hl,sp+right @@ -3764,7 +3927,7 @@ genPlus (iCode * ic) adc (hl) ld hl,sp+result+1 ld (hl),a - So you cant afford to load up hl if either left, right, or result + So you can't 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) @@ -3780,36 +3943,36 @@ genPlus (iCode * ic) 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; - } - } + 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; + } + } if (size == 4) { /* Be paranoid on the GB with 4 byte variables due to how C @@ -3819,31 +3982,65 @@ genPlus (iCode * ic) goto release; } } - - setupToPreserveCarry (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)), AOP (IC_RIGHT (ic))); + + setupToPreserveCarry (ic); + + /* This is ugly, but it fixes the worst code generation bug on Z80. */ + /* Probably something similar has to be done for addition of larger numbers, too. */ + if(size == 2) + { + _moveA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE)); + emit2 ("add a,%s", aopGet (AOP (IC_RIGHT (ic)), 0, FALSE)); + if(strcmp (aopGet (AOP (IC_RESULT (ic)), 0, FALSE), aopGet (AOP (IC_LEFT (ic)), 1, FALSE))) + { + aopPut (AOP (IC_RESULT (ic)), "a", 0); + _moveA (aopGet (AOP (IC_LEFT (ic)), 1, FALSE)); + } + else + { + emitDebug ("; Addition result is in same register as operand of next addition."); + if(strchr (aopGet (AOP (IC_RESULT (ic)), 0, FALSE), 'c') || + strchr (aopGet (AOP (IC_RESULT (ic)), 0, FALSE), 'b') ) + { + emit2 ("push de"); + emit2 ("ld e, a"); + emit2 ("ld a, %s", aopGet (AOP (IC_LEFT (ic)), 1, FALSE)); + emit2 ("ld d, a"); + emit2 ("ld a, e"); + emit2 ("ld %s, a", aopGet (AOP (IC_RESULT (ic)), 0, FALSE)); + emit2 ("ld a, d"); + emit2 ("pop de"); + } + else + { + emit2 ("push bc"); + emit2 ("ld c, a"); + emit2 ("ld a, %s", aopGet (AOP (IC_LEFT (ic)), 1, FALSE)); + emit2 ("ld b, a"); + emit2 ("ld a, c"); + emit2 ("ld %s, a", aopGet (AOP (IC_RESULT (ic)), 0, FALSE)); + emit2 ("ld a, b"); + emit2 ("pop bc"); + } + + } + emit2 ("adc a,%s", aopGet (AOP (IC_RIGHT (ic)), 1, FALSE)); + aopPut (AOP (IC_RESULT (ic)), "a", 1); + goto release; + } while (size--) { - if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC) - { - _moveA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE)); - if (offset == 0) - emit2 ("add a,%s", - aopGet (AOP (IC_RIGHT (ic)), offset, FALSE)); - else - emit2 ("adc a,%s", - aopGet (AOP (IC_RIGHT (ic)), offset, FALSE)); - } + _moveA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE)); + if (offset == 0) + { + if(size == 0 && AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT && ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) == 1) + emit2 ("inc a"); + else + emit2 ("add a,%s", aopGet (AOP (IC_RIGHT (ic)), offset, FALSE)); + } else - { - _moveA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE)); - if (offset == 0) - emit2 ("add a,%s", - aopGet (AOP (IC_RIGHT (ic)), offset, FALSE)); - else - emit2 ("adc a,%s", - aopGet (AOP (IC_RIGHT (ic)), offset, FALSE)); - } + emit2 ("adc a,%s", aopGet (AOP (IC_RIGHT (ic)), offset, FALSE)); aopPut (AOP (IC_RESULT (ic)), "a", offset++); } @@ -3852,7 +4049,6 @@ release: freeAsmop (IC_LEFT (ic), NULL, ic); freeAsmop (IC_RIGHT (ic), NULL, ic); freeAsmop (IC_RESULT (ic), NULL, ic); - } /*-----------------------------------------------------------------*/ @@ -3871,7 +4067,7 @@ genMinusDec (iCode * ic) /* if the literal value of the right hand side is greater than 4 then it is not worth it */ - if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 2) + if ((icount = (unsigned int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 2) return FALSE; size = getDataSize (IC_RESULT (ic)); @@ -3881,7 +4077,7 @@ genMinusDec (iCode * ic) (size > 1) && isPair (AOP (IC_RESULT (ic)))) { while (icount--) - emit2 ("dec %s", getPairName (AOP (IC_RESULT (ic)))); + emit2 ("dec %s", getPairName (AOP (IC_RESULT (ic)))); return TRUE; } @@ -3890,7 +4086,7 @@ genMinusDec (iCode * ic) { movLeft2ResultLong (IC_LEFT (ic), 0, IC_RESULT (ic), 0, 0, 2); while (icount--) - emit2 ("dec %s", getPairName (AOP (IC_RESULT (ic)))); + emit2 ("dec %s", getPairName (AOP (IC_RESULT (ic)))); return TRUE; } @@ -3921,7 +4117,7 @@ genMinusDec (iCode * ic) if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic)))) { while (icount--) - emit2 ("dec %s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE)); + emit2 ("dec %s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE)); return TRUE; } @@ -3961,7 +4157,7 @@ genMinus (iCode * ic) } else { - lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit); + lit = ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit); lit = -(long) lit; } @@ -3969,45 +4165,45 @@ genMinus (iCode * ic) 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); + 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); if ( AOP_SIZE (IC_RESULT (ic)) > 1) { aopPut (AOP (IC_RESULT (ic)), "a", 1); } - aopPut (AOP (IC_RESULT (ic)), "e", 0); - goto release; - } - } + aopPut (AOP (IC_RESULT (ic)), "e", 0); + goto release; + } + } if (size == 4) { /* Be paranoid on the GB with 4 byte variables due to how C @@ -4018,29 +4214,34 @@ genMinus (iCode * ic) } } - setupToPreserveCarry (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)), AOP (IC_RIGHT (ic))); + setupToPreserveCarry (ic); /* if literal, add a,#-lit, else normal subb */ while (size--) { _moveA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE)); if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) - { - if (!offset) - emit2 ("sub a,%s", - aopGet (AOP (IC_RIGHT (ic)), offset, FALSE)); - else - emit2 ("sbc a,%s", - aopGet (AOP (IC_RIGHT (ic)), offset, FALSE)); - } + { + if (!offset) + emit2 ("sub a,%s", + aopGet (AOP (IC_RIGHT (ic)), offset, FALSE)); + else + emit2 ("sbc a,%s", + aopGet (AOP (IC_RIGHT (ic)), offset, FALSE)); + } else - { - /* first add without previous c */ - if (!offset) - emit2 ("add a,!immedbyte", (unsigned int) (lit & 0x0FFL)); - else - emit2 ("adc a,!immedbyte", (unsigned int) ((lit >> (offset * 8)) & 0x0FFL)); - } + { + /* first add without previous c */ + if (!offset) + { + if (size == 0 && (unsigned int) (lit & 0x0FFL) == 0xFF) + emit2 ("dec a"); + else + emit2 ("add a,!immedbyte", (unsigned int) (lit & 0x0FFL)); + } + else + emit2 ("adc a,!immedbyte", (unsigned int) ((lit >> (offset * 8)) & 0x0FFL)); + } aopPut (AOP (IC_RESULT (ic)), "a", offset++); } @@ -4058,6 +4259,72 @@ release: freeAsmop (IC_RESULT (ic), NULL, ic); } +/*-----------------------------------------------------------------*/ +/* genMultChar - generates code for unsigned 8x8 multiplication */ +/*-----------------------------------------------------------------*/ +static void +genMultOneChar (iCode * ic) +{ + symbol *tlbl1, *tlbl2; + bool savedB = FALSE; + + if(IS_GB) + { + wassertl (0, "Multiplication is handled through support function calls on gbz80"); + return; + } + + /* Save b into a if b is in use. */ + if (bitVectBitValue (ic->rMask, B_IDX) && + !(getPairId (AOP (IC_RESULT (ic))) == PAIR_BC)) + { + emit2 ("ld a, b"); + savedB = TRUE; + } + if (isPairInUse (PAIR_DE, ic) && + !(getPairId (AOP (IC_RESULT (ic))) == PAIR_DE)) + { + _push (PAIR_DE); + _G.stack.pushedDE = TRUE; + } + + tlbl1 = newiTempLabel (NULL); + tlbl2 = newiTempLabel (NULL); + + emit2 ("ld e,%s", aopGet (AOP (IC_RIGHT (ic)), LSB, FALSE)); + emit2 ("ld h,%s", aopGet (AOP (IC_LEFT (ic)), LSB, FALSE)); + emit2 ("ld l,#0x00"); + emit2 ("ld d,l"); + emit2 ("ld b,#0x08"); + emitLabelNoSpill (tlbl1->key + 100); + emit2 ("add hl,hl"); + emit2 ("jp NC,!tlabel", tlbl2->key + 100); + emit2 ("add hl,de"); + emitLabelNoSpill (tlbl2->key + 100); + emit2 ("djnz !tlabel", tlbl1->key + 100); + + spillPair(PAIR_HL); + + if (IS_Z80 && _G.stack.pushedDE) + { + _pop (PAIR_DE); + _G.stack.pushedDE = FALSE; + } + if (savedB) + { + emit2 ("ld b, a"); + } + + if (AOP_SIZE (IC_RESULT (ic)) == 1) + aopPut (AOP (IC_RESULT (ic)), "l", 0); + else + commitPair ( AOP (IC_RESULT (ic)), PAIR_HL); + + freeAsmop (IC_LEFT (ic), NULL, ic); + freeAsmop (IC_RIGHT (ic), NULL, ic); + freeAsmop (IC_RESULT (ic), NULL, ic); +} + /*-----------------------------------------------------------------*/ /* genMult - generates code for multiplication */ /*-----------------------------------------------------------------*/ @@ -4074,7 +4341,7 @@ genMult (iCode * ic) aopOp (IC_LEFT (ic), ic, FALSE, FALSE); aopOp (IC_RIGHT (ic), ic, FALSE, FALSE); aopOp (IC_RESULT (ic), ic, TRUE, FALSE); - + byteResult = (AOP_SIZE (IC_RESULT (ic)) == 1); if (AOP_SIZE (IC_LEFT (ic)) > 2 || @@ -4092,9 +4359,15 @@ genMult (iCode * ic) IC_LEFT (ic) = t; } + if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) + { + genMultOneChar (ic); + return; + } + wassertl (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT, "Right must be a literal"); - val = (int)floatFromVal ( AOP (IC_RIGHT (ic))->aopu.aop_lit); + val = (int) ulFromVal ( AOP (IC_RIGHT (ic))->aopu.aop_lit); // wassertl (val > 0, "Multiply must be positive"); wassertl (val != 1, "Can't multiply by 1"); @@ -4103,7 +4376,9 @@ genMult (iCode * ic) _G.stack.pushedDE = TRUE; } - if ( AOP_SIZE (IC_LEFT (ic)) == 1 && !SPEC_USIGN (getSpec (operandType ( IC_LEFT (ic))))) + if (byteResult) + emit2 ("ld a,%s", aopGet (AOP (IC_LEFT (ic)), LSB, FALSE)); + else if ( AOP_SIZE (IC_LEFT (ic)) == 1 && !SPEC_USIGN (getSpec (operandType ( IC_LEFT (ic))))) { emit2 ("ld e,%s", aopGet (AOP (IC_LEFT (ic)), LSB, FALSE)); if (!byteResult) @@ -4112,7 +4387,7 @@ genMult (iCode * ic) emit2 ("rlc a"); emit2 ("sbc a,a"); emit2 ("ld d,a"); - } + } } else { @@ -4121,32 +4396,40 @@ genMult (iCode * ic) i = val; - /* Fully unroled version of mul.s. Not the most efficient. - */ for (count = 0; count < 16; count++) { if (count != 0 && active) { - emit2 ("add hl,hl"); + if (byteResult) + emit2 ("add a,a"); + else + emit2 ("add hl,hl"); } if (i & 0x8000U) { if (active == FALSE) { - emit2 ("ld l,e"); - if (!byteResult) - emit2 ("ld h,d"); + if (byteResult) + emit2("ld e,a"); + else + { + emit2 ("ld l,e"); + emit2 ("ld h,d"); + } } else { - emit2 ("add hl,de"); + if (byteResult) + emit2 ("add a,e"); + else + emit2 ("add hl,de"); } active = TRUE; } i <<= 1; } - spillCached(); + spillPair(PAIR_HL); if (IS_Z80 && _G.stack.pushedDE) { @@ -4155,7 +4438,7 @@ genMult (iCode * ic) } if (byteResult) - aopPut (AOP (IC_RESULT (ic)), _pairs[PAIR_HL].l, 0); + aopPut (AOP (IC_RESULT (ic)), "a", 0); else commitPair ( AOP (IC_RESULT (ic)), PAIR_HL); @@ -4199,60 +4482,60 @@ genIfxJump (iCode * ic, char *jval) { jlbl = IC_TRUE (ic); if (!strcmp (jval, "a")) - { - inst = "nz"; - } + { + inst = "NZ"; + } else if (!strcmp (jval, "c")) - { - inst = "c"; - } + { + inst = "C"; + } else if (!strcmp (jval, "nc")) - { - inst = "nc"; - } + { + inst = "NC"; + } else if (!strcmp (jval, "m")) - { - inst = "m"; - } + { + inst = "M"; + } else if (!strcmp (jval, "p")) - { - inst = "p"; - } + { + inst = "P"; + } else - { - /* The buffer contains the bit on A that we should test */ - inst = "nz"; - } + { + /* The buffer contains the bit on A that we should test */ + inst = "NZ"; + } } else { /* false label is present */ jlbl = IC_FALSE (ic); if (!strcmp (jval, "a")) - { - inst = "z"; - } + { + inst = "Z"; + } else if (!strcmp (jval, "c")) - { - inst = "nc"; - } + { + inst = "NC"; + } else if (!strcmp (jval, "nc")) - { - inst = "c"; - } + { + inst = "C"; + } else if (!strcmp (jval, "m")) - { - inst = "p"; - } + { + inst = "P"; + } else if (!strcmp (jval, "p")) - { - inst = "m"; - } + { + inst = "M"; + } else - { - /* The buffer contains the bit on A that we should test */ - inst = "z"; - } + { + /* The buffer contains the bit on A that we should test */ + inst = "Z"; + } } /* Z80 can do a conditional long jump */ if (!strcmp (jval, "a")) @@ -4292,17 +4575,17 @@ _getPairIdName (PAIR_ID id) #if OLD /* if unsigned char cmp with lit, just compare */ if ((size == 1) && - (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR)) - { - emit2 ("ld a,%s", aopGet (AOP (left), offset, FALSE)); - if (sign) - { - emit2 ("xor a,!immedbyte", 0x80); - emit2 ("cp %s^!constbyte", aopGet (AOP (right), offset, FALSE), 0x80); - } - else - emit2 ("cp %s", aopGet (AOP (right), offset, FALSE)); - } + (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR)) + { + emit2 ("ld a,%s", aopGet (AOP (left), offset, FALSE)); + if (sign) + { + emit2 ("xor a,!immedbyte", 0x80); + emit2 ("cp %s^!constbyte", aopGet (AOP (right), offset, FALSE), 0x80); + } + else + emit2 ("cp %s", aopGet (AOP (right), offset, FALSE)); + } else if (size == 4 && IS_GB && requiresHL(AOP(right)) && requiresHL(AOP(left))) { // On the Gameboy we can't afford to adjust HL as it may trash the carry. @@ -4334,7 +4617,7 @@ _getPairIdName (PAIR_ID id) emit2 ("ld a,(de)"); emit2 ("%s a,(hl)", offset == 0 ? "sub" : "sbc"); } - + if (size != 0) { emit2 ("inc hl"); @@ -4371,7 +4654,7 @@ _getPairIdName (PAIR_ID id) emit2 ("ld a,(hl)"); emit2 ("%s a,%d(iy)", offset == 0 ? "sub" : "sbc", offset); } - + if (size != 0) { emit2 ("inc hl"); @@ -4382,87 +4665,85 @@ _getPairIdName (PAIR_ID id) spillPair (PAIR_IY); } else - { - if (AOP_TYPE (right) == AOP_LIT) - { - lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit); - /* optimize if(x < 0) or if(x >= 0) */ - if (lit == 0L) - { - if (!sign) - { - /* No sign so it's always false */ - _clearCarry(); - } - else - { - /* Just load in the top most bit */ - _moveA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE)); - if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx) - { - genIfxJump (ifx, "7"); - return; - } - else - emit2 ("rlc a"); - } - goto release; - } - } - - if (sign) - { - /* First setup h and l contaning the top most bytes XORed */ - bool fDidXor = FALSE; - if (AOP_TYPE (left) == AOP_LIT) - { - unsigned long lit = (unsigned long) - floatFromVal (AOP (left)->aopu.aop_lit); - emit2 ("ld %s,!immedbyte", _fTmp[0], - 0x80 ^ (unsigned int) ((lit >> ((size - 1) * 8)) & 0x0FFL)); - } - else - { - emit2 ("ld a,%s", aopGet (AOP (left), size - 1, FALSE)); - emit2 ("xor a,!immedbyte", 0x80); - emit2 ("ld %s,a", _fTmp[0]); - fDidXor = TRUE; - } - if (AOP_TYPE (right) == AOP_LIT) - { - unsigned long lit = (unsigned long) - floatFromVal (AOP (right)->aopu.aop_lit); - emit2 ("ld %s,!immedbyte", _fTmp[1], - 0x80 ^ (unsigned int) ((lit >> ((size - 1) * 8)) & 0x0FFL)); - } - else - { - emit2 ("ld a,%s", aopGet (AOP (right), size - 1, FALSE)); - emit2 ("xor a,!immedbyte", 0x80); - emit2 ("ld %s,a", _fTmp[1]); - fDidXor = TRUE; - } - } - while (size--) - { - /* Do a long subtract */ - if (!sign || size) - { - _moveA (aopGet (AOP (left), offset, FALSE)); - } - if (sign && size == 0) - { - emit2 ("ld a,%s", _fTmp[0]); - emit2 ("%s a,%s", offset == 0 ? "sub" : "sbc", _fTmp[1]); - } - else - { - /* Subtract through, propagating the carry */ - emit2 ("%s a,%s", offset == 0 ? "sub" : "sbc", aopGet (AOP (right), offset, FALSE)); - offset++; - } - } - } + { + if (AOP_TYPE (right) == AOP_LIT) + { + lit = ulFromVal (AOP (right)->aopu.aop_lit); + /* optimize if(x < 0) or if(x >= 0) */ + if (lit == 0L) + { + if (!sign) + { + /* No sign so it's always false */ + _clearCarry(); + } + else + { + /* Just load in the top most bit */ + _moveA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE)); + if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx) + { + genIfxJump (ifx, "7"); + return; + } + else + emit2 ("rlc a"); + } + goto release; + } + } + + if (sign) + { + /* First setup h and l contaning the top most bytes XORed */ + bool fDidXor = FALSE; + if (AOP_TYPE (left) == AOP_LIT) + { + unsigned long lit = ulFromVal (AOP (left)->aopu.aop_lit); + emit2 ("ld %s,!immedbyte", _fTmp[0], + 0x80 ^ (unsigned int) ((lit >> ((size - 1) * 8)) & 0x0FFL)); + } + else + { + emit2 ("ld a,%s", aopGet (AOP (left), size - 1, FALSE)); + emit2 ("xor a,!immedbyte", 0x80); + emit2 ("ld %s,a", _fTmp[0]); + fDidXor = TRUE; + } + if (AOP_TYPE (right) == AOP_LIT) + { + unsigned long lit = ulFromVal (AOP (right)->aopu.aop_lit); + emit2 ("ld %s,!immedbyte", _fTmp[1], + 0x80 ^ (unsigned int) ((lit >> ((size - 1) * 8)) & 0x0FFL)); + } + else + { + emit2 ("ld a,%s", aopGet (AOP (right), size - 1, FALSE)); + emit2 ("xor a,!immedbyte", 0x80); + emit2 ("ld %s,a", _fTmp[1]); + fDidXor = TRUE; + } + } + while (size--) + { + /* Do a long subtract */ + if (!sign || size) + { + _moveA (aopGet (AOP (left), offset, FALSE)); + } + if (sign && size == 0) + { + emit2 ("ld a,%s", _fTmp[0]); + emit2 ("%s a,%s", offset == 0 ? "sub" : "sbc", _fTmp[1]); + } + else + { + /* Subtract through, propagating the carry */ + emit2 ("%s a,%s", offset == 0 ? "sub" : "sbc", aopGet (AOP (right), offset, FALSE)); + offset++; + } + } + } } #endif @@ -4470,11 +4751,10 @@ _getPairIdName (PAIR_ID id) */ static void genCmp (operand * left, operand * right, - operand * result, iCode * ifx, int sign) + operand * result, iCode * ifx, int sign) { int size, offset = 0; unsigned long lit = 0L; - bool swap_sense = FALSE; /* if left & right are bit variables */ if (AOP_TYPE (left) == AOP_CRY && @@ -4501,7 +4781,7 @@ genCmp (operand * left, operand * right, { emit2 ("ld a,(de)"); emit2 ("%s a,(hl)", offset == 0 ? "sub" : "sbc"); - + if (size != 0) { emit2 ("inc hl"); @@ -4515,7 +4795,7 @@ genCmp (operand * left, operand * right, if (AOP_TYPE (right) == AOP_LIT) { - lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit); + lit = ulFromVal (AOP (right)->aopu.aop_lit); /* optimize if(x < 0) or if(x >= 0) */ if (lit == 0) { @@ -4535,13 +4815,13 @@ genCmp (operand * left, operand * right, } else { - if (!sign) + if (!sign) { emit2 ("rlc a"); } if (ifx) { - genIfxJump (ifx, swap_sense ? "c" : "nc"); + genIfxJump (ifx, "nc"); return; } } @@ -4567,7 +4847,7 @@ release: /* Shift the sign bit up into carry */ emit2 ("rlca"); } - outBitCLong (result, swap_sense); + outBitC (result); } else { @@ -4581,16 +4861,16 @@ release: if (IS_GB) { emit2 ("rlca"); - genIfxJump (ifx, swap_sense ? "nc" : "c"); + genIfxJump (ifx, "c"); } else { - genIfxJump (ifx, swap_sense ? "p" : "m"); + genIfxJump (ifx, "m"); } } else { - genIfxJump (ifx, swap_sense ? "nc" : "c"); + genIfxJump (ifx, "c"); } } else @@ -4600,7 +4880,7 @@ release: /* Shift the sign bit up into carry */ emit2 ("rlca"); } - outBitCLong (result, swap_sense); + outBitC (result); } /* leave the result in acc */ } @@ -4623,13 +4903,16 @@ genCmpGt (iCode * ic, iCode * ifx) letype = getSpec (operandType (left)); retype = getSpec (operandType (right)); sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype)); - /* assign the amsops */ + /* assign the asmops */ aopOp (left, ic, FALSE, FALSE); aopOp (right, ic, FALSE, FALSE); aopOp (result, ic, TRUE, FALSE); + setupToPreserveCarry (ic); + genCmp (right, left, result, ifx, sign); + _G.preserveCarry = FALSE; freeAsmop (left, NULL, ic); freeAsmop (right, NULL, ic); freeAsmop (result, NULL, ic); @@ -4653,13 +4936,16 @@ genCmpLt (iCode * ic, iCode * ifx) retype = getSpec (operandType (right)); sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype)); - /* assign the amsops */ + /* assign the asmops */ aopOp (left, ic, FALSE, FALSE); aopOp (right, ic, FALSE, FALSE); aopOp (result, ic, TRUE, FALSE); + setupToPreserveCarry (ic); + genCmp (left, right, result, ifx, sign); + _G.preserveCarry = FALSE; freeAsmop (left, NULL, ic); freeAsmop (right, NULL, ic); freeAsmop (result, NULL, ic); @@ -4667,8 +4953,9 @@ genCmpLt (iCode * ic, iCode * ifx) /*-----------------------------------------------------------------*/ /* gencjneshort - compare and jump if not equal */ +/* returns pair that still needs to be popped */ /*-----------------------------------------------------------------*/ -static void +static PAIR_ID gencjneshort (operand * left, operand * right, symbol * lbl) { int size = max (AOP_SIZE (left), AOP_SIZE (right)); @@ -4683,78 +4970,92 @@ gencjneshort (operand * left, operand * right, symbol * lbl) left = t; } - if (AOP_TYPE (right) == AOP_LIT) - { - lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit); - } - /* if the right side is a literal then anything goes */ - if (AOP_TYPE (right) == AOP_LIT && - AOP_TYPE (left) != AOP_DIR) + if (AOP_TYPE (right) == AOP_LIT) { + lit = ulFromVal (AOP (right)->aopu.aop_lit); if (lit == 0) - { - emit2 ("ld a,%s", aopGet (AOP (left), offset, FALSE)); - if (size > 1) - { - while (--size) - { - emit2 ("or a,%s", aopGet (AOP (left), ++offset, FALSE)); - } - } - else - { - emit2 ("or a,a"); - } - emit2 ("jp nz,!tlabel", lbl->key + 100); - } + { + _moveA (aopGet (AOP (left), offset, FALSE)); + if (size > 1) + { + while (--size) + { + emit2 ("or a,%s", aopGet (AOP (left), ++offset, FALSE)); + } + } + else + { + emit2 ("or a,a"); + } + emit2 ("jp NZ,!tlabel", lbl->key + 100); + } else - { - while (size--) - { - emit2 ("ld a,%s", aopGet (AOP (left), offset, FALSE)); - if ((AOP_TYPE (right) == AOP_LIT) && lit == 0) - emit2 ("or a,a"); - else - emit2 ("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 */ + { + while (size--) + { + _moveA (aopGet (AOP (left), offset, FALSE)); + if ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0) + emit2 ("or a,a"); + else + emit2 ("sub a,%s", aopGet (AOP (right), offset, FALSE)); + emit2 ("jp NZ,!tlabel", lbl->key + 100); + offset++; + } + } + } + /* if the right side is in a register or + pointed to by HL, IX or IY */ else if (AOP_TYPE (right) == AOP_REG || - AOP_TYPE (right) == AOP_DIR || - (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT)) + AOP_TYPE (right) == AOP_HL || + AOP_TYPE (right) == AOP_IY || + AOP_TYPE (right) == AOP_STK || + AOP_IS_PAIRPTR (right, PAIR_HL) || + AOP_IS_PAIRPTR (right, PAIR_IX) || + AOP_IS_PAIRPTR (right, PAIR_IY)) { while (size--) - { - _moveA (aopGet (AOP (left), offset, FALSE)); - if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) && - ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0)) - /* PENDING */ - emit2 ("jp nz,!tlabel", lbl->key + 100); - else - { - emit2 ("cp %s", aopGet (AOP (right), offset, FALSE)); - emit2 ("jp nz,!tlabel", lbl->key + 100); - } - offset++; - } + { + _moveA (aopGet (AOP (left), offset, FALSE)); + if (AOP_TYPE (right) == AOP_LIT && + ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0)) + { + emit2 ("or a,a"); + emit2 ("jp NZ,!tlabel", lbl->key + 100); + } + else + { + emit2 ("sub a,%s", aopGet (AOP (right), offset, FALSE)); + emit2 ("jp NZ,!tlabel", lbl->key + 100); + } + offset++; + } } + /* right is in direct space or a pointer reg, need both a & b */ else { - /* right is a pointer reg need both a & b */ - /* PENDING: is this required? */ + PAIR_ID pair; + for (pair = PAIR_BC; pair <= PAIR_HL; pair++) + { + if (((AOP_TYPE (left) != AOP_PAIRPTR) || (AOP (left)->aopu.aop_pairId != pair)) && + ((AOP_TYPE (right) != AOP_PAIRPTR) || (AOP (right)->aopu.aop_pairId != pair))) + { + break; + } + } + _push (pair); while (size--) - { - _moveA (aopGet (AOP (right), offset, FALSE)); - emit2 ("cp %s", aopGet (AOP (left), offset, FALSE)); - emit2 ("!shortjp nz,!tlabel", lbl->key + 100); - offset++; - } + { + emit2 ("; direct compare"); + _emitMove (_pairs[pair].l, aopGet (AOP (left), offset, FALSE)); + _moveA (aopGet (AOP (right), offset, FALSE)); + emit2 ("sub a,%s", _pairs[pair].l); + emit2 ("!shortjp NZ,!tlabel", lbl->key + 100); + offset++; + } + return pair; } + return PAIR_INVALID; } /*-----------------------------------------------------------------*/ @@ -4765,14 +5066,15 @@ gencjne (operand * left, operand * right, symbol * lbl) { symbol *tlbl = newiTempLabel (NULL); - gencjneshort (left, right, lbl); + PAIR_ID pop = gencjneshort (left, right, lbl); /* PENDING: ?? */ emit2 ("ld a,!one"); emit2 ("!shortjp !tlabel", tlbl->key + 100); emitLabel (lbl->key + 100); emit2 ("xor a,a"); - emitLabel (tlbl->key + 100); + emitLabelNoSpill (tlbl->key + 100); + _pop (pop); } /*-----------------------------------------------------------------*/ @@ -4804,29 +5106,34 @@ genCmpEq (iCode * ic, iCode * ifx) symbol *tlbl; /* if they are both bit variables */ if (AOP_TYPE (left) == AOP_CRY && - ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT))) - { - wassertl (0, "Tried to compare two bits"); - } + ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT))) + { + wassertl (0, "Tried to compare two bits"); + } else - { - tlbl = newiTempLabel (NULL); - gencjneshort (left, right, tlbl); - if (IC_TRUE (ifx)) - { - emit2 ("jp !tlabel", IC_TRUE (ifx)->key + 100); - emitLabel (tlbl->key + 100); - } - else - { - /* PENDING: do this better */ - symbol *lbl = newiTempLabel (NULL); - emit2 ("!shortjp !tlabel", lbl->key + 100); - emitLabel (tlbl->key + 100); - emit2 ("jp !tlabel", IC_FALSE (ifx)->key + 100); - emitLabel (lbl->key + 100); - } - } + { + PAIR_ID pop; + tlbl = newiTempLabel (NULL); + pop = gencjneshort (left, right, tlbl); + if (IC_TRUE (ifx)) + { + _pop (pop); + emit2 ("jp !tlabel", IC_TRUE (ifx)->key + 100); + emitLabelNoSpill (tlbl->key + 100); + _pop (pop); + } + else + { + /* PENDING: do this better */ + symbol *lbl = newiTempLabel (NULL); + _pop (pop); + emit2 ("!shortjp !tlabel", lbl->key + 100); + emitLabelNoSpill (tlbl->key + 100); + _pop (pop); + emit2 ("jp !tlabel", IC_FALSE (ifx)->key + 100); + emitLabelNoSpill (lbl->key + 100); + } + } /* mark the icode as generated */ ifx->generated = 1; goto release; @@ -4841,25 +5148,25 @@ genCmpEq (iCode * ic, iCode * ifx) else { emitDebug(";4"); - + gencjne (left, right, newiTempLabel (NULL)); if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) - { - wassert (0); - } + { + wassert (0); + } if (ifx) - { + { emitDebug(";5"); - genIfxJump (ifx, "a"); - goto release; - } + genIfxJump (ifx, "a"); + goto release; + } /* if the result is used in an arithmetic operation then put the result in place */ if (AOP_TYPE (result) != AOP_CRY) - { + { emitDebug(";6"); - outAcc (result); - } + outAcc (result); + } /* leave the result in acc */ } @@ -4917,9 +5224,9 @@ genAndOp (iCode * ic) { tlbl = newiTempLabel (NULL); _toBoolean (left); - emit2 ("!shortjp z,!tlabel", tlbl->key + 100); + emit2 ("!shortjp Z,!tlabel", tlbl->key + 100); _toBoolean (right); - emitLabel (tlbl->key + 100); + emitLabelNoSpill (tlbl->key + 100); outBitAcc (result); } @@ -4954,9 +5261,9 @@ genOrOp (iCode * ic) { tlbl = newiTempLabel (NULL); _toBoolean (left); - emit2 ("!shortjp nz,!tlabel", tlbl->key + 100); + emit2 ("!shortjp NZ,!tlabel", tlbl->key + 100); _toBoolean (right); - emitLabel (tlbl->key + 100); + emitLabelNoSpill (tlbl->key + 100); outBitAcc (result); } @@ -4998,14 +5305,14 @@ jmpTrueOrFalse (iCode * ic, symbol * tlbl) { symbol *nlbl = newiTempLabel (NULL); emit2 ("jp !tlabel", nlbl->key + 100); - emitLabel (tlbl->key + 100); + emitLabelNoSpill (tlbl->key + 100); emit2 ("jp !tlabel", IC_TRUE (ic)->key + 100); - emitLabel (nlbl->key + 100); + emitLabelNoSpill (nlbl->key + 100); } else { emit2 ("jp !tlabel", IC_FALSE (ic)->key + 100); - emitLabel (tlbl->key + 100); + emitLabelNoSpill (tlbl->key + 100); } ic->generated = 1; } @@ -5051,7 +5358,7 @@ genAnd (iCode * ic, iCode * ifx) left = tmp; } if (AOP_TYPE (right) == AOP_LIT) - lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit); + lit = ulFromVal (AOP (right)->aopu.aop_lit); size = AOP_SIZE (result); @@ -5088,15 +5395,17 @@ genAnd (iCode * ic, iCode * ifx) /* For the flags */ emit2 ("or a,a"); } - emit2 ("!shortjp nz,!tlabel", tlbl->key + 100); + if (size || ifx) /* emit jmp only, if it is actually used */ + emit2 ("!shortjp NZ,!tlabel", tlbl->key + 100); } - offset++; + offset++; } // bit = left & literal if (size) { emit2 ("clr c"); emit2 ("!tlabeldef", tlbl->key + 100); + _G.lines.current->isLabel = 1; } // if(left & literal) else @@ -5115,82 +5424,82 @@ genAnd (iCode * ic, iCode * ifx) if (sameRegs (AOP (result), AOP (left))) { for (; size--; offset++) - { - if (AOP_TYPE (right) == AOP_LIT) - { - if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF) - continue; - else - { - if (bytelit == 0) - aopPut (AOP (result), "!zero", offset); - else - { - _moveA (aopGet (AOP (left), offset, FALSE)); - emit2 ("and a,%s", - aopGet (AOP (right), offset, FALSE)); - aopPut (AOP (left), "a", offset); - } - } - - } - else - { - if (AOP_TYPE (left) == AOP_ACC) - { - wassertl (0, "Tried to perform an AND where the left operand is allocated into A"); - } - else - { - _moveA (aopGet (AOP (left), offset, FALSE)); - emit2 ("and a,%s", - aopGet (AOP (right), offset, FALSE)); - aopPut (AOP (left), "a", offset); - } - } - } + { + if (AOP_TYPE (right) == AOP_LIT) + { + if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF) + continue; + else + { + if (bytelit == 0) + aopPut (AOP (result), "!zero", offset); + else + { + _moveA (aopGet (AOP (left), offset, FALSE)); + emit2 ("and a,%s", + aopGet (AOP (right), offset, FALSE)); + aopPut (AOP (left), "a", offset); + } + } + + } + else + { + if (AOP_TYPE (left) == AOP_ACC) + { + wassertl (0, "Tried to perform an AND where the left operand is allocated into A"); + } + else + { + _moveA (aopGet (AOP (left), offset, FALSE)); + emit2 ("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) - { - wassertl (0, "Tried to AND where the result is in carry"); - } + { + wassertl (0, "Tried to AND where the result is in carry"); + } else - { - for (; (size--); offset++) - { - // normal case - // result = left & right - if (AOP_TYPE (right) == AOP_LIT) - { - if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF) - { - aopPut (AOP (result), - aopGet (AOP (left), offset, FALSE), - offset); - continue; - } - else if (bytelit == 0) - { - aopPut (AOP (result), "!zero", offset); - continue; - } - } - // faster than result <- left, anl result,right - // and better if result is SFR - if (AOP_TYPE (left) == AOP_ACC) - emit2 ("and a,%s", aopGet (AOP (right), offset, FALSE)); - else - { - _moveA (aopGet (AOP (left), offset, FALSE)); - emit2 ("and a,%s", - aopGet (AOP (right), offset, FALSE)); - } - aopPut (AOP (result), "a", offset); - } - } + { + for (; (size--); offset++) + { + // normal case + // result = left & right + if (AOP_TYPE (right) == AOP_LIT) + { + if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF) + { + aopPut (AOP (result), + aopGet (AOP (left), offset, FALSE), + offset); + continue; + } + else if (bytelit == 0) + { + aopPut (AOP (result), "!zero", offset); + continue; + } + } + // faster than result <- left, anl result,right + // and better if result is SFR + if (AOP_TYPE (left) == AOP_ACC) + emit2 ("and a,%s", aopGet (AOP (right), offset, FALSE)); + else + { + _moveA (aopGet (AOP (left), offset, FALSE)); + emit2 ("and a,%s", + aopGet (AOP (right), offset, FALSE)); + } + aopPut (AOP (result), "a", offset); + } + } } @@ -5241,7 +5550,7 @@ genOr (iCode * ic, iCode * ifx) left = tmp; } if (AOP_TYPE (right) == AOP_LIT) - lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit); + lit = ulFromVal (AOP (right)->aopu.aop_lit); size = AOP_SIZE (result); @@ -5264,15 +5573,25 @@ genOr (iCode * ic, iCode * ifx) { wassertl (0, "Result is assigned to a bit"); } - /* PENDING: Modeled after the AND code which is inefficent. */ + /* PENDING: Modeled after the AND code which is inefficient. */ while (sizel--) { bytelit = (lit >> (offset * 8)) & 0x0FFL; _moveA (aopGet (AOP (left), offset, FALSE)); - /* OR with any literal is the same as OR with itself. */ - emit2 ("or a,a"); - emit2 ("!shortjp nz,!tlabel", tlbl->key + 100); + + if (bytelit != 0) + { /* FIXME, allways true, shortcut possible */ + emit2 ("or a,%s", aopGet (AOP (right), offset, FALSE)); + } + else + { + /* For the flags */ + emit2 ("or a,a"); + } + + if (ifx) /* emit jmp only, if it is actually used */ + emit2 ("!shortjp NZ,!tlabel", tlbl->key + 100); offset++; } @@ -5287,70 +5606,70 @@ genOr (iCode * ic, iCode * ifx) if (sameRegs (AOP (result), AOP (left))) { for (; size--; offset++) - { - if (AOP_TYPE (right) == AOP_LIT) - { - if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L) - continue; - else - { - _moveA (aopGet (AOP (left), offset, FALSE)); - emit2 ("or a,%s", - aopGet (AOP (right), offset, FALSE)); - aopPut (AOP (result), "a", offset); - } - } - else - { - if (AOP_TYPE (left) == AOP_ACC) - emit2 ("or a,%s", aopGet (AOP (right), offset, FALSE)); - else - { - _moveA (aopGet (AOP (left), offset, FALSE)); - emit2 ("or a,%s", - aopGet (AOP (right), offset, FALSE)); - aopPut (AOP (result), "a", offset); - } - } - } + { + if (AOP_TYPE (right) == AOP_LIT) + { + if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L) + continue; + else + { + _moveA (aopGet (AOP (left), offset, FALSE)); + emit2 ("or a,%s", + aopGet (AOP (right), offset, FALSE)); + aopPut (AOP (result), "a", offset); + } + } + else + { + if (AOP_TYPE (left) == AOP_ACC) + emit2 ("or a,%s", aopGet (AOP (right), offset, FALSE)); + else + { + _moveA (aopGet (AOP (left), offset, FALSE)); + emit2 ("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) - { - wassertl (0, "Result of OR is in a bit"); - } + { + wassertl (0, "Result of OR is in a bit"); + } else - for (; (size--); offset++) - { - // normal case - // result = left & right - if (AOP_TYPE (right) == AOP_LIT) - { - if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L) - { - aopPut (AOP (result), - aopGet (AOP (left), offset, FALSE), - offset); - continue; - } - } - // faster than result <- left, anl result,right - // and better if result is SFR - if (AOP_TYPE (left) == AOP_ACC) - emit2 ("or a,%s", aopGet (AOP (right), offset, FALSE)); - else - { - _moveA (aopGet (AOP (left), offset, FALSE)); - emit2 ("or a,%s", - aopGet (AOP (right), offset, FALSE)); - } - aopPut (AOP (result), "a", offset); - /* PENDING: something weird is going on here. Add exception. */ - if (AOP_TYPE (result) == AOP_ACC) - break; - } + for (; (size--); offset++) + { + // normal case + // result = left & right + if (AOP_TYPE (right) == AOP_LIT) + { + if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L) + { + aopPut (AOP (result), + aopGet (AOP (left), offset, FALSE), + offset); + continue; + } + } + // faster than result <- left, anl result,right + // and better if result is SFR + if (AOP_TYPE (left) == AOP_ACC) + emit2 ("or a,%s", aopGet (AOP (right), offset, FALSE)); + else + { + _moveA (aopGet (AOP (left), offset, FALSE)); + emit2 ("or a,%s", + aopGet (AOP (right), offset, FALSE)); + } + aopPut (AOP (result), "a", offset); + /* PENDING: something weird is going on here. Add exception. */ + if (AOP_TYPE (result) == AOP_ACC) + break; + } } release: @@ -5399,7 +5718,7 @@ genXor (iCode * ic, iCode * ifx) left = tmp; } if (AOP_TYPE (right) == AOP_LIT) - lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit); + lit = ulFromVal (AOP (right)->aopu.aop_lit); size = AOP_SIZE (result); @@ -5427,7 +5746,7 @@ genXor (iCode * ic, iCode * ifx) { _moveA (aopGet (AOP (left), offset, FALSE)); emit2 ("xor a,%s", aopGet (AOP (right), offset, FALSE)); - emit2 ("!shortjp nz,!tlabel", tlbl->key + 100); + emit2 ("!shortjp NZ,!tlabel", tlbl->key + 100); offset++; } if (ifx) @@ -5445,71 +5764,71 @@ genXor (iCode * ic, iCode * ifx) if (sameRegs (AOP (result), AOP (left))) { for (; size--; offset++) - { - if (AOP_TYPE (right) == AOP_LIT) - { - if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L) - continue; - else - { - _moveA (aopGet (AOP (left), offset, FALSE)); - emit2 ("xor a,%s", - aopGet (AOP (right), offset, FALSE)); - aopPut (AOP (result), "a", offset); - } - } - else - { - if (AOP_TYPE (left) == AOP_ACC) + { + if (AOP_TYPE (right) == AOP_LIT) + { + if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L) + continue; + else + { + _moveA (aopGet (AOP (left), offset, FALSE)); + emit2 ("xor a,%s", + aopGet (AOP (right), offset, FALSE)); + aopPut (AOP (result), "a", offset); + } + } + else + { + if (AOP_TYPE (left) == AOP_ACC) { emit2 ("xor a,%s", aopGet (AOP (right), offset, FALSE)); } - else - { - _moveA (aopGet (AOP (left), offset, FALSE)); - emit2 ("xor a,%s", - aopGet (AOP (right), offset, FALSE)); - aopPut (AOP (result), "a", offset); - } - } - } + else + { + _moveA (aopGet (AOP (left), offset, FALSE)); + emit2 ("xor a,%s", + aopGet (AOP (right), offset, FALSE)); + aopPut (AOP (result), "a", offset); + } + } + } } else { // left & result in different registers if (AOP_TYPE (result) == AOP_CRY) - { - wassertl (0, "Result of XOR is in a bit"); - } + { + wassertl (0, "Result of XOR is in a bit"); + } else - for (; (size--); offset++) - { - // normal case - // result = left & right - if (AOP_TYPE (right) == AOP_LIT) - { - if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L) - { - aopPut (AOP (result), - aopGet (AOP (left), offset, FALSE), - offset); - continue; - } - } - // faster than result <- left, anl result,right - // and better if result is SFR - if (AOP_TYPE (left) == AOP_ACC) + for (; (size--); offset++) + { + // normal case + // result = left & right + if (AOP_TYPE (right) == AOP_LIT) + { + if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L) + { + aopPut (AOP (result), + aopGet (AOP (left), offset, FALSE), + offset); + continue; + } + } + // faster than result <- left, anl result,right + // and better if result is SFR + if (AOP_TYPE (left) == AOP_ACC) { emit2 ("xor a,%s", aopGet (AOP (right), offset, FALSE)); } - else - { - _moveA (aopGet (AOP (left), offset, FALSE)); - emit2 ("xor a,%s", - aopGet (AOP (right), offset, FALSE)); - } - aopPut (AOP (result), "a", offset); - } + else + { + _moveA (aopGet (AOP (left), offset, FALSE)); + emit2 ("xor a,%s", + aopGet (AOP (right), offset, FALSE)); + } + aopPut (AOP (result), "a", offset); + } } release: @@ -5525,37 +5844,49 @@ static void genInline (iCode * ic) { char *buffer, *bp, *bp1; + bool inComment = FALSE; _G.lines.isInline += (!options.asmpeep); - buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1); - strcpy (buffer, IC_INLINE (ic)); + buffer = bp = bp1 = Safe_strdup (IC_INLINE (ic)); /* emit each line as a code */ while (*bp) { - if (*bp == '\n') - { - *bp++ = '\0'; - emit2 (bp1); - bp1 = bp; - } - else - { - if (*bp == ':') - { - bp++; - *bp = '\0'; - bp++; - emit2 (bp1); - bp1 = bp; - } - else - bp++; - } + switch (*bp) + { + case ';': + inComment = TRUE; + ++bp; + break; + + case '\n': + inComment = FALSE; + *bp++ = '\0'; + emit2 (bp1); + bp1 = bp; + break; + + default: + /* Add \n for labels, not dirs such as c:\mydir */ + if (!inComment && (*bp == ':') && (isspace((unsigned char)bp[1]))) + { + ++bp; + *bp = '\0'; + ++bp; + emit2 (bp1); + bp1 = bp; + } + else + ++bp; + break; + } } if (bp1 != bp) emit2 (bp1); + + Safe_free (buffer); + _G.lines.isInline -= (!options.asmpeep); } @@ -5636,22 +5967,25 @@ emitRsh2 (asmop *aop, int size, int is_signed) /*-----------------------------------------------------------------*/ static void shiftR2Left2Result (operand * left, int offl, - operand * result, int offr, - int shCount, int is_signed) + operand * result, int offr, + int shCount, int is_signed) { int size = 2; - symbol *tlbl, *tlbl1; + symbol *tlbl; movLeft2Result (left, offl, result, offr, 0); movLeft2Result (left, offl + 1, result, offr + 1, 0); + if (shCount == 0) + return; + /* if (AOP(result)->type == AOP_REG) { */ - + tlbl = newiTempLabel (NULL); - tlbl1 = newiTempLabel (NULL); /* Left is already in result - so now do the shift */ - if (shCount <= 4) + /* Optimizing for speed by default. */ + if (!optimize.codeSize || shCount <= 2) { while (shCount--) { @@ -5660,15 +5994,14 @@ shiftR2Left2Result (operand * left, int offl, } else { - emit2 ("ld a,!immedbyte+1", shCount); - emit2 ("!shortjp !tlabel", tlbl1->key + 100); - emitLabel (tlbl->key + 100); + emit2 ("ld a,!immedbyte", shCount); + + emitLabelNoSpill (tlbl->key + 100); emitRsh2 (AOP (result), size, is_signed); - emitLabel (tlbl1->key + 100); emit2 ("dec a"); - emit2 ("!shortjp nz,!tlabel", tlbl->key + 100); + emit2 ("!shortjp NZ,!tlabel", tlbl->key + 100); } } @@ -5677,7 +6010,7 @@ shiftR2Left2Result (operand * left, int offl, /*-----------------------------------------------------------------*/ static void shiftL2Left2Result (operand * left, int offl, - operand * result, int offr, int shCount) + operand * result, int offr, int shCount) { if (sameRegs (AOP (result), AOP (left)) && ((offl + MSB16) == offr)) @@ -5691,12 +6024,15 @@ shiftL2Left2Result (operand * left, int offl, movLeft2Result (left, offl + 1, result, offr + 1, 0); } + if (shCount == 0) + return; + if (getPairId (AOP (result)) == PAIR_HL) { while (shCount--) - { - emit2 ("add hl,hl"); - } + { + emit2 ("add hl,hl"); + } } else { @@ -5710,54 +6046,54 @@ shiftL2Left2Result (operand * left, int offl, if (AOP (result)->type == AOP_REG) { - while (shCount--) - { - for (offset = 0; offset < size; offset++) - { - l = aopGet (AOP (result), offset, FALSE); - - if (offset == 0) - { - emit2 ("sla %s", l); - } - else - { - emit2 ("rl %s", l); - } - } - } + while (shCount--) + { + for (offset = 0; offset < size; offset++) + { + l = aopGet (AOP (result), offset, FALSE); + + if (offset == 0) + { + emit2 ("sla %s", l); + } + else + { + emit2 ("rl %s", l); + } + } + } } else { - /* Left is already in result - so now do the shift */ - if (shCount > 1) - { - emit2 ("ld a,!immedbyte+1", shCount); - emit2 ("!shortjp !tlabel", tlbl1->key + 100); - emitLabel (tlbl->key + 100); - } - - while (size--) - { - l = aopGet (AOP (result), offset, FALSE); - - if (offset == 0) - { - emit2 ("sla %s", l); - } - else - { - emit2 ("rl %s", l); - } - - offset++; - } - if (shCount > 1) - { - emitLabel (tlbl1->key + 100); - emit2 ("dec a"); - emit2 ("!shortjp nz,!tlabel", tlbl->key + 100); - } + /* Left is already in result - so now do the shift */ + if (shCount > 1) + { + emit2 ("ld a,!immedbyte+1", shCount); + emit2 ("!shortjp !tlabel", tlbl1->key + 100); + emitLabelNoSpill (tlbl->key + 100); + } + + while (size--) + { + l = aopGet (AOP (result), offset, FALSE); + + if (offset == 0) + { + emit2 ("sla %s", l); + } + else + { + emit2 ("rl %s", l); + } + + offset++; + } + if (shCount > 1) + { + emitLabelNoSpill (tlbl1->key + 100); + emit2 ("dec a"); + emit2 ("!shortjp NZ,!tlabel", tlbl->key + 100); + } } } } @@ -5768,7 +6104,7 @@ shiftL2Left2Result (operand * left, int offl, static void AccRol (int shCount) { - shCount &= 0x0007; // shCount : 0..7 + shCount &= 0x0007; // shCount : 0..7 #if 0 switch (shCount) @@ -5859,21 +6195,21 @@ AccLsh (int shCount) if (shCount != 0) { if (shCount == 1) - { - emit2 ("add a,a"); - } + { + emit2 ("add a,a"); + } else if (shCount == 2) - { - emit2 ("add a,a"); - emit2 ("add a,a"); - } + { + emit2 ("add a,a"); + emit2 ("add a,a"); + } else - { - /* rotate left accumulator */ - AccRol (shCount); - /* and kill the lower order bits */ - emit2 ("and a,!immedbyte", SLMask[shCount]); - } + { + /* rotate left accumulator */ + AccRol (shCount); + /* and kill the lower order bits */ + emit2 ("and a,!immedbyte", SLMask[shCount]); + } } } @@ -5882,19 +6218,31 @@ AccLsh (int shCount) /*-----------------------------------------------------------------*/ static void shiftL1Left2Result (operand * left, int offl, - operand * result, int offr, int shCount) + operand * result, int offr, int shCount) { const char *l; - l = aopGet (AOP (left), offl, FALSE); - _moveA (l); - /* shift left accumulator */ - AccLsh (shCount); - aopPut (AOP (result), "a", offr); -} + /* If operand and result are the same we can shift in place. + However shifting in acc using add is cheaper than shifting + in place using sla; when shifting by more than 2 shifting in + acc is worth the additional effort for loading from/to acc. */ + if (sameRegs (AOP (left), AOP (result)) && shCount <= 2 && offr == offl) + { + while (shCount--) + emit2 ("sla %s", aopGet (AOP (result), 0, FALSE)); + } + else + { + l = aopGet (AOP (left), offl, FALSE); + _moveA (l); + /* shift left accumulator */ + AccLsh (shCount); + aopPut (AOP (result), "a", offr); + } +} /*-----------------------------------------------------------------*/ -/* genlshTwo - left shift two bytes by known amount != 0 */ +/* genlshTwo - left shift two bytes by known amount */ /*-----------------------------------------------------------------*/ static void genlshTwo (operand * result, operand * left, int shCount) @@ -5908,35 +6256,35 @@ genlshTwo (operand * result, operand * left, int shCount) { shCount -= 8; if (size > 1) - { - if (shCount) - { - movLeft2Result (left, LSB, result, MSB16, 0); - aopPut (AOP (result), "!zero", 0); - shiftL1Left2Result (left, LSB, result, MSB16, shCount); - } - else - { - movLeft2Result (left, LSB, result, MSB16, 0); - aopPut (AOP (result), "!zero", 0); - } - } + { + if (shCount) + { + movLeft2Result (left, LSB, result, MSB16, 0); + shiftL1Left2Result (left, LSB, result, MSB16, shCount); + aopPut (AOP (result), "!zero", LSB); + } + else + { + movLeft2Result (left, LSB, result, MSB16, 0); + aopPut (AOP (result), "!zero", 0); + } + } else - { - aopPut (AOP (result), "!zero", LSB); - } + { + aopPut (AOP (result), "!zero", LSB); + } } - /* 1 <= shCount <= 7 */ + /* 0 <= shCount <= 7 */ else { if (size == 1) - { - wassert (0); - } + { + wassert (0); + } else - { - shiftL2Left2Result (left, LSB, result, LSB, shCount); - } + { + shiftL2Left2Result (left, LSB, result, LSB, shCount); + } } } @@ -5954,11 +6302,11 @@ genlshOne (operand * result, operand * left, int shCount) /*-----------------------------------------------------------------*/ static void genLeftShiftLiteral (operand * left, - operand * right, - operand * result, - iCode * ic) + operand * right, + operand * result, + iCode * ic) { - int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit); + int shCount = (int) ulFromVal (AOP (right)->aopu.aop_lit); int size; freeAsmop (right, NULL, ic); @@ -5969,12 +6317,8 @@ genLeftShiftLiteral (operand * left, size = getSize (operandType (result)); /* I suppose that the left size >= result size */ - if (shCount == 0) - { - wassert (0); - } - else if (shCount >= (size * 8)) + if (shCount >= (size * 8)) { while (size--) { @@ -5984,19 +6328,19 @@ genLeftShiftLiteral (operand * left, else { switch (size) - { - case 1: - genlshOne (result, left, shCount); - break; - case 2: - genlshTwo (result, left, shCount); - break; - case 4: - wassertl (0, "Shifting of longs is currently unsupported"); - break; - default: - wassert (0); - } + { + case 1: + genlshOne (result, left, shCount); + break; + case 2: + genlshTwo (result, left, shCount); + break; + case 4: + wassertl (0, "Shifting of longs is currently unsupported"); + break; + default: + wassert (0); + } } freeAsmop (left, NULL, ic); freeAsmop (result, NULL, ic); @@ -6037,6 +6381,9 @@ genLeftShift (iCode * ic) aopOp (left, ic, FALSE, FALSE); aopOp (result, ic, FALSE, FALSE); + if (AOP_TYPE (left) != AOP_REG || AOP_TYPE (result) != AOP_REG) + _push (PAIR_AF); + /* now move the left to the result if they are not the same */ @@ -6046,11 +6393,11 @@ genLeftShift (iCode * ic) size = AOP_SIZE (result); offset = 0; while (size--) - { - l = aopGet (AOP (left), offset, FALSE); - aopPut (AOP (result), l, offset); - offset++; - } + { + l = aopGet (AOP (left), offset, FALSE); + aopPut (AOP (result), l, offset); + offset++; + } } tlbl = newiTempLabel (NULL); @@ -6058,8 +6405,11 @@ genLeftShift (iCode * ic) offset = 0; tlbl1 = newiTempLabel (NULL); + if (AOP_TYPE (left) != AOP_REG || AOP_TYPE (result) != AOP_REG) + _pop (PAIR_AF); + emit2 ("!shortjp !tlabel", tlbl1->key + 100); - emitLabel (tlbl->key + 100); + emitLabelNoSpill (tlbl->key + 100); l = aopGet (AOP (result), offset, FALSE); while (size--) @@ -6076,9 +6426,9 @@ genLeftShift (iCode * ic) } offset++; } - emitLabel (tlbl1->key + 100); + emitLabelNoSpill (tlbl1->key + 100); emit2 ("dec a"); - emit2 ("!shortjp nz,!tlabel", tlbl->key + 100); + emit2 ("!shortjp NZ,!tlabel", tlbl->key + 100); freeAsmop (left, NULL, ic); freeAsmop (result, NULL, ic); @@ -6112,9 +6462,9 @@ genrshOne (operand * result, operand * left, int shCount, int is_signed) { _moveA (l); while (shCount--) - { - emit2 ("%s a", is_signed ? "sra" : "srl"); - } + { + emit2 ("%s a", is_signed ? "sra" : "srl"); + } aopPut (AOP (result), "a", 0); } } @@ -6144,16 +6494,16 @@ AccRsh (int shCount) /*-----------------------------------------------------------------*/ static void shiftR1Left2Result (operand * left, int offl, - operand * result, int offr, - int shCount, int sign) + operand * result, int offr, + int shCount, int sign) { _moveA (aopGet (AOP (left), offl, FALSE)); if (sign) { while (shCount--) - { - emit2 ("%s a", sign ? "sra" : "srl"); - } + { + emit2 ("%s a", sign ? "sra" : "srl"); + } } else { @@ -6163,25 +6513,25 @@ shiftR1Left2Result (operand * left, int offl, } /*-----------------------------------------------------------------*/ -/* genrshTwo - right shift two bytes by known amount != 0 */ +/* genrshTwo - right shift two bytes by known amount */ /*-----------------------------------------------------------------*/ static void genrshTwo (operand * result, operand * left, - int shCount, int sign) + int shCount, int sign) { /* if shCount >= 8 */ if (shCount >= 8) { shCount -= 8; if (shCount) - { - shiftR1Left2Result (left, MSB16, result, LSB, - shCount, sign); - } + { + shiftR1Left2Result (left, MSB16, result, LSB, + shCount, sign); + } else - { - movLeft2Result (left, MSB16, result, LSB, sign); - } + { + movLeft2Result (left, MSB16, result, LSB, sign); + } if (sign) { /* Sign extend the result */ @@ -6196,7 +6546,7 @@ genrshTwo (operand * result, operand * left, aopPut (AOP (result), "!zero", 1); } } - /* 1 <= shCount <= 7 */ + /* 0 <= shCount <= 7 */ else { shiftR2Left2Result (left, LSB, result, LSB, shCount, sign); @@ -6208,12 +6558,12 @@ genrshTwo (operand * result, operand * left, /*-----------------------------------------------------------------*/ static void genRightShiftLiteral (operand * left, - operand * right, - operand * result, - iCode * ic, + operand * right, + operand * result, + iCode * ic, int sign) { - int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit); + int shCount = (int) ulFromVal (AOP (right)->aopu.aop_lit); int size; freeAsmop (right, NULL, ic); @@ -6224,12 +6574,8 @@ genRightShiftLiteral (operand * left, size = getSize (operandType (result)); /* I suppose that the left size >= result size */ - if (shCount == 0) - { - wassert (0); - } - else if (shCount >= (size * 8)) { + if (shCount >= (size * 8)) { const char *s; if (!SPEC_USIGN(getSpec(operandType(left)))) { _moveA(aopGet (AOP (left), 0, FALSE)); @@ -6245,19 +6591,19 @@ genRightShiftLiteral (operand * left, else { switch (size) - { - case 1: - genrshOne (result, left, shCount, sign); - break; - case 2: - genrshTwo (result, left, shCount, sign); - break; - case 4: - wassertl (0, "Asked to shift right a long which should be a function call"); - break; - default: - wassertl (0, "Entered default case in right shift delegate"); - } + { + case 1: + genrshOne (result, left, shCount, sign); + break; + case 2: + genrshTwo (result, left, shCount, sign); + break; + case 4: + wassertl (0, "Asked to shift right a long which should be a function call"); + break; + default: + wassertl (0, "Entered default case in right shift delegate"); + } } freeAsmop (left, NULL, ic); freeAsmop (result, NULL, ic); @@ -6311,6 +6657,9 @@ genRightShift (iCode * ic) aopOp (left, ic, FALSE, FALSE); aopOp (result, ic, FALSE, FALSE); + if (AOP_TYPE (left) != AOP_REG || AOP_TYPE (result) != AOP_REG) + _push (PAIR_AF); + /* now move the left to the result if they are not the same */ if (!sameRegs (AOP (left), AOP (result))) @@ -6319,11 +6668,11 @@ genRightShift (iCode * ic) size = AOP_SIZE (result); offset = 0; while (size--) - { - l = aopGet (AOP (left), offset, FALSE); - aopPut (AOP (result), l, offset); - offset++; - } + { + l = aopGet (AOP (left), offset, FALSE); + aopPut (AOP (result), l, offset); + offset++; + } } tlbl = newiTempLabel (NULL); @@ -6331,24 +6680,27 @@ genRightShift (iCode * ic) size = AOP_SIZE (result); offset = size - 1; + if (AOP_TYPE (left) != AOP_REG || AOP_TYPE (result) != AOP_REG) + _pop (PAIR_AF); + emit2 ("!shortjp !tlabel", tlbl1->key + 100); - emitLabel (tlbl->key + 100); + emitLabelNoSpill (tlbl->key + 100); while (size--) { l = aopGet (AOP (result), offset--, FALSE); if (first) - { + { emit2 ("%s %s", is_signed ? "sra" : "srl", l); - first = 0; - } + first = 0; + } else { emit2 ("rr %s", l); } } - emitLabel (tlbl1->key + 100); + emitLabelNoSpill (tlbl1->key + 100); emit2 ("dec a"); - emit2 ("!shortjp nz,!tlabel", tlbl->key + 100); + emit2 ("!shortjp NZ,!tlabel", tlbl->key + 100); freeAsmop (left, NULL, ic); freeAsmop (result, NULL, ic); @@ -6361,12 +6713,12 @@ genRightShift (iCode * ic) static void genUnpackBits (operand * result, int pair) { - int offset = 0; /* result byte offset */ - int rsize; /* result size */ - int rlen = 0; /* remaining bitfield length */ - sym_link *etype; /* bitfield type information */ - int blen; /* bitfield length */ - int bstr; /* bitfield starting bit within byte */ + int offset = 0; /* result byte offset */ + int rsize; /* result size */ + int rlen = 0; /* remaining bitfield length */ + sym_link *etype; /* bitfield type information */ + int blen; /* bitfield length */ + int bstr; /* bitfield starting bit within byte */ emitDebug ("; genUnpackBits"); @@ -6379,8 +6731,18 @@ genUnpackBits (operand * result, int pair) if (blen < 8) { emit2 ("ld a,!*pair", _pairs[pair].name); - AccRsh (bstr); + AccRol (8 - bstr); emit2 ("and a,!immedbyte", ((unsigned char) -1) >> (8 - blen)); + if (!SPEC_USIGN (etype)) + { + /* signed bitfield */ + symbol *tlbl = newiTempLabel (NULL); + + emit2 ("bit %d,a", blen - 1); + emit2 ("jp Z,!tlabel", tlbl->key + 100); + emit2 ("or a,!immedbyte", (unsigned char) (0xff << blen)); + emitLabelNoSpill (tlbl->key + 100); + } aopPut (AOP (result), "a", offset++); goto finish; } @@ -6395,6 +6757,15 @@ genUnpackBits (operand * result, int pair) emit2 ("ld l,a"); emit2 ("ld a,h"); emit2 ("and a,!immedbyte", ((unsigned char) -1) >> (16 - blen)); + if (!SPEC_USIGN (etype)) + { + /* signed bitfield */ + symbol *tlbl = newiTempLabel (NULL); + emit2 ("bit %d,a", blen - 1 - 8); + emit2 ("jp Z,!tlabel", tlbl->key + 100); + emit2 ("or a,!immedbyte", (unsigned char) (0xff << (blen - 8))); + emitLabelNoSpill (tlbl->key + 100); + } emit2 ("ld h,a"); spillPair (PAIR_HL); return; @@ -6418,15 +6789,37 @@ genUnpackBits (operand * result, int pair) { emit2 ("ld a,!*pair", _pairs[pair].name); emit2 ("and a,!immedbyte", ((unsigned char) -1) >> (8 - rlen)); + if (!SPEC_USIGN (etype)) + { + /* signed bitfield */ + symbol *tlbl = newiTempLabel (NULL); + + emit2 ("bit %d,a", rlen - 1); + emit2 ("jp Z,!tlabel", tlbl->key + 100); + emit2 ("or a,!immedbyte", (unsigned char) (0xff << rlen)); + emitLabelNoSpill (tlbl->key + 100); + } aopPut (AOP (result), "a", offset++); } finish: if (offset < rsize) { + char *source; + + if (SPEC_USIGN (etype)) + source = "!zero"; + else + { + /* signed bitfield: sign extension with 0x00 or 0xff */ + emit2 ("rla"); + emit2 ("sbc a,a"); + + source = "a"; + } rsize -= offset; while (rsize--) - aopPut (AOP (result), "!zero", offset++); + aopPut (AOP (result), source, offset++); } } @@ -6435,7 +6828,7 @@ finish: /*-----------------------------------------------------------------*/ static void genGenPointerGet (operand * left, - operand * result, iCode * ic) + operand * result, iCode * ic) { int size, offset; sym_link *retype = getSpec (operandType (result)); @@ -6453,16 +6846,16 @@ genGenPointerGet (operand * left, { /* Just do it */ if (isPtrPair (AOP (left))) - { - tsprintf (buffer, sizeof(buffer), - "!*pair", getPairName (AOP (left))); - aopPut (AOP (result), buffer, 0); - } + { + tsprintf (buffer, sizeof(buffer), + "!*pair", getPairName (AOP (left))); + aopPut (AOP (result), buffer, 0); + } else - { - emit2 ("ld a,!*pair", getPairName (AOP (left))); - aopPut (AOP (result), "a", 0); - } + { + emit2 ("ld a,!*pair", getPairName (AOP (left))); + aopPut (AOP (result), "a", 0); + } freeAsmop (left, NULL, ic); goto release; } @@ -6471,14 +6864,14 @@ genGenPointerGet (operand * left, { /* Just do it */ offset = 0; - while (size--) + while (size--) { char at[20]; tsprintf (at, sizeof(at), "!*iyx", offset); aopPut (AOP (result), at, offset); offset++; } - + freeAsmop (left, NULL, ic); goto release; } @@ -6510,23 +6903,23 @@ genGenPointerGet (operand * left, offset = 0; while (size--) - { - /* PENDING: make this better */ - if (!IS_GB && AOP_TYPE (result) == AOP_REG) - { - aopPut (AOP (result), "!*hl", offset++); - } - else - { - emit2 ("ld a,!*pair", _pairs[pair].name); - aopPut (AOP (result), "a", offset++); - } - if (size) - { - emit2 ("inc %s", _pairs[pair].name); - _G.pairs[pair].offset++; - } - } + { + /* PENDING: make this better */ + if (!IS_GB && AOP_TYPE (result) == AOP_REG) + { + aopPut (AOP (result), "!*hl", offset++); + } + else + { + emit2 ("ld a,!*pair", _pairs[pair].name); + aopPut (AOP (result), "a", offset++); + } + if (size) + { + emit2 ("inc %s", _pairs[pair].name); + _G.pairs[pair].offset++; + } + } /* Fixup HL back down */ for (size = AOP_SIZE (result)-1; size; size--) { @@ -6539,24 +6932,24 @@ genGenPointerGet (operand * left, offset = 0; while (size--) - { - /* PENDING: make this better */ - if (!IS_GB && + { + /* PENDING: make this better */ + if (!IS_GB && (AOP_TYPE (result) == AOP_REG || AOP_TYPE (result) == AOP_HLREG)) - { - aopPut (AOP (result), "!*hl", offset++); - } - else - { - emit2 ("ld a,!*pair", _pairs[pair].name); - aopPut (AOP (result), "a", offset++); - } - if (size) - { - emit2 ("inc %s", _pairs[pair].name); - _G.pairs[pair].offset++; - } - } + { + aopPut (AOP (result), "!*hl", offset++); + } + else + { + emit2 ("ld a,!*pair", _pairs[pair].name); + aopPut (AOP (result), "a", offset++); + } + if (size) + { + emit2 ("inc %s", _pairs[pair].name); + _G.pairs[pair].offset++; + } + } } freeAsmop (left, NULL, ic); @@ -6599,18 +6992,18 @@ isRegOrLit (asmop * aop) /*-----------------------------------------------------------------*/ static void genPackBits (sym_link * etype, - operand * right, - int pair, - iCode *ic) -{ - int offset = 0; /* source byte offset */ - int rlen = 0; /* remaining bitfield length */ - int blen; /* bitfield length */ - int bstr; /* bitfield starting bit within byte */ - int litval; /* source literal value (if AOP_LIT) */ - unsigned char mask; /* bitmask within current byte */ - int extraPair; /* a tempory register */ - bool needPopExtra=0; /* need to restore original value of temp reg */ + operand * right, + int pair, + iCode *ic) +{ + int offset = 0; /* source byte offset */ + int rlen = 0; /* remaining bitfield length */ + int blen; /* bitfield length */ + int bstr; /* bitfield starting bit within byte */ + int litval; /* source literal value (if AOP_LIT) */ + unsigned char mask; /* bitmask within current byte */ + int extraPair; /* a tempory register */ + bool needPopExtra=0; /* need to restore original value of temp reg */ emitDebug ("; genPackBits",""); @@ -6621,13 +7014,13 @@ genPackBits (sym_link * etype, if (blen < 8) { mask = ((unsigned char) (0xFF << (blen + bstr)) | - (unsigned char) (0xFF >> (8 - bstr))); + (unsigned char) (0xFF >> (8 - bstr))); if (AOP_TYPE (right) == AOP_LIT) { /* Case with a bitfield length <8 and literal source */ - litval = (int) floatFromVal (AOP (right)->aopu.aop_lit); + litval = (int) ulFromVal (AOP (right)->aopu.aop_lit); litval <<= bstr; litval &= (~mask) & 0xff; emit2 ("ld a,!*pair", _pairs[pair].name); @@ -6687,12 +7080,12 @@ genPackBits (sym_link * etype, if (rlen) { mask = (((unsigned char) -1 << rlen) & 0xff); - + if (AOP_TYPE (right) == AOP_LIT) { /* Case with partial byte and literal source */ - litval = (int) floatFromVal (AOP (right)->aopu.aop_lit); + litval = (int) ulFromVal (AOP (right)->aopu.aop_lit); litval >>= (blen-rlen); litval &= (~mask) & 0xff; emit2 ("ld a,!*pair", _pairs[pair].name); @@ -6741,14 +7134,14 @@ genPackBits (sym_link * etype, /*-----------------------------------------------------------------*/ static void genGenPointerSet (operand * right, - operand * result, iCode * ic) + operand * result, iCode * ic) { int size, offset; sym_link *retype = getSpec (operandType (right)); sym_link *letype = getSpec (operandType (result)); PAIR_ID pairId = PAIR_HL; bool isBitvar; - + aopOp (result, ic, FALSE, FALSE); aopOp (right, ic, FALSE, FALSE); @@ -6767,24 +7160,24 @@ genGenPointerSet (operand * right, const char *l = aopGet (AOP (right), 0, FALSE); const char *pair = getPairName (AOP (result)); if (canAssignToPtr (l) && isPtr (pair)) - { - emit2 ("ld !*pair,%s", pair, l); - } + { + emit2 ("ld !*pair,%s", pair, l); + } else - { - _moveA (l); - emit2 ("ld !*pair,a", pair); - } + { + _moveA (l); + emit2 ("ld !*pair,a", pair); + } goto release; } - + if ( getPairId( AOP (result)) == PAIR_IY && !isBitvar) { /* Just do it */ const char *l = aopGet (AOP (right), 0, FALSE); offset = 0; - while (size--) + while (size--) { if (canAssignToPtr (l)) { @@ -6805,24 +7198,24 @@ genGenPointerSet (operand * right, offset = 0; while (size--) - { - const char *l = aopGet (AOP (right), offset, FALSE); - if (isRegOrLit (AOP (right)) && !IS_GB) - { - emit2 ("ld !*pair,%s", _pairs[PAIR_HL].name, l); - } - else - { - _moveA (l); - emit2 ("ld !*pair,a", _pairs[PAIR_HL].name); - } - if (size) - { - emit2 ("inc %s", _pairs[PAIR_HL].name); - _G.pairs[PAIR_HL].offset++; - } - offset++; - } + { + const char *l = aopGet (AOP (right), offset, FALSE); + if (isRegOrLit (AOP (right)) && !IS_GB) + { + emit2 ("ld !*pair,%s", _pairs[PAIR_HL].name, l); + } + else + { + _moveA (l); + emit2 ("ld !*pair,a", _pairs[PAIR_HL].name); + } + if (size) + { + emit2 ("inc %s", _pairs[PAIR_HL].name); + _G.pairs[PAIR_HL].offset++; + } + offset++; + } /* Fixup HL back down */ for (size = AOP_SIZE (right)-1; size; size--) @@ -6853,24 +7246,24 @@ genGenPointerSet (operand * right, offset = 0; while (size--) - { - const char *l = aopGet (AOP (right), offset, FALSE); - if (isRegOrLit (AOP (right)) && !IS_GB) - { - emit2 ("ld !*pair,%s", _pairs[pairId].name, l); - } - else - { - _moveA (l); - emit2 ("ld !*pair,a", _pairs[pairId].name); - } - if (size) - { - emit2 ("inc %s", _pairs[pairId].name); - _G.pairs[pairId].offset++; - } - offset++; - } + { + const char *l = aopGet (AOP (right), offset, FALSE); + if (isRegOrLit (AOP (right)) && !IS_GB) + { + emit2 ("ld !*pair,%s", _pairs[pairId].name, l); + } + else + { + _moveA (l); + emit2 ("ld !*pair,a", _pairs[pairId].name); + } + if (size) + { + emit2 ("inc %s", _pairs[pairId].name); + _G.pairs[pairId].offset++; + } + offset++; + } } release: freeAsmop (right, NULL, ic); @@ -6947,40 +7340,40 @@ genAddrOf (iCode * ic) if (IS_GB) { if (sym->onStack) - { - spillCached (); - if (sym->stack <= 0) - { + { + spillPair (PAIR_HL); + if (sym->stack <= 0) + { setupPairFromSP (PAIR_HL, sym->stack + _G.stack.pushed + _G.stack.offset); - } - else - { + } + else + { setupPairFromSP (PAIR_HL, sym->stack + _G.stack.pushed + _G.stack.offset + _G.stack.param_offset); - } + } commitPair (AOP (IC_RESULT (ic)), PAIR_HL); - } + } else - { - emit2 ("ld de,!hashedstr", sym->rname); + { + emit2 ("ld de,!hashedstr", sym->rname); commitPair (AOP (IC_RESULT (ic)), PAIR_DE); - } + } } else { - spillCached (); + spillPair (PAIR_HL); if (sym->onStack) - { - /* if it has an offset then we need to compute it */ - if (sym->stack > 0) - emit2 ("ld hl,!immedword", sym->stack + _G.stack.pushed + _G.stack.offset + _G.stack.param_offset); - else - emit2 ("ld hl,!immedword", sym->stack + _G.stack.pushed + _G.stack.offset); - emit2 ("add hl,sp"); - } + { + /* if it has an offset then we need to compute it */ + if (sym->stack > 0) + emit2 ("ld hl,!immedword", sym->stack + _G.stack.pushed + _G.stack.offset + _G.stack.param_offset); + else + emit2 ("ld hl,!immedword", sym->stack + _G.stack.pushed + _G.stack.offset); + emit2 ("add hl,sp"); + } else - { - emit2 ("ld hl,!hashedstr", sym->rname); - } + { + emit2 ("ld hl,!hashedstr", sym->rname); + } commitPair (AOP (IC_RESULT (ic)), PAIR_HL); } freeAsmop (IC_RESULT (ic), NULL, ic); @@ -7028,7 +7421,7 @@ genAssign (iCode * ic) if (AOP_TYPE (right) == AOP_LIT) { - lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit); + lit = ulFromVal (AOP (right)->aopu.aop_lit); } if (isPair (AOP (result))) @@ -7036,10 +7429,10 @@ genAssign (iCode * ic) fetchPairLong (getPairId (AOP (result)), AOP (right), ic, LSB); } else if ((size > 1) && - (AOP_TYPE (result) != AOP_REG) && - (AOP_TYPE (right) == AOP_LIT) && - !IS_FLOAT (operandType (right)) && - (lit < 256L)) + (AOP_TYPE (result) != AOP_REG) && + (AOP_TYPE (right) == AOP_LIT) && + !IS_FLOAT (operandType (right)) && + (lit < 256L)) { bool fXored = FALSE; offset = 0; @@ -7047,29 +7440,29 @@ genAssign (iCode * ic) Done this way so that we can use the cached copy of 0 in A for a fast clear */ while (size--) - { - if ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0) - { - if (!fXored && size > 1) - { - emit2 ("xor a,a"); - fXored = TRUE; - } - if (fXored) - { - aopPut (AOP (result), "a", offset); - } - else - { - aopPut (AOP (result), "!zero", offset); - } - } - else - aopPut (AOP (result), - aopGet (AOP (right), offset, FALSE), - offset); - offset++; - } + { + if ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0) + { + if (!fXored && size > 1) + { + emit2 ("xor a,a"); + fXored = TRUE; + } + if (fXored) + { + aopPut (AOP (result), "a", offset); + } + else + { + aopPut (AOP (result), "!zero", offset); + } + } + else + aopPut (AOP (result), + aopGet (AOP (right), offset, FALSE), + offset); + offset++; + } } else if (size == 2 && AOP_TYPE (right) == AOP_IY) { @@ -7110,19 +7503,19 @@ genAssign (iCode * ic) else { while (size--) - { - /* PENDING: do this check better */ - if (IS_GB && requiresHL (AOP (right)) && requiresHL (AOP (result))) - { - _moveA (aopGet (AOP (right), offset, FALSE)); - aopPut (AOP (result), "a", offset); - } - else - aopPut (AOP (result), - aopGet (AOP (right), offset, FALSE), - offset); - offset++; - } + { + /* PENDING: do this check better */ + if (IS_GB && requiresHL (AOP (right)) && requiresHL (AOP (result))) + { + _moveA (aopGet (AOP (right), offset, FALSE)); + aopPut (AOP (result), "a", offset); + } + else + aopPut (AOP (result), + aopGet (AOP (right), offset, FALSE), + offset); + offset++; + } } release: @@ -7147,7 +7540,7 @@ genJumpTab (iCode * ic) emit2 ("ld e,%s", l); emit2 ("ld d,!zero"); jtab = newiTempLabel (NULL); - spillCached (); + spillPair (PAIR_HL); emit2 ("ld hl,!immed!tlabel", jtab->key + 100); emit2 ("add hl,de"); emit2 ("add hl,de"); @@ -7193,18 +7586,18 @@ genCast (iCode * ic) /* if they are in the same place */ if (sameRegs (AOP (right), AOP (result))) - goto release; + goto release; /* if they in different places then copy */ size = AOP_SIZE (result); offset = 0; while (size--) - { - aopPut (AOP (result), - aopGet (AOP (right), offset, FALSE), - offset); - offset++; - } + { + aopPut (AOP (result), + aopGet (AOP (right), offset, FALSE), + offset); + offset++; + } goto release; } @@ -7216,8 +7609,8 @@ genCast (iCode * ic) while (size--) { aopPut (AOP (result), - aopGet (AOP (right), offset, FALSE), - offset); + aopGet (AOP (right), offset, FALSE), + offset); offset++; } @@ -7227,18 +7620,17 @@ genCast (iCode * ic) if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY) { while (size--) - aopPut (AOP (result), "!zero", offset++); + aopPut (AOP (result), "!zero", offset++); } else { /* we need to extend the sign :{ */ - const char *l = aopGet (AOP (right), AOP_SIZE (right) - 1, - FALSE); + const char *l = aopGet (AOP (right), AOP_SIZE (right) - 1, FALSE); _moveA (l); emit2 ("rla "); emit2 ("sbc a,a"); while (size--) - aopPut (AOP (result), "a", offset++); + aopPut (AOP (result), "a", offset++); } release: @@ -7269,7 +7661,7 @@ genReceive (iCode * ic) for (i = 0; i < size; i++) { aopPut(AOP(IC_RESULT(ic)), _fReceive[_G.receiveOffset++], i); - } + } } freeAsmop (IC_RESULT (ic), NULL, ic); @@ -7288,39 +7680,112 @@ genDummyRead (iCode * ic) if (op && IS_SYMOP (op)) { aopOp (op, ic, FALSE, FALSE); - + /* general case */ size = AOP_SIZE (op); offset = 0; while (size--) - { - _moveA (aopGet (AOP (op), offset, FALSE)); - offset++; - } + { + _moveA (aopGet (AOP (op), offset, FALSE)); + offset++; + } freeAsmop (op, NULL, ic); } - + op = IC_LEFT (ic); if (op && IS_SYMOP (op)) { aopOp (op, ic, FALSE, FALSE); - + /* general case */ size = AOP_SIZE (op); offset = 0; while (size--) - { - _moveA (aopGet (AOP (op), offset, FALSE)); - offset++; - } + { + _moveA (aopGet (AOP (op), offset, FALSE)); + offset++; + } freeAsmop (op, NULL, ic); } } +/*-----------------------------------------------------------------*/ +/* genCritical - generate code for start of a critical sequence */ +/*-----------------------------------------------------------------*/ +static void +genCritical (iCode *ic) +{ + symbol *tlbl = newiTempLabel (NULL); + + if (IS_GB) + { + emit2 ("!di"); + } + else if (IC_RESULT (ic)) + { + aopOp (IC_RESULT (ic), ic, TRUE, FALSE); + aopPut (AOP (IC_RESULT (ic)), "!zero", 0); + //get interrupt enable flag IFF2 into P/O + emit2 ("ld a,i"); + //disable interrupt + emit2 ("!di"); + //parity odd <==> P/O=0 <==> interrupt enable flag IFF2=0 + emit2 ("jp PO,!tlabel", tlbl->key + 100); + aopPut (AOP (IC_RESULT (ic)), "!one", 0); + emit2 ("!tlabeldef", (tlbl->key + 100)); + _G.lines.current->isLabel = 1; + freeAsmop (IC_RESULT (ic), NULL, ic); + } + else + { + //get interrupt enable flag IFF2 into P/O + emit2 ("ld a,i"); + //disable interrupt + emit2 ("!di"); + //save P/O flag + _push (PAIR_AF); + } +} + +/*-----------------------------------------------------------------*/ +/* genEndCritical - generate code for end of a critical sequence */ +/*-----------------------------------------------------------------*/ +static void +genEndCritical (iCode *ic) +{ + symbol *tlbl = newiTempLabel (NULL); + + if (IS_GB) + { + emit2 ("!ei"); + } + else if (IC_RIGHT (ic)) + { + aopOp (IC_RIGHT (ic), ic, FALSE, TRUE); + _toBoolean (IC_RIGHT (ic)); + //don't enable interrupts if they were off before + emit2 ("!shortjp Z,!tlabel", tlbl->key + 100); + emit2 ("!ei"); + emitLabel (tlbl->key + 100); + freeAsmop (IC_RIGHT (ic), NULL, ic); + } + else + { + //restore P/O flag + _pop (PAIR_AF); + //parity odd <==> P/O=0 <==> interrupt enable flag IFF2 was 0 <==> + //don't enable interrupts as they were off before + emit2 ("jp PO,!tlabel", tlbl->key + 100); + emit2 ("!ei"); + emit2 ("!tlabeldef", (tlbl->key + 100)); + _G.lines.current->isLabel = 1; + } +} + enum { /** Maximum number of bytes to emit per line. */ @@ -7336,7 +7801,7 @@ typedef struct /** Flushes a byte chunker by writing out all in the buffer and - reseting. + reseting. */ static void _dbFlush(DBEMITCTX *self) @@ -7397,9 +7862,9 @@ _rleCommit(RLECTX *self) { DBEMITCTX db; memset(&db, 0, sizeof(db)); - + emit2(".db %u", self->pos); - + for (i = 0; i < self->pos; i++) { _dbEmit(&db, self->buffer[i]); @@ -7431,7 +7896,7 @@ _rleCommit(RLECTX *self) chunks. */ static void -_rleAppend(RLECTX *self, int c) +_rleAppend(RLECTX *self, unsigned c) { int i; @@ -7509,9 +7974,9 @@ genArrayInit (iCode * ic) fetchPair (PAIR_HL, AOP (IC_LEFT (ic))); emit2 ("call __initrleblock"); - + type = operandType(IC_LEFT(ic)); - + if (type && type->next) { if (IS_SPEC(type->next) || IS_PTR(type->next)) @@ -7524,7 +7989,7 @@ genArrayInit (iCode * ic) } else { - printTypeChainRaw (type, NULL); + printTypeChainRaw (type, NULL); wassertl (0, "Can't determine element size in genArrayInit."); } } @@ -7555,7 +8020,7 @@ genArrayInit (iCode * ic) _rleAppend(&rle, val); } } - + iLoop = iLoop->next; } @@ -7588,67 +8053,12 @@ _swap (PAIR_ID one, PAIR_ID two) } } -/* The problem is that we may have all three pairs used and they may - be needed in a different order. - - Note: Have ex de,hl - - Combinations: - hl = hl => unity, fine - bc = bc - de = de - - hl = hl hl = hl, swap de <=> bc - bc = de - de = bc - - hl = bc Worst case - bc = de - de = hl - - hl = bc de = de, swap bc <=> hl - bc = hl - de = de - - hl = de Worst case - bc = hl - de = bc - - hl = de bc = bc, swap hl <=> de - bc = bc - de = hl - - Break it down into: - * Any pair = pair are done last - * Any pair = iTemp are done last - * Any swaps can be done any time - - A worst case: - push p1 - p1 = p2 - p2 = p3 - pop p3 - - So how do we detect the cases? - How about a 3x3 matrix? - source - dest x x x x - x x x x - x x x x (Fourth for iTemp/other) - - First determin which mode to use by counting the number of unity and - iTemp assigns. - Three - any order - Two - Assign the pair first, then the rest - One - Swap the two, then the rest - Zero - Worst case. -*/ static void -setupForBuiltin3 (iCode *ic, int nparams, operand **pparams) +setupForMemcpy (iCode *ic, int nparams, operand **pparams) { PAIR_ID ids[NUM_PAIRS][NUM_PAIRS]; PAIR_ID dest[3] = { - PAIR_BC, PAIR_HL, PAIR_DE + PAIR_DE, PAIR_HL, PAIR_BC }; int i, j, nunity = 0; memset (ids, PAIR_INVALID, sizeof (ids)); @@ -7656,10 +8066,6 @@ setupForBuiltin3 (iCode *ic, int nparams, operand **pparams) /* Sanity checks */ wassert (nparams == 3); - /* First save everything that needs to be saved. */ - _saveRegsForCall (ic, 0); - - /* Loading HL first means that DE is always fine. */ for (i = 0; i < nparams; i++) { aopOp (pparams[i], ic, FALSE, FALSE); @@ -7667,7 +8073,7 @@ setupForBuiltin3 (iCode *ic, int nparams, operand **pparams) } /* Count the number of unity or iTemp assigns. */ - for (i = 0; i < 3; i++) + for (i = 0; i < 3; i++) { if (ids[dest[i]][dest[i]] == TRUE || ids[dest[i]][PAIR_INVALID] == TRUE) { @@ -7681,7 +8087,7 @@ setupForBuiltin3 (iCode *ic, int nparams, operand **pparams) } else if (nunity == 2) { - /* One is assigned. Pull it out and assign. */ + /* Two are OK. Assign the other one. */ for (i = 0; i < 3; i++) { for (j = 0; j < NUM_PAIRS; j++) @@ -7704,7 +8110,7 @@ setupForBuiltin3 (iCode *ic, int nparams, operand **pparams) } else if (nunity == 1) { - /* Find the pairs to swap. */ + /* One is OK. Find the other two. */ for (i = 0; i < 3; i++) { for (j = 0; j < NUM_PAIRS; j++) @@ -7713,12 +8119,22 @@ setupForBuiltin3 (iCode *ic, int nparams, operand **pparams) { if (j == PAIR_INVALID || j == dest[i]) { - /* Keep looking. */ + /* This one is OK. */ } else { - _swap (j, dest[i]); - goto done; + /* Found one. */ + if(ids[j][dest[i]] == TRUE) + { + /* Just swap. */ + _swap (j, dest[i]); + goto done; + } + else + { + fetchPair (dest[i], AOP (pparams[i])); + continue; + } } } } @@ -7752,59 +8168,33 @@ setupForBuiltin3 (iCode *ic, int nparams, operand **pparams) } } -static void -genBuiltInStrcpy (iCode *ic, int nParams, operand **pparams) -{ - operand *from, *to; - symbol *label; - bool deInUse; - - wassertl (nParams == 2, "Built-in strcpy must have two parameters"); - to = pparams[0]; - from = pparams[1]; - - deInUse = bitVectBitValue (ic->rMask, D_IDX) || bitVectBitValue(ic->rMask, E_IDX); - - setupForBuiltin3 (ic, nParams, pparams); - - label = newiTempLabel(NULL); - - emitLabel (label->key); - emit2 ("ld a,(hl)"); - emit2 ("ldi"); - emit2 ("or a"); - emit2 ("!shortjp nz,!tlabel ; 1", label->key); - - freeAsmop (from, NULL, ic->next); - freeAsmop (to, NULL, ic); -} - static void genBuiltInMemcpy (iCode *ic, int nParams, operand **pparams) { operand *from, *to, *count; - bool deInUse; - wassertl (nParams == 3, "Built-in memcpy must have two parameters"); + wassertl (nParams == 3, "Built-in memcpy() must have three parameters"); to = pparams[2]; from = pparams[1]; count = pparams[0]; - deInUse = bitVectBitValue (ic->rMask, D_IDX) || bitVectBitValue(ic->rMask, E_IDX); + _saveRegsForCall (ic, 0); - setupForBuiltin3 (ic, nParams, pparams); + setupForMemcpy (ic, nParams, pparams); emit2 ("ldir"); freeAsmop (count, NULL, ic->next->next); freeAsmop (from, NULL, ic); + spillPair (PAIR_HL); + _restoreRegsAfterCall(); /* if we need assign a result value */ if ((IS_ITEMP (IC_RESULT (ic)) && (OP_SYMBOL (IC_RESULT (ic))->nRegs || - OP_SYMBOL (IC_RESULT (ic))->spildir)) || + OP_SYMBOL (IC_RESULT (ic))->spildir)) || IS_TRUE_SYMOP (IC_RESULT (ic))) { aopOp (IC_RESULT (ic), ic, FALSE, FALSE); @@ -7817,7 +8207,7 @@ genBuiltInMemcpy (iCode *ic, int nParams, operand **pparams) /*-----------------------------------------------------------------*/ /* genBuiltIn - calls the appropriate function to generating code */ -/* for a built in function */ +/* for a built in function */ /*-----------------------------------------------------------------*/ static void genBuiltIn (iCode *ic) { @@ -7832,17 +8222,13 @@ static void genBuiltIn (iCode *ic) /* which function is it */ bif = OP_SYMBOL(IC_LEFT(bi_iCode)); - if (strcmp(bif->name,"__builtin_strcpy")==0) - { - genBuiltInStrcpy(bi_iCode, nbi_parms, bi_parms); - } - else if (strcmp(bif->name,"__builtin_memcpy")==0) + if (strcmp(bif->name,"__builtin_memcpy")==0) { - genBuiltInMemcpy(bi_iCode, nbi_parms, bi_parms); - } - else + genBuiltInMemcpy(bi_iCode, nbi_parms, bi_parms); + } + else { - wassertl (0, "Unknown builtin function encountered"); + wassertl (0, "Unknown builtin function encountered"); } } @@ -7868,7 +8254,7 @@ genZ80Code (iCode * lic) } _G.lines.head = _G.lines.current = NULL; - + /* if debug information required */ if (options.debug && currFunc) { @@ -7880,257 +8266,261 @@ genZ80Code (iCode * lic) _G.current_iCode = ic; if (ic->lineno && cln != ic->lineno) - { - if (options.debug) - { - debugFile->writeCLine (ic); - } - if (!options.noCcodeInAsm) { - emit2 (";%s:%d: %s", ic->filename, ic->lineno, - printCLine(ic->filename, ic->lineno)); - } - cln = ic->lineno; - } - if (options.iCodeInAsm) { - emit2 (";ic:%d: %s", ic->key, printILine(ic)); - } + { + if (options.debug) + { + debugFile->writeCLine (ic); + } + if (!options.noCcodeInAsm) + { + emit2 (";%s:%d: %s", ic->filename, ic->lineno, + printCLine(ic->filename, ic->lineno)); + } + cln = ic->lineno; + } + if (options.iCodeInAsm) + { + const char *iLine = printILine(ic); + emit2 (";ic:%d: %s", ic->key, iLine); + dbuf_free(iLine); + } /* if the result is marked as spilt and rematerializable or code for this has already been generated then do nothing */ if (resultRemat (ic) || ic->generated) - continue; + continue; /* depending on the operation */ switch (ic->op) - { - case '!': - emitDebug ("; genNot"); - genNot (ic); - break; - - case '~': - emitDebug ("; genCpl"); - genCpl (ic); - break; - - case UNARYMINUS: - emitDebug ("; genUminus"); - genUminus (ic); - break; - - case IPUSH: - emitDebug ("; genIpush"); - genIpush (ic); - break; - - case IPOP: - /* IPOP happens only when trying to restore a - spilt live range, if there is an ifx statement - following this pop then the if statement might - be using some of the registers being popped which - would destory the contents of the register so - we need to check for this condition and handle it */ - if (ic->next && - ic->next->op == IFX && - regsInCommon (IC_LEFT (ic), IC_COND (ic->next))) - { + { + case '!': + emitDebug ("; genNot"); + genNot (ic); + break; + + case '~': + emitDebug ("; genCpl"); + genCpl (ic); + break; + + case UNARYMINUS: + emitDebug ("; genUminus"); + genUminus (ic); + break; + + case IPUSH: + emitDebug ("; genIpush"); + genIpush (ic); + break; + + case IPOP: + /* IPOP happens only when trying to restore a + spilt live range, if there is an ifx statement + following this pop then the if statement might + be using some of the registers being popped which + would destroy the contents of the register so + we need to check for this condition and handle it */ + if (ic->next && + ic->next->op == IFX && + regsInCommon (IC_LEFT (ic), IC_COND (ic->next))) + { emitDebug ("; genIfx"); - genIfx (ic->next, ic); - } - else - { - emitDebug ("; genIpop"); - genIpop (ic); - } - break; - - case CALL: - emitDebug ("; genCall"); - genCall (ic); - break; - - case PCALL: - emitDebug ("; genPcall"); - genPcall (ic); - break; - - case FUNCTION: - emitDebug ("; genFunction"); - genFunction (ic); - break; - - case ENDFUNCTION: - emitDebug ("; genEndFunction"); - genEndFunction (ic); - break; - - case RETURN: - emitDebug ("; genRet"); - genRet (ic); - break; - - case LABEL: - emitDebug ("; genLabel"); - genLabel (ic); - break; - - case GOTO: - emitDebug ("; genGoto"); - genGoto (ic); - break; - - case '+': - emitDebug ("; genPlus"); - genPlus (ic); - break; - - case '-': - emitDebug ("; genMinus"); - genMinus (ic); - break; - - case '*': - emitDebug ("; genMult"); - genMult (ic); - break; - - case '/': - emitDebug ("; genDiv"); - genDiv (ic); - break; - - case '%': - emitDebug ("; genMod"); - genMod (ic); - break; - - case '>': - emitDebug ("; genCmpGt"); - genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic)); - break; - - case '<': - emitDebug ("; genCmpLt"); - genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic)); - break; - - case LE_OP: - case GE_OP: - case NE_OP: - - /* note these two are xlated by algebraic equivalence - during parsing SDCC.y */ - werror (E_INTERNAL_ERROR, __FILE__, __LINE__, - "got '>=' or '<=' shouldn't have come here"); - break; - - case EQ_OP: - emitDebug ("; genCmpEq"); - genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic)); - break; - - case AND_OP: - emitDebug ("; genAndOp"); - genAndOp (ic); - break; - - case OR_OP: - emitDebug ("; genOrOp"); - genOrOp (ic); - break; - - case '^': - emitDebug ("; genXor"); - genXor (ic, ifxForOp (IC_RESULT (ic), ic)); - break; - - case '|': - emitDebug ("; genOr"); - genOr (ic, ifxForOp (IC_RESULT (ic), ic)); - break; - - case BITWISEAND: - emitDebug ("; genAnd"); - genAnd (ic, ifxForOp (IC_RESULT (ic), ic)); - break; - - case INLINEASM: - emitDebug ("; genInline"); - genInline (ic); - break; - - case RRC: - emitDebug ("; genRRC"); - genRRC (ic); - break; - - case RLC: - emitDebug ("; genRLC"); - genRLC (ic); - break; - - case GETHBIT: - emitDebug ("; genGetHBIT"); - genGetHbit (ic); + genIfx (ic->next, ic); + } + else + { + emitDebug ("; genIpop"); + genIpop (ic); + } + break; + + case CALL: + emitDebug ("; genCall"); + genCall (ic); + break; + + case PCALL: + emitDebug ("; genPcall"); + genPcall (ic); + break; + + case FUNCTION: + emitDebug ("; genFunction"); + genFunction (ic); + break; + + case ENDFUNCTION: + emitDebug ("; genEndFunction"); + genEndFunction (ic); + break; + + case RETURN: + emitDebug ("; genRet"); + genRet (ic); + break; + + case LABEL: + emitDebug ("; genLabel"); + genLabel (ic); + break; + + case GOTO: + emitDebug ("; genGoto"); + genGoto (ic); + break; + + case '+': + emitDebug ("; genPlus"); + genPlus (ic); + break; + + case '-': + emitDebug ("; genMinus"); + genMinus (ic); break; - case LEFT_OP: - emitDebug ("; genLeftShift"); - genLeftShift (ic); - break; - - case RIGHT_OP: - emitDebug ("; genRightShift"); - genRightShift (ic); - break; - - case GET_VALUE_AT_ADDRESS: - emitDebug ("; genPointerGet"); - genPointerGet (ic); - break; - - case '=': - - if (POINTER_SET (ic)) - { - emitDebug ("; genAssign (pointer)"); - genPointerSet (ic); - } - else - { - emitDebug ("; genAssign"); - genAssign (ic); - } - break; - - case IFX: + case '*': + emitDebug ("; genMult"); + genMult (ic); + break; + + case '/': + emitDebug ("; genDiv"); + genDiv (ic); + break; + + case '%': + emitDebug ("; genMod"); + genMod (ic); + break; + + case '>': + emitDebug ("; genCmpGt"); + genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic)); + break; + + case '<': + emitDebug ("; genCmpLt"); + genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic)); + break; + + case LE_OP: + case GE_OP: + case NE_OP: + + /* note these two are xlated by algebraic equivalence + during parsing SDCC.y */ + werror (E_INTERNAL_ERROR, __FILE__, __LINE__, + "got '>=' or '<=' shouldn't have come here"); + break; + + case EQ_OP: + emitDebug ("; genCmpEq"); + genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic)); + break; + + case AND_OP: + emitDebug ("; genAndOp"); + genAndOp (ic); + break; + + case OR_OP: + emitDebug ("; genOrOp"); + genOrOp (ic); + break; + + case '^': + emitDebug ("; genXor"); + genXor (ic, ifxForOp (IC_RESULT (ic), ic)); + break; + + case '|': + emitDebug ("; genOr"); + genOr (ic, ifxForOp (IC_RESULT (ic), ic)); + break; + + case BITWISEAND: + emitDebug ("; genAnd"); + genAnd (ic, ifxForOp (IC_RESULT (ic), ic)); + break; + + case INLINEASM: + emitDebug ("; genInline"); + genInline (ic); + break; + + case RRC: + emitDebug ("; genRRC"); + genRRC (ic); + break; + + case RLC: + emitDebug ("; genRLC"); + genRLC (ic); + break; + + case GETHBIT: + emitDebug ("; genGetHBIT"); + genGetHbit (ic); + break; + + case LEFT_OP: + emitDebug ("; genLeftShift"); + genLeftShift (ic); + break; + + case RIGHT_OP: + emitDebug ("; genRightShift"); + genRightShift (ic); + break; + + case GET_VALUE_AT_ADDRESS: + emitDebug ("; genPointerGet"); + genPointerGet (ic); + break; + + case '=': + + if (POINTER_SET (ic)) + { + emitDebug ("; genAssign (pointer)"); + genPointerSet (ic); + } + else + { + emitDebug ("; genAssign"); + genAssign (ic); + } + break; + + case IFX: emitDebug ("; genIfx"); - genIfx (ic, NULL); - break; - - case ADDRESS_OF: - emitDebug ("; genAddrOf"); - genAddrOf (ic); - break; - - case JUMPTABLE: - emitDebug ("; genJumpTab"); - genJumpTab (ic); - break; - - case CAST: - emitDebug ("; genCast"); - genCast (ic); - break; - - case RECEIVE: - emitDebug ("; genReceive"); - genReceive (ic); - break; - - case SEND: - if (ic->builtinSEND) + genIfx (ic, NULL); + break; + + case ADDRESS_OF: + emitDebug ("; genAddrOf"); + genAddrOf (ic); + break; + + case JUMPTABLE: + emitDebug ("; genJumpTab"); + genJumpTab (ic); + break; + + case CAST: + emitDebug ("; genCast"); + genCast (ic); + break; + + case RECEIVE: + emitDebug ("; genReceive"); + genReceive (ic); + break; + + case SEND: + if (ic->builtinSEND) { emitDebug ("; genBuiltIn"); genBuiltIn(ic); @@ -8140,21 +8530,31 @@ genZ80Code (iCode * lic) emitDebug ("; addSet"); addSet (&_G.sendSet, ic); } - break; + break; - case ARRAYINIT: - emitDebug ("; genArrayInit"); + case ARRAYINIT: + emitDebug ("; genArrayInit"); genArrayInit(ic); break; - case DUMMY_READ_VOLATILE: - emitDebug ("; genDummyRead"); - genDummyRead (ic); - break; + case DUMMY_READ_VOLATILE: + emitDebug ("; genDummyRead"); + genDummyRead (ic); + break; + + case CRITICAL: + emitDebug ("; genCritical"); + genCritical (ic); + break; + + case ENDCRITICAL: + emitDebug ("; genEndCritical"); + genEndCritical (ic); + break; - default: - ic = ic; - } + default: + ic = ic; + } } @@ -8166,16 +8566,16 @@ genZ80Code (iCode * lic) /* This is unfortunate */ /* now do the actual printing */ { - FILE *fp = codeOutFile; - if (isInHome () && codeOutFile == code->oFile) - codeOutFile = home->oFile; - printLine (_G.lines.head, codeOutFile); + struct dbuf_s *buf = codeOutBuf; + if (isInHome () && codeOutBuf == &code->oBuf) + codeOutBuf = &home->oBuf; + printLine (_G.lines.head, codeOutBuf); if (_G.flushStatics) { - flushStatics (); - _G.flushStatics = 0; + flushStatics (); + _G.flushStatics = 0; } - codeOutFile = fp; + codeOutBuf = buf; } freeTrace(&_G.lines.trace); @@ -8192,9 +8592,9 @@ _isPairUsed (iCode * ic, PAIR_ID pairId) { case PAIR_DE: if (bitVectBitValue (ic->rMask, D_IDX)) - ret++; + ret++; if (bitVectBitValue (ic->rMask, E_IDX)) - ret++; + ret++; break; default: wassert (0); @@ -8211,7 +8611,7 @@ fetchLitSpecial (asmop * aop, bool negate, bool xor) wassert (aop->type == AOP_LIT); wassert (!IS_FLOAT (val->type)); - v = (unsigned long) floatFromVal (val); + v = ulFromVal (val); if (xor) v ^= 0x8000;