X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Fz80%2Fgen.c;h=826a2cf4114a071b472c5e33bd82f7907fab601e;hb=0f13c644cfaea92c44ee33764cce21da520676f1;hp=d2af3cd5dc735fdd44eda630b804cfb7a5ec7538;hpb=8e771bbd4bcbc2c888bd57e4877f364a63e24787;p=fw%2Fsdcc diff --git a/src/z80/gen.c b/src/z80/gen.c index d2af3cd5..826a2cf4 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 @@ -233,6 +235,49 @@ static struct static const char *aopGet (asmop * aop, int offset, bool bit16); +static const char *aopNames[] = { + "AOP_INVALID", + "AOP_LIT", + "AOP_REG", + "AOP_DIR", + "AOP_SFR", + "AOP_STK", + "AOP_IMMD", + "AOP_STR", + "AOP_CRY", + "AOP_IY", + "AOP_HL", + "AOP_ACC", + "AOP_HLREG", + "AOP_SIMPLELIT", + "AOP_EXSTK", + "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) { @@ -252,14 +297,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; } @@ -392,6 +473,20 @@ _emitMove(const char *to, const char *from) } } +void +aopDump(const char *plabel, asmop *aop) +{ + emitDebug("; Dump of %s: type %s size %u", plabel, aopNames[aop->type], aop->size); + switch (aop->type) + { + case AOP_STK: + emitDebug("; aop_stk %d", aop->aopu.aop_stk); + break; + default: + /* No information. */ + } +} + static void _moveA(const char *moveFrom) { @@ -554,7 +649,9 @@ aopForSym (iCode * ic, symbol * sym, bool result, bool requires_a) /* if already has one */ if (sym->aop) - return sym->aop; + { + return sym->aop; + } /* Assign depending on the storage class */ if (sym->onStack || sym->iaccess) @@ -791,7 +888,9 @@ aopOp (operand * op, iCode * ic, bool result, bool requires_a) /* if already has a asmop then continue */ if (op->aop) - return; + { + return; + } /* if the underlying symbol has a aop */ if (IS_SYMOP (op) && OP_SYMBOL (op)->aop) @@ -883,8 +982,13 @@ aopOp (operand * op, iCode * ic, bool result, bool requires_a) } /* else spill location */ + 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); return; } @@ -1133,8 +1237,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)) { @@ -1186,19 +1318,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); @@ -1208,7 +1345,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 @@ -1278,6 +1415,7 @@ setupPair (PAIR_ID pairId, asmop * aop, int offset) { /* 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; @@ -1613,7 +1751,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 @@ -2001,7 +2139,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); @@ -2290,11 +2428,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; @@ -2581,7 +2719,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"); } @@ -2726,8 +2864,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) @@ -2864,8 +3002,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; @@ -2909,7 +3047,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 { @@ -3297,7 +3435,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; @@ -3647,8 +3785,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))))) @@ -3692,9 +3831,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); @@ -3860,10 +4000,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"); @@ -3897,10 +4037,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"); @@ -5127,6 +5267,7 @@ genGetHbit (iCode * ic) operand *left, *result; left = IC_LEFT (ic); result = IC_RESULT (ic); + aopOp (left, ic, FALSE, FALSE); aopOp (result, ic, FALSE, FALSE); @@ -5141,8 +5282,7 @@ genGetHbit (iCode * ic) else { emit2 ("rlc a"); - /* PENDING: For re-target. */ - emit2 ("and a,#1"); + emit2 ("and a,!one"); outAcc (result); } @@ -5230,9 +5370,13 @@ 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 (shCount == 1 && getPairId (AOP (result)) == PAIR_HL) + { + emit2 ("add hl,hl"); + } + else + { int size = 2; int offset = 0; symbol *tlbl, *tlbl1; @@ -5854,7 +5998,7 @@ genGenPointerGet (operand * left, goto release; } - if ( getPairId( AOP (left)) == PAIR_IY) + if (getPairId (AOP (left)) == PAIR_IY) { /* Just do it */ offset = 0; @@ -5865,6 +6009,8 @@ genGenPointerGet (operand * left, aopPut (AOP (result), at, offset); offset++; } + + freeAsmop (left, NULL, ic); goto release; } @@ -5872,14 +6018,12 @@ 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"); @@ -5887,6 +6031,35 @@ genGenPointerGet (operand * left, emit2 ("ld h,!*hl"); emit2 ("ld l,a"); } + 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 { size = AOP_SIZE (result); @@ -5895,7 +6068,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++); } @@ -5912,6 +6086,8 @@ genGenPointerGet (operand * left, } } + freeAsmop (left, NULL, ic); + release: freeAsmop (result, NULL, ic); } @@ -6002,6 +6178,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 */ @@ -6141,14 +6348,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); } @@ -6197,12 +6404,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) && @@ -6339,7 +6546,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; @@ -6393,7 +6600,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++); @@ -6569,7 +6776,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 { @@ -6594,7 +6801,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++; @@ -6895,9 +7102,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];