X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Fz80%2Fgen.c;h=b5f0afc975a66fb4c0b35702e14f32b4d27bac53;hb=25991ff3ca6bdbc0b10204adc00022c0777b9ab9;hp=ee1ddaad71e88253258135f64ec117fb261f6337;hpb=b2751d94f5aa42a4c50ba4d227d533be0fb0b674;p=fw%2Fsdcc diff --git a/src/z80/gen.c b/src/z80/gen.c index ee1ddaad..b5f0afc9 100644 --- a/src/z80/gen.c +++ b/src/z80/gen.c @@ -60,7 +60,9 @@ 9. With asm optimised strings 17030 192 2223 10 and below are with asm strings off. - + + 10 Mucho optimisations 13562 201 1FCC + Apparent advantage of turning on regparams: 1. Cost of push Decent case is push of a constant @@ -85,8 +87,10 @@ #include #include -#ifdef HAVE_SYS_ISA_DEFS_H -#include +#if defined(__BORLANDC__) || defined(_MSC_VER) +#define STRCASECMP stricmp +#else +#define STRCASECMP strcasecmp #endif #include "z80.h" @@ -203,6 +207,13 @@ static struct int pushedBC; int pushedDE; } stack; + + struct + { + int pushedBC; + int pushedDE; + } calleeSaves; + int frameId; int receiveOffset; bool flushStatics; @@ -252,6 +263,30 @@ static const char *aopNames[] = { "AOP_PAIRPT" }; +static bool +isLastUse (iCode *ic, operand *op) +{ + bitVect *uses = bitVectCopy (OP_USES (op)); + + while (!bitVectIsZero (uses)) + { + if (bitVectFirstBit (uses) == ic->key) + { + if (bitVectnBitsOn (uses) == 1) + { + return TRUE; + } + else + { + return FALSE; + } + } + bitVectUnSetBit (uses, bitVectFirstBit (uses)); + } + + return FALSE; +} + static PAIR_ID _getTempPairId(void) { @@ -271,14 +306,50 @@ _getTempPairName(void) return _pairs[_getTempPairId()].name; } +static bool +isPairInUse (PAIR_ID id, iCode *ic) +{ + if (id == PAIR_DE) + { + return bitVectBitValue (ic->rMask, D_IDX) || bitVectBitValue(ic->rMask, E_IDX); + } + else if (id == PAIR_BC) + { + return bitVectBitValue (ic->rMask, B_IDX) || bitVectBitValue(ic->rMask, C_IDX); + } + else + { + wassertl (0, "Only implemented for DE and BC"); + return TRUE; + } +} + +static bool +isPairInUseNotInRet(PAIR_ID id, iCode *ic) +{ + bitVect *rInUse; + + rInUse = bitVectCplAnd (bitVectCopy (ic->rMask), ic->rUsed); + + if (id == PAIR_DE) + { + return bitVectBitValue (rInUse, D_IDX) || bitVectBitValue(rInUse, E_IDX); + } + else + { + wassertl (0, "Only implemented for DE"); + return TRUE; + } +} + static PAIR_ID getFreePairId (iCode *ic) { - if (!(bitVectBitValue (ic->rMask, B_IDX) || bitVectBitValue(ic->rMask, C_IDX))) + if (!isPairInUse (PAIR_BC, ic)) { return PAIR_BC; } - else if (IS_Z80 && !(bitVectBitValue (ic->rMask, D_IDX) || bitVectBitValue(ic->rMask, E_IDX))) + else if (IS_Z80 && !isPairInUse (PAIR_DE, ic)) { return PAIR_DE; } @@ -327,7 +398,7 @@ _vemit2 (const char *szFormat, va_list ap) { char buffer[256]; - tvsprintf (buffer, szFormat, ap); + tvsprintf (buffer, sizeof(buffer), szFormat, ap); _tidyUp (buffer); _G.lines.current = (_G.lines.current ? @@ -400,7 +471,7 @@ _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); } @@ -411,7 +482,7 @@ _emitMove(const char *to, const char *from) } } -static void +void aopDump(const char *plabel, asmop *aop) { emitDebug("; Dump of %s: type %s size %u", plabel, aopNames[aop->type], aop->size); @@ -422,6 +493,7 @@ aopDump(const char *plabel, asmop *aop) break; default: /* No information. */ + break; } } @@ -920,12 +992,14 @@ aopOp (operand * op, iCode * ic, bool result, bool requires_a) } /* else spill location */ - op->aop = aop = + if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) { + /* force a new aop if sizes differ */ + sym->usl.spillLoc->aop = NULL; + } + sym->aop = op->aop = aop = aopForSym (ic, sym->usl.spillLoc, result, requires_a); wassertl (aop->size >= getSize (sym->type), "Operand doesn't fit in the spill location"); aop->size = getSize (sym->type); - /* PENDING: HACK. Can have different sizes in the same AOP. */ - sym->usl.spillLoc->aop = NULL; return; } @@ -962,6 +1036,11 @@ freeAsmop (operand * op, asmop * aaop, iCode * ic) _pop (aop->aopu.aop_pairId); } + if (getPairId (aop) == PAIR_HL) + { + spillPair (PAIR_HL); + } + dealloc: /* all other cases just dealloc */ if (op) @@ -996,8 +1075,6 @@ isLitWord (asmop * aop) char * aopGetLitWordLong (asmop * aop, int offset, bool with_hash) { - char *s = buffer; - /* depending on type */ switch (aop->type) { @@ -1007,17 +1084,20 @@ aopGetLitWordLong (asmop * aop, int offset, bool with_hash) /* PENDING: for re-target */ if (with_hash) { - tsprintf (s, "!hashedstr + %d", aop->aopu.aop_immd, offset); + tsprintf (buffer, sizeof(buffer), + "!hashedstr + %d", aop->aopu.aop_immd, offset); } else if (offset == 0) { - tsprintf (s, "%s", aop->aopu.aop_immd); + tsprintf (buffer, sizeof(buffer), + "%s", aop->aopu.aop_immd); } else { - tsprintf (s, "%s + %d", aop->aopu.aop_immd, offset); + tsprintf (buffer, sizeof(buffer), + "%s + %d", aop->aopu.aop_immd, offset); } - return traceAlloc(&_G.trace.aops, Safe_strdup(s)); + return traceAlloc(&_G.trace.aops, Safe_strdup(buffer)); case AOP_LIT: { @@ -1042,9 +1122,9 @@ aopGetLitWordLong (asmop * aop, int offset, bool with_hash) } if (with_hash) - tsprintf (buffer, "!immedword", v); + tsprintf (buffer, sizeof(buffer), "!immedword", v); else - tsprintf (buffer, "!constword", v); + tsprintf (buffer, sizeof(buffer), "!constword", v); return traceAlloc(&_G.trace.aops, Safe_strdup(buffer)); } @@ -1060,15 +1140,15 @@ aopGetLitWordLong (asmop * aop, int offset, bool with_hash) /* it is type float */ fl.f = (float) floatFromVal (val); -#ifdef _BIG_ENDIAN +#ifdef WORDS_BIGENDIAN i = fl.c[3-offset] | (fl.c[3-offset-1]<<8); #else i = fl.c[offset] | (fl.c[offset+1]<<8); #endif if (with_hash) - tsprintf (buffer, "!immedword", i); + tsprintf (buffer, sizeof(buffer), "!immedword", i); else - tsprintf (buffer, "!constword", i); + tsprintf (buffer, sizeof(buffer), "!constword", i); return traceAlloc(&_G.trace.aops, Safe_strdup(buffer)); } @@ -1173,8 +1253,36 @@ fetchLitPair (PAIR_ID pairId, asmop * left, int offset) emit2 ("ld %s,!hashedstr", pair, l); } +static PAIR_ID +makeFreePairId (iCode *ic, bool *pisUsed) +{ + *pisUsed = FALSE; + + if (ic != NULL) + { + if (!bitVectBitValue (ic->rMask, B_IDX) && !bitVectBitValue(ic->rMask, C_IDX)) + { + return PAIR_BC; + } + else if (IS_Z80 && !bitVectBitValue (ic->rMask, D_IDX) && !bitVectBitValue(ic->rMask, E_IDX)) + { + return PAIR_DE; + } + else + { + *pisUsed = TRUE; + return PAIR_HL; + } + } + else + { + *pisUsed = TRUE; + return PAIR_HL; + } +} + static void -fetchPairLong (PAIR_ID pairId, asmop * aop, int offset) +fetchPairLong (PAIR_ID pairId, asmop * aop, iCode *ic, int offset) { /* if this is remateriazable */ if (isLitWord (aop)) { @@ -1226,19 +1334,24 @@ fetchPairLong (PAIR_ID pairId, asmop * aop, int offset) } else { - _push (PAIR_HL); + bool isUsed; + PAIR_ID id = makeFreePairId (ic, &isUsed); + if (isUsed) + _push (id); /* Can't load into parts, so load into HL then exchange. */ - emit2 ("ld %s,%s", _pairs[PAIR_HL].l, aopGet (aop, offset, FALSE)); - emit2 ("ld %s,%s", _pairs[PAIR_HL].h, aopGet (aop, offset + 1, FALSE)); - emit2 ("push hl"); + emit2 ("ld %s,%s", _pairs[id].l, aopGet (aop, offset, FALSE)); + emit2 ("ld %s,%s", _pairs[id].h, aopGet (aop, offset + 1, FALSE)); + emit2 ("push %s", _pairs[id].name); emit2 ("pop iy"); - _pop (PAIR_HL); + if (isUsed) + _pop (id); } } - else { + else + { emit2 ("ld %s,%s", _pairs[pairId].l, aopGet (aop, offset, FALSE)); emit2 ("ld %s,%s", _pairs[pairId].h, aopGet (aop, offset + 1, FALSE)); - } + } /* PENDING: check? */ if (pairId == PAIR_HL) spillPair (PAIR_HL); @@ -1248,7 +1361,7 @@ fetchPairLong (PAIR_ID pairId, asmop * aop, int offset) static void fetchPair (PAIR_ID pairId, asmop * aop) { - fetchPairLong (pairId, aop, 0); + fetchPairLong (pairId, aop, NULL, 0); } static void @@ -1360,15 +1473,15 @@ emitLabel (int key) static const char * aopGet (asmop * aop, int offset, bool bit16) { - char *s = buffer; + // char *s = buffer; /* offset is greater than size then zero */ /* PENDING: this seems a bit screwed in some pointer cases. */ if (offset > (aop->size - 1) && aop->type != AOP_LIT) { - tsprintf (s, "!zero"); - return traceAlloc(&_G.trace.aops, Safe_strdup(s)); + tsprintf (buffer, sizeof(buffer), "!zero"); + return traceAlloc(&_G.trace.aops, Safe_strdup(buffer)); } /* depending on type */ @@ -1377,38 +1490,38 @@ aopGet (asmop * aop, int offset, bool bit16) case AOP_IMMD: /* PENDING: re-target */ if (bit16) - tsprintf (s, "!immedwords", aop->aopu.aop_immd); + tsprintf (buffer, sizeof(buffer), "!immedwords", aop->aopu.aop_immd); else switch (offset) { case 2: - tsprintf (s, "!bankimmeds", aop->aopu.aop_immd); + tsprintf (buffer, sizeof(buffer), "!bankimmeds", aop->aopu.aop_immd); break; case 1: - tsprintf (s, "!msbimmeds", aop->aopu.aop_immd); + tsprintf (buffer, sizeof(buffer), "!msbimmeds", aop->aopu.aop_immd); break; case 0: - tsprintf (s, "!lsbimmeds", aop->aopu.aop_immd); + tsprintf (buffer, sizeof(buffer), "!lsbimmeds", aop->aopu.aop_immd); break; default: wassertl (0, "Fetching from beyond the limits of an immediate value."); } - return traceAlloc(&_G.trace.aops, Safe_strdup(s)); + return traceAlloc(&_G.trace.aops, Safe_strdup(buffer)); case AOP_DIR: wassert (IS_GB); emit2 ("ld a,(%s+%d)", aop->aopu.aop_dir, offset); - sprintf (s, "a"); + SNPRINTF (buffer, sizeof(buffer), "a"); - return traceAlloc(&_G.trace.aops, Safe_strdup(s)); + return traceAlloc(&_G.trace.aops, Safe_strdup(buffer)); case AOP_SFR: wassert (IS_GB); emit2 ("ldh a,(%s+%d)", aop->aopu.aop_dir, offset); - sprintf (s, "a"); + SNPRINTF (buffer, sizeof(buffer), "a"); - return traceAlloc(&_G.trace.aops, Safe_strdup(s)); + return traceAlloc(&_G.trace.aops, Safe_strdup(buffer)); case AOP_REG: return aop->aopu.aop_reg[offset]->name; @@ -1416,38 +1529,39 @@ aopGet (asmop * aop, int offset, bool bit16) case AOP_HL: wassert (IS_GB); setupPair (PAIR_HL, aop, offset); - tsprintf (s, "!*hl"); + tsprintf (buffer, sizeof(buffer), "!*hl"); - return traceAlloc(&_G.trace.aops, Safe_strdup (s)); + return traceAlloc(&_G.trace.aops, Safe_strdup (buffer)); case AOP_IY: wassert (IS_Z80); setupPair (PAIR_IY, aop, offset); - tsprintf (s, "!*iyx", offset); + tsprintf (buffer, sizeof(buffer), "!*iyx", offset); - return traceAlloc(&_G.trace.aops, Safe_strdup(s)); + return traceAlloc(&_G.trace.aops, Safe_strdup(buffer)); case AOP_EXSTK: wassert (IS_Z80); setupPair (PAIR_IY, aop, offset); - tsprintf (s, "!*iyx", offset, offset); + tsprintf (buffer, sizeof(buffer), "!*iyx", offset, offset); - return traceAlloc(&_G.trace.aops, Safe_strdup(s)); + return traceAlloc(&_G.trace.aops, Safe_strdup(buffer)); case AOP_STK: if (IS_GB) { setupPair (PAIR_HL, aop, offset); - tsprintf (s, "!*hl"); + tsprintf (buffer, sizeof(buffer), "!*hl"); } else { if (aop->aopu.aop_stk >= 0) offset += _G.stack.param_offset; - tsprintf (s, "!*ixx", aop->aopu.aop_stk + offset); + tsprintf (buffer, sizeof(buffer), + "!*ixx", aop->aopu.aop_stk + offset); } - return traceAlloc(&_G.trace.aops, Safe_strdup(s)); + return traceAlloc(&_G.trace.aops, Safe_strdup(buffer)); case AOP_CRY: wassertl (0, "Tried to fetch from a bit variable"); @@ -1459,8 +1573,8 @@ aopGet (asmop * aop, int offset, bool bit16) } else { - tsprintf(s, "!zero"); - return traceAlloc(&_G.trace.aops, Safe_strdup(s)); + tsprintf(buffer, sizeof(buffer), "!zero"); + return traceAlloc(&_G.trace.aops, Safe_strdup(buffer)); } case AOP_HLREG: @@ -1475,9 +1589,10 @@ aopGet (asmop * aop, int offset, bool bit16) unsigned long v = aop->aopu.aop_simplelit; v >>= (offset * 8); - tsprintf (s, "!immedbyte", (unsigned int) v & 0xff); + tsprintf (buffer, sizeof(buffer), + "!immedbyte", (unsigned int) v & 0xff); - return traceAlloc(&_G.trace.aops, Safe_strdup(s)); + return traceAlloc(&_G.trace.aops, Safe_strdup(buffer)); } case AOP_STR: aop->coff = offset; @@ -1485,9 +1600,10 @@ aopGet (asmop * aop, int offset, bool bit16) case AOP_PAIRPTR: setupPair (aop->aopu.aop_pairId, aop, offset); - sprintf (s, "(%s)", _pairs[aop->aopu.aop_pairId].name); + SNPRINTF (buffer, sizeof(buffer), + "(%s)", _pairs[aop->aopu.aop_pairId].name); - return traceAlloc(&_G.trace.aops, Safe_strdup(s)); + return traceAlloc(&_G.trace.aops, Safe_strdup(buffer)); default: break; @@ -1543,7 +1659,7 @@ aopPut (asmop * aop, const char *s, int offset) } // PENDING - tsprintf(buffer2, s); + tsprintf(buffer2, sizeof(buffer2), s); s = buffer2; /* will assign value to value */ @@ -1654,7 +1770,7 @@ aopPut (asmop * aop, const char *s, int offset) /* if bit variable */ if (!aop->aopu.aop_dir) { - emit2 ("ld a,#0"); + emit2 ("ld a,!zero"); emit2 ("rla"); } else @@ -1801,6 +1917,7 @@ 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); } else if ( getPairId ( AOP (result)) == PAIR_IY) { @@ -2042,7 +2159,7 @@ _gbz80_emitAddSubLongLong (iCode *ic, asmop *left, asmop *right, bool isAdd) aopPut ( AOP (IC_RESULT (ic)), "a", MSB16); aopPut ( AOP (IC_RESULT (ic)), "e", LSB); - fetchPairLong (PAIR_DE, left, MSB24); + fetchPairLong (PAIR_DE, left, NULL, MSB24); aopGet (right, MSB24, FALSE); _pop (PAIR_AF); @@ -2331,11 +2448,11 @@ genIpush (iCode * ic) } if (size == 4) { - fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), 2); + fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), ic, 2); emit2 ("push hl"); spillPair (PAIR_HL); _G.stack.pushed += 2; - fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), 0); + fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), ic, 0); emit2 ("push hl"); spillPair (PAIR_HL); _G.stack.pushed += 2; @@ -2622,7 +2739,7 @@ emitCall (iCode * ic, bool ispcall) spillCached (); if (i > 8) { - emit2 ("ld iy,#%d", i); + emit2 ("ld iy,!immedword", i); emit2 ("add iy,sp"); emit2 ("ld sp,iy"); } @@ -2750,10 +2867,8 @@ genFunction (iCode * ic) symbol *sym = OP_SYMBOL (IC_LEFT (ic)); sym_link *ftype; -#if CALLEE_SAVES bool bcInUse = FALSE; bool deInUse = FALSE; -#endif setArea (IFFUNC_NONBANKED (sym->type)); @@ -2767,8 +2882,8 @@ genFunction (iCode * ic) /* Create the function header */ emit2 ("!functionheader", sym->name); - /* PENDING: portability. */ - emit2 ("__%s_start:", sym->rname); + sprintf (buffer, "%s_start", sym->rname); + emit2 ("!labeldef", buffer); emit2 ("!functionlabeldef", sym->rname); if (options.profile) @@ -2792,9 +2907,13 @@ genFunction (iCode * ic) _G.stack.param_offset = 0; -#if CALLEE_SAVES + if (z80_opts.calleeSavesBC) + { + bcInUse = TRUE; + } + /* Detect which registers are used. */ - if (sym->regsUsed) + if (IFFUNC_CALLEESAVES(sym->type) && sym->regsUsed) { int i; for (i = 0; i < sym->regsUsed->size; i++) @@ -2827,7 +2946,7 @@ genFunction (iCode * ic) _G.stack.param_offset += 2; } - _G.stack.pushedBC = bcInUse; + _G.calleeSaves.pushedBC = bcInUse; if (deInUse) { @@ -2835,8 +2954,7 @@ genFunction (iCode * ic) _G.stack.param_offset += 2; } - _G.stack.pushedDE = deInUse; -#endif + _G.calleeSaves.pushedDE = deInUse; /* adjust the stack for the function */ _G.stack.last = sym->stack; @@ -2882,19 +3000,17 @@ genEndFunction (iCode * ic) emit2 ("!leave"); } -#if CALLEE_SAVES - if (_G.stack.pushedDE) + if (_G.calleeSaves.pushedDE) { emit2 ("pop de"); - _G.stack.pushedDE = FALSE; + _G.calleeSaves.pushedDE = FALSE; } - if (_G.stack.pushedDE) + if (_G.calleeSaves.pushedBC) { emit2 ("pop bc"); - _G.stack.pushedDE = FALSE; + _G.calleeSaves.pushedBC = FALSE; } -#endif if (options.profile) { @@ -2905,8 +3021,8 @@ genEndFunction (iCode * ic) /* Both baned and non-banked just ret */ emit2 ("ret"); - /* PENDING: portability. */ - emit2 ("__%s_end:", sym->rname); + sprintf (buffer, "%s_end", sym->rname); + emit2 ("!labeldef", buffer); } _G.flushStatics = 1; _G.stack.pushed = 0; @@ -2950,7 +3066,7 @@ genRet (iCode * ic) if (IS_GB && size == 4 && requiresHL (AOP (IC_LEFT (ic)))) { fetchPair (PAIR_DE, AOP (IC_LEFT (ic))); - fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), 2); + fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), ic, 2); } else { @@ -3338,7 +3454,7 @@ genPlus (iCode * ic) if (isPair (AOP (IC_RIGHT (ic))) && AOP_TYPE (IC_LEFT (ic)) == AOP_IMMD && getPairId (AOP (IC_RIGHT (ic))) != PAIR_HL) { fetchPair (PAIR_HL, AOP (IC_LEFT (ic))); - emit2 ("add hl,%s ; 2", getPairName (AOP (IC_RIGHT (ic)))); + emit2 ("add hl,%s", getPairName (AOP (IC_RIGHT (ic)))); spillCached(); commitPair ( AOP (IC_RESULT (ic)), PAIR_HL); goto release; @@ -3688,8 +3804,9 @@ genMult (iCode * ic) // wassertl (val > 0, "Multiply must be positive"); wassertl (val != 1, "Can't multiply by 1"); - if (IS_Z80) { + if (IS_Z80 && isPairInUseNotInRet (PAIR_DE, ic)) { _push (PAIR_DE); + _G.stack.pushedDE = TRUE; } if ( AOP_SIZE (IC_LEFT (ic)) == 1 && !SPEC_USIGN (getSpec (operandType ( IC_LEFT (ic))))) @@ -3733,9 +3850,10 @@ genMult (iCode * ic) spillCached(); - if (IS_Z80) + if (IS_Z80 && _G.stack.pushedDE) { _pop (PAIR_DE); + _G.stack.pushedDE = FALSE; } commitPair ( AOP (IC_RESULT (ic)), PAIR_HL); @@ -3901,10 +4019,10 @@ _getPairIdName (PAIR_ID id) // Save the flags emit2 ("push af"); emit2 ("ld a,(de)"); - emit2 ("xor #0x80"); + emit2 ("xor !immedbyte", 0x80); emit2 ("ld e,a"); emit2 ("ld a,(hl)"); - emit2 ("xor #0x80"); + emit2 ("xor !immedbyte", 0x80); emit2 ("ld d,a"); emit2 ("pop af"); emit2 ("ld a,e"); @@ -3938,10 +4056,10 @@ _getPairIdName (PAIR_ID id) // Save the flags emit2 ("push af"); emit2 ("ld a,(hl)"); - emit2 ("xor #0x80"); + emit2 ("xor !immedbyte", 0x80); emit2 ("ld l,a"); emit2 ("ld a,%d(iy)", offset); - emit2 ("xor #0x80"); + emit2 ("xor !immedbyte", 0x80); emit2 ("ld h,a"); emit2 ("pop af"); emit2 ("ld a,l"); @@ -5271,9 +5389,16 @@ shiftL2Left2Result (operand * left, int offl, movLeft2Result (left, offl, result, offr, 0); movLeft2Result (left, offl + 1, result, offr + 1, 0); } - /* PENDING: for now just see if it'll work. */ - /*if (AOP(result)->type == AOP_REG) { */ - { + + if (getPairId (AOP (result)) == PAIR_HL) + { + while (shCount--) + { + emit2 ("add hl,hl"); + } + } + else + { int size = 2; int offset = 0; symbol *tlbl, *tlbl1; @@ -5282,34 +5407,56 @@ shiftL2Left2Result (operand * left, int offl, tlbl = newiTempLabel (NULL); tlbl1 = newiTempLabel (NULL); - /* Left is already in result - so now do the shift */ - if (shCount > 1) + if (AOP (result)->type == AOP_REG) { - emit2 ("ld a,!immedbyte+1", shCount); - emit2 ("!shortjp !tlabel", tlbl1->key + 100); - emitLabel (tlbl->key + 100); + while (shCount--) + { + for (offset = 0; offset < size; offset++) + { + l = aopGet (AOP (result), offset, FALSE); + + if (offset == 0) + { + emit2 ("sla %s", l); + } + else + { + emit2 ("rl %s", l); + } + } + } } - - while (size--) + else { - l = aopGet (AOP (result), offset, FALSE); - - if (offset == 0) - { - emit2 ("sla %s", l); - } - else - { - emit2 ("rl %s", l); - } + /* Left is already in result - so now do the shift */ + if (shCount > 1) + { + emit2 ("ld a,!immedbyte+1", shCount); + emit2 ("!shortjp !tlabel", tlbl1->key + 100); + emitLabel (tlbl->key + 100); + } - offset++; - } - if (shCount > 1) - { - emitLabel (tlbl1->key + 100); - emit2 ("dec a"); - emit2 ("!shortjp nz,!tlabel", tlbl->key + 100); + while (size--) + { + l = aopGet (AOP (result), offset, FALSE); + + if (offset == 0) + { + emit2 ("sla %s", l); + } + else + { + emit2 ("rl %s", l); + } + + offset++; + } + if (shCount > 1) + { + emitLabel (tlbl1->key + 100); + emit2 ("dec a"); + emit2 ("!shortjp nz,!tlabel", tlbl->key + 100); + } } } } @@ -5743,9 +5890,19 @@ genRightShiftLiteral (operand * left, wassert (0); } - else if (shCount >= (size * 8)) + else if (shCount >= (size * 8)) { + const char *s; + if (!SPEC_USIGN(getSpec(operandType(left)))) { + _moveA(aopGet (AOP (left), 0, FALSE)); + emit2 ("rlc a"); + emit2 ("sbc a,a"); + s=ACC_NAME; + } else { + s="!zero"; + } while (size--) - aopPut (AOP (result), "!zero", size); + aopPut (AOP (result), s, size); + } else { switch (size) @@ -5883,7 +6040,8 @@ genGenPointerGet (operand * left, /* Just do it */ if (isPtrPair (AOP (left))) { - tsprintf (buffer, "!*pair", getPairName (AOP (left))); + tsprintf (buffer, sizeof(buffer), + "!*pair", getPairName (AOP (left))); aopPut (AOP (result), buffer, 0); } else @@ -5895,14 +6053,14 @@ genGenPointerGet (operand * left, goto release; } - if ( getPairId( AOP (left)) == PAIR_IY) + if (getPairId (AOP (left)) == PAIR_IY) { /* Just do it */ offset = 0; while (size--) { char at[20]; - tsprintf (at, "!*iyx", offset); + tsprintf (at, sizeof(at), "!*iyx", offset); aopPut (AOP (result), at, offset); offset++; } @@ -5915,20 +6073,48 @@ genGenPointerGet (operand * left, /* if this is remateriazable */ fetchPair (pair, AOP (left)); - freeAsmop (left, NULL, ic); - /* if bit then unpack */ if (IS_BITVAR (retype)) { wassert (0); } - else if ( getPairId( AOP (result)) == PAIR_HL) + else if (getPairId (AOP (result)) == PAIR_HL) { wassertl (size == 2, "HL must be of size 2"); emit2 ("ld a,!*hl"); emit2 ("inc hl"); emit2 ("ld h,!*hl"); emit2 ("ld l,a"); + spillPair (PAIR_HL); + } + else if (getPairId (AOP (left)) == PAIR_HL && !isLastUse (ic, left)) + { + size = AOP_SIZE (result); + offset = 0; + + while (size--) + { + /* PENDING: make this better */ + if (!IS_GB && AOP_TYPE (result) == AOP_REG) + { + aopPut (AOP (result), "!*hl", offset++); + } + else + { + emit2 ("ld a,!*pair", _pairs[pair].name); + aopPut (AOP (result), "a", offset++); + } + if (size) + { + emit2 ("inc %s", _pairs[pair].name); + _G.pairs[pair].offset++; + } + } + /* Fixup HL back down */ + for (size = AOP_SIZE (result)-1; size; size--) + { + emit2 ("dec %s", _pairs[pair].name); + } } else { @@ -5938,7 +6124,8 @@ genGenPointerGet (operand * left, while (size--) { /* PENDING: make this better */ - if (!IS_GB && AOP (result)->type == AOP_REG) + if (!IS_GB && + (AOP_TYPE (result) == AOP_REG || AOP_TYPE (result) == AOP_HLREG)) { aopPut (AOP (result), "!*hl", offset++); } @@ -5955,6 +6142,8 @@ genGenPointerGet (operand * left, } } + freeAsmop (left, NULL, ic); + release: freeAsmop (result, NULL, ic); } @@ -6045,6 +6234,37 @@ genGenPointerSet (operand * right, } goto release; } + else if (getPairId (AOP (result)) == PAIR_HL && !isLastUse (ic, result)) + { + offset = 0; + + while (size--) + { + const char *l = aopGet (AOP (right), offset, FALSE); + if (isRegOrLit (AOP (right)) && !IS_GB) + { + emit2 ("ld !*pair,%s", _pairs[PAIR_HL].name, l); + } + else + { + _moveA (l); + emit2 ("ld !*pair,a", _pairs[PAIR_HL].name); + } + if (size) + { + emit2 ("inc %s", _pairs[PAIR_HL].name); + _G.pairs[PAIR_HL].offset++; + } + offset++; + } + + /* Fixup HL back down */ + for (size = AOP_SIZE (right)-1; size; size--) + { + emit2 ("dec %s", _pairs[PAIR_HL].name); + } + goto release; + } /* if the operand is already in dptr then we do nothing else we move the value to dptr */ @@ -6184,14 +6404,14 @@ genAddrOf (iCode * ic) { /* if it has an offset then we need to compute it */ if (sym->stack > 0) - emit2 ("ld hl,#%d+%d+%d+%d", sym->stack, _G.stack.pushed, _G.stack.offset, _G.stack.param_offset); + emit2 ("ld hl,!immedword", sym->stack + _G.stack.pushed + _G.stack.offset + _G.stack.param_offset); else - emit2 ("ld hl,#%d+%d+%d", sym->stack, _G.stack.pushed, _G.stack.offset); + emit2 ("ld hl,!immedword", sym->stack + _G.stack.pushed + _G.stack.offset); emit2 ("add hl,sp"); } else { - emit2 ("ld hl,#%s", sym->rname); + emit2 ("ld hl,!hashedstr", sym->rname); } commitPair (AOP (IC_RESULT (ic)), PAIR_HL); } @@ -6240,12 +6460,12 @@ genAssign (iCode * ic) if (AOP_TYPE (right) == AOP_LIT) { - lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit); + lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit); } if (isPair (AOP (result))) { - fetchPair (getPairId (AOP (result)), AOP (right)); + fetchPairLong (getPairId (AOP (result)), AOP (right), ic, LSB); } else if ((size > 1) && (AOP_TYPE (result) != AOP_REG) && @@ -6382,7 +6602,7 @@ static void genCast (iCode * ic) { operand *result = IC_RESULT (ic); - sym_link *ctype = operandType (IC_LEFT (ic)); + sym_link *rtype = operandType (IC_RIGHT (ic)); operand *right = IC_RIGHT (ic); int size, offset; @@ -6436,7 +6656,7 @@ genCast (iCode * ic) /* now depending on the sign of the destination */ size = AOP_SIZE (result) - AOP_SIZE (right); /* Unsigned or not an integral type - right fill with zeros */ - if (SPEC_USIGN (ctype) || !IS_SPEC (ctype)) + if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE(right)==AOP_CRY) { while (size--) aopPut (AOP (result), "!zero", offset++); @@ -6612,7 +6832,7 @@ _rleAppend(RLECTX *self, int c) /* Yes, worthwhile. */ /* Commit whatever was in the buffer. */ _rleCommit(self); - emit2(".db -%u,0x%02X", self->runLen, self->last); + emit2("!db !immed-%u,!immedbyte", self->runLen, self->last); } else { @@ -6637,7 +6857,7 @@ _rleAppend(RLECTX *self, int c) /* Commit whatever was in the buffer. */ _rleCommit(self); - emit2 (".db -%u,0x%02X", self->runLen, self->last); + emit2 ("!db !immed-%u,!immedbyte", self->runLen, self->last); self->runLen = 0; } self->runLen++; @@ -6938,9 +7158,7 @@ static void genBuiltInMemcpy (iCode *ic, int nParams, operand **pparams) { operand *from, *to, *count; - symbol *label; bool deInUse; - iCode *pcall; wassertl (nParams == 3, "Built-in memcpy must have two parameters"); to = pparams[2]; @@ -7031,9 +7249,15 @@ genZ80Code (iCode * lic) if (cln != ic->lineno) { - emit2 ("; %s %d", ic->filename, ic->lineno); + if (!options.noCcodeInAsm) { + emit2 (";%s:%d: %s", ic->filename, ic->lineno, + printCLine(ic->filename, ic->lineno)); + } cln = ic->lineno; } + if (options.iCodeInAsm) { + emit2 (";ic:%d: %s", ic->key, printILine(ic)); + } /* if the result is marked as spilt and rematerializable or code for this has already been generated then @@ -7354,7 +7578,7 @@ fetchLitSpecial (asmop * aop, bool negate, bool xor) v = 0-v; v &= 0xFFFF; - tsprintf (buffer, "!immedword", v); + tsprintf (buffer, sizeof(buffer), "!immedword", v); return traceAlloc(&_G.trace.aops, Safe_strdup (buffer)); }