X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Fz80%2Fgen.c;h=e9b3302b73642afb8922c51d0a4763b158635b14;hb=30357bade4ba51536bdf52d60db2a3c96251a1ff;hp=9df933375c825dcb4c6b9d69b87fb7ef731c0971;hpb=f9e215854492482aeee7d24ab3814253e4fac96c;p=fw%2Fsdcc diff --git a/src/z80/gen.c b/src/z80/gen.c index 9df93337..e9b3302b 100644 --- a/src/z80/gen.c +++ b/src/z80/gen.c @@ -214,12 +214,15 @@ static struct int pushedDE; } calleeSaves; + bool omitFramePtr; int frameId; int receiveOffset; bool flushStatics; bool in_home; const char *lastFunctionName; - + iCode *current_iCode; + bool preserveCarry; + set *sendSet; struct @@ -233,6 +236,7 @@ static struct lineNode *head; lineNode *current; int isInline; + int isDebug; allocTrace trace; } lines; @@ -260,7 +264,8 @@ static const char *aopNames[] = { "AOP_HLREG", "AOP_SIMPLELIT", "AOP_EXSTK", - "AOP_PAIRPT" + "AOP_PAIRPT", + "AOP_DUMMY" }; static bool @@ -396,7 +401,7 @@ _newLineNode (char *line) static void _vemit2 (const char *szFormat, va_list ap) { - char buffer[256]; + char buffer[INITIAL_INLINEASM]; tvsprintf (buffer, sizeof(buffer), szFormat, ap); @@ -406,6 +411,8 @@ _vemit2 (const char *szFormat, va_list ap) (_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; } static void @@ -465,6 +472,7 @@ _emit2 (const char *inst, const char *fmt,...) (_G.lines.head = _newLineNode (lb))); } _G.lines.current->isInline = _G.lines.isInline; + _G.lines.current->ic = _G.current_iCode; va_end (ap); } @@ -485,12 +493,26 @@ _emitMove(const char *to, const char *from) void 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) { + case AOP_EXSTK: case AOP_STK: emitDebug("; aop_stk %d", aop->aopu.aop_stk); break; + case AOP_REG: + for (i=aop->size-1;i>=0;i--) + *rbp++ = *(aop->aopu.aop_reg[i]->name); + *rbp = '\0'; + emitDebug("; reg = %s", regbuf); + break; + case AOP_PAIRPTR: + emitDebug("; pairptr = (%s)", _pairs[aop->aopu.aop_pairId].name); + default: /* No information. */ break; @@ -623,6 +645,30 @@ spillPair (PAIR_ID pairId) _G.pairs[pairId].base = NULL; } +/* 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) + { + case 'h': + case 'l': + spillPair(PAIR_HL); + break; + case 'd': + case 'e': + spillPair(PAIR_DE); + break; + case 'b': + case 'c': + spillPair(PAIR_BC); + break; + } + } +} + /** Push a register pair onto the stack */ void genPairPush (asmop * aop) @@ -645,6 +691,39 @@ _pop (PAIR_ID pairId) spillPair (pairId); } +void +genMovePairPair (PAIR_ID srcPair, PAIR_ID dstPair) +{ + switch (dstPair) + { + case PAIR_IX: + case PAIR_IY: + case PAIR_AF: + _push(srcPair); + _pop(dstPair); + break; + case PAIR_BC: + case PAIR_DE: + case PAIR_HL: + if (srcPair == PAIR_IX || srcPair == PAIR_IY) + { + _push(srcPair); + _pop(dstPair); + } + else + { + emit2("ld %s,%s",_pairs[dstPair].l,_pairs[srcPair].l); + emit2("ld %s,%s",_pairs[dstPair].h,_pairs[srcPair].h); + } + default: + wassertl (0, "Tried to move a nonphysical pair"); + } + _G.pairs[dstPair].last_type = _G.pairs[srcPair].last_type; + _G.pairs[dstPair].base = _G.pairs[srcPair].base; + _G.pairs[dstPair].offset = _G.pairs[srcPair].offset; +} + + /*-----------------------------------------------------------------*/ /* newAsmop - creates a new asmOp */ /*-----------------------------------------------------------------*/ @@ -686,7 +765,7 @@ aopForSym (iCode * ic, symbol * sym, bool result, bool requires_a) Normally everything is AOP_STK, but for offsets of < -128 or > 127 on the Z80 an extended stack pointer is used. */ - if (IS_Z80 && (options.ommitFramePtr || sym->stack < INT8MIN || sym->stack > (int)(INT8MAX-getSize (sym->type)))) + if (IS_Z80 && (_G.omitFramePtr || sym->stack < INT8MIN || sym->stack > (int)(INT8MAX-getSize (sym->type)))) { emitDebug ("; AOP_EXSTK for %s", sym->rname); sym->aop = aop = newAsmop (AOP_EXSTK); @@ -1007,14 +1086,21 @@ aopOp (operand * op, iCode * ic, bool result, bool requires_a) return; } - /* 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"); + if (sym->usl.spillLoc) + { + 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; + } + + /* else must be a dummy iTemp */ + sym->aop = op->aop = aop = newAsmop (AOP_DUMMY); aop->size = getSize (sym->type); return; } @@ -1396,6 +1482,12 @@ setupPairFromSP (PAIR_ID id, int offset) { wassertl (id == PAIR_HL, "Setup relative to SP only implemented for HL"); + if (_G.preserveCarry) + { + _push (PAIR_AF); + offset += 2; + } + if (offset < INT8MIN || offset > INT8MAX) { emit2 ("ld hl,!immedword", offset); @@ -1403,7 +1495,13 @@ setupPairFromSP (PAIR_ID id, int offset) } else { - emit2 ("!ldahlsp", offset); + emit2 ("!ldahlsp", offset); + } + + if (_G.preserveCarry) + { + _pop (PAIR_AF); + offset -= 2; } } @@ -1439,11 +1537,15 @@ setupPair (PAIR_ID pairId, asmop * aop, int offset) else { /* PENDING: Do this better. */ + if (_G.preserveCarry) + _push (PAIR_AF); sprintf (buffer, "%d", offset + _G.stack.pushed); emit2 ("ld %s,!hashedstr", _pairs[pairId].name, buffer); emit2 ("add %s,sp", _pairs[pairId].name); _G.pairs[pairId].last_type = aop->type; _G.pairs[pairId].offset = offset; + if (_G.preserveCarry) + _pop (PAIR_AF); } } break; @@ -1472,6 +1574,8 @@ setupPair (PAIR_ID pairId, asmop * aop, int offset) } case AOP_PAIRPTR: + if (pairId != aop->aopu.aop_pairId) + genMovePairPair(aop->aopu.aop_pairId, pairId); adjustPair (_pairs[pairId].name, &_G.pairs[pairId].offset, offset); break; @@ -1508,6 +1612,10 @@ aopGet (asmop * aop, int offset, bool bit16) /* depending on type */ switch (aop->type) { + case AOP_DUMMY: + tsprintf (buffer, sizeof(buffer), "!zero"); + return traceAlloc(&_G.trace.aops, Safe_strdup(buffer)); + case AOP_IMMD: /* PENDING: re-target */ if (bit16) @@ -1621,8 +1729,15 @@ aopGet (asmop * aop, int offset, bool bit16) case AOP_PAIRPTR: setupPair (aop->aopu.aop_pairId, aop, offset); - SNPRINTF (buffer, sizeof(buffer), - "(%s)", _pairs[aop->aopu.aop_pairId].name); + if (aop->aopu.aop_pairId==PAIR_IX) + SNPRINTF (buffer, sizeof(buffer), + "!*ixx", 0); + else if (aop->aopu.aop_pairId==PAIR_IY) + SNPRINTF (buffer, sizeof(buffer), + "!*iyx", 0); + else + SNPRINTF (buffer, sizeof(buffer), + "(%s)", _pairs[aop->aopu.aop_pairId].name); return traceAlloc(&_G.trace.aops, Safe_strdup(buffer)); @@ -1687,6 +1802,10 @@ aopPut (asmop * aop, const char *s, int offset) /* depending on where it is ofcourse */ switch (aop->type) { + case AOP_DUMMY: + _moveA (s); /* in case s is volatile */ + break; + case AOP_DIR: /* Direct. Hmmm. */ wassert (IS_GB); @@ -1708,6 +1827,7 @@ aopPut (asmop * aop, const char *s, int offset) else emit2 ("ld %s,%s", aop->aopu.aop_reg[offset]->name, s); + spillPairReg(aop->aopu.aop_reg[offset]->name); break; case AOP_IY: @@ -1807,6 +1927,7 @@ aopPut (asmop * aop, const char *s, int offset) { emit2 ("ld %s,%s", aop->aopu.aop_str[offset], s); } + spillPairReg(aop->aopu.aop_str[offset]); break; case AOP_ACC: @@ -1820,18 +1941,27 @@ aopPut (asmop * aop, const char *s, int offset) else { 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_HLREG: wassert (offset < 2); emit2 ("ld %s,%s", aop->aopu.aop_str[offset], s); + spillPairReg(aop->aopu.aop_str[offset]); break; case AOP_PAIRPTR: setupPair (aop->aopu.aop_pairId, aop, offset); - emit2 ("ld (%s),%s", _pairs[aop->aopu.aop_pairId].name, s); + 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); + else + emit2 ("ld (%s),%s", _pairs[aop->aopu.aop_pairId].name, s); break; default: @@ -2033,43 +2163,6 @@ _toBoolean (operand * oper) } } -/*-----------------------------------------------------------------*/ -/* genNotFloat - generates not for float operations */ -/*-----------------------------------------------------------------*/ -static void -genNotFloat (operand * op, operand * res) -{ - int size, offset; - symbol *tlbl; - - emitDebug ("; genNotFloat"); - - /* we will put 127 in the first byte of - the result */ - aopPut (AOP (res), "!immedbyte", 0x7F); - size = AOP_SIZE (op) - 1; - offset = 1; - - _moveA (aopGet (op->aop, offset++, FALSE)); - - while (size--) - { - emit2 ("or a,%s", aopGet (op->aop, offset++, FALSE)); - } - - tlbl = newiTempLabel (NULL); - aopPut (res->aop, "!one", 1); - emit2 ("!shortjp z !tlabel", tlbl->key + 100); - aopPut (res->aop, "!zero", 1); - - emitLabel(tlbl->key + 100); - - size = res->aop->size - 2; - offset = 2; - /* put zeros in the rest */ - while (size--) - aopPut (res->aop, "!zero", offset++); -} /*-----------------------------------------------------------------*/ /* genNot - generate code for ! operation */ @@ -2077,7 +2170,6 @@ genNotFloat (operand * op, operand * res) static void genNot (iCode * ic) { - sym_link *optype = operandType (IC_LEFT (ic)); /* assign asmOps to operand & result */ aopOp (IC_LEFT (ic), ic, FALSE, TRUE); @@ -2089,13 +2181,6 @@ genNot (iCode * ic) wassertl (0, "Tried to negate a bit"); } - /* if type float then do float */ - if (IS_FLOAT (optype)) - { - genNotFloat (IC_LEFT (ic), IC_RESULT (ic)); - goto release; - } - _toBoolean (IC_LEFT (ic)); /* Not of A: @@ -2105,7 +2190,6 @@ genNot (iCode * ic) emit2 ("sub a,!one"); outBitC (IC_RESULT (ic)); - release: /* release the aops */ freeAsmop (IC_LEFT (ic), NULL, ic); freeAsmop (IC_RESULT (ic), NULL, ic); @@ -2377,7 +2461,8 @@ _saveRegsForCall(iCode *ic, int sendSetSize) bool bcInRet = FALSE, deInRet = FALSE; bitVect *rInUse; - rInUse = bitVectCplAnd (bitVectCopy (ic->rMask), ic->rUsed); + rInUse = bitVectCplAnd (bitVectCopy (ic->rMask), + z80_rUmaskForOp (IC_RESULT(ic))); deInUse = bitVectBitValue (rInUse, D_IDX) || bitVectBitValue(rInUse, E_IDX); bcInUse = bitVectBitValue (rInUse, B_IDX) || bitVectBitValue(rInUse, C_IDX); @@ -2612,6 +2697,7 @@ _opUsesPair (operand * op, iCode * ic, PAIR_ID pairId) static void emitCall (iCode * ic, bool ispcall) { + bool bInRet, cInRet, dInRet, eInRet; sym_link *dtype = operandType (IC_LEFT (ic)); /* if caller saves & we have not saved then */ @@ -2780,12 +2866,24 @@ emitCall (iCode * ic, bool ispcall) } spillCached (); + if (IC_RESULT (ic)) + { + bitVect *result = z80_rUmaskForOp (IC_RESULT (ic)); + bInRet = bitVectBitValue(result, B_IDX); + cInRet = bitVectBitValue(result, C_IDX); + dInRet = bitVectBitValue(result, D_IDX); + eInRet = bitVectBitValue(result, E_IDX); + } + else + { + bInRet = FALSE; + cInRet = FALSE; + dInRet = FALSE; + eInRet = FALSE; + } if (_G.stack.pushedDE) { - bool dInRet = bitVectBitValue(ic->rUsed, D_IDX); - bool eInRet = bitVectBitValue(ic->rUsed, E_IDX); - if (dInRet && eInRet) { wassertl (0, "Shouldn't push DE if it's wiped out by the return"); @@ -2812,9 +2910,6 @@ emitCall (iCode * ic, bool ispcall) if (_G.stack.pushedBC) { - bool bInRet = bitVectBitValue(ic->rUsed, B_IDX); - bool cInRet = bitVectBitValue(ic->rUsed, C_IDX); - if (bInRet && cInRet) { wassertl (0, "Shouldn't push BC if it's wiped out by the return"); @@ -2885,6 +2980,8 @@ extern set *publics; static void genFunction (iCode * ic) { + bool stackParm; + symbol *sym = OP_SYMBOL (IC_LEFT (ic)); sym_link *ftype; @@ -2979,8 +3076,29 @@ genFunction (iCode * ic) /* adjust the stack for the function */ _G.stack.last = sym->stack; - - if (sym->stack && IS_GB && sym->stack > -INT8MIN) + + stackParm = FALSE; + for (sym = setFirstItem (istack->syms); sym; + sym = setNextItem (istack->syms)) + { + if (sym->_isparm && !IS_REGPARM (sym->etype)) + { + stackParm = TRUE; + break; + } + } + sym = OP_SYMBOL (IC_LEFT (ic)); + + _G.omitFramePtr = options.ommitFramePtr; + if (IS_Z80 && !stackParm && !sym->stack) + { + /* When the conflicts between AOP_EXSTK && AOP_HLREG are fixed, */ + /* the above !sym->stack condition can be removed. -- EEP */ + if (sym->stack) + emit2 ("!ldaspsp", -sym->stack); + _G.omitFramePtr = TRUE; + } + else if (sym->stack && IS_GB && sym->stack > -INT8MIN) emit2 ("!enterxl", sym->stack); else if (sym->stack) emit2 ("!enterx", sym->stack); @@ -3008,7 +3126,12 @@ genEndFunction (iCode * ic) /* PENDING: calleeSave */ - if (_G.stack.offset && IS_GB && _G.stack.offset > INT8MAX) + if (IS_Z80 && _G.omitFramePtr) + { + if (_G.stack.offset) + emit2 ("!ldaspsp", _G.stack.offset); + } + else if (_G.stack.offset && IS_GB && _G.stack.offset > INT8MAX) { emit2 ("!leavexl", _G.stack.offset); } @@ -3039,7 +3162,22 @@ genEndFunction (iCode * ic) } - /* Both baned and non-banked just ret */ + if (options.debug && currFunc) + { + _G.lines.isDebug = 1; + sprintf (buffer, "C$%s$%d$%d$%d", + FileBaseName (ic->filename), currFunc->lastLine, + ic->level, ic->block); + emit2 ("!labeldef", buffer); + if (IS_STATIC (currFunc->etype)) + sprintf (buffer, "XF%s$%s$0$0", moduleName, currFunc->name); + else + sprintf (buffer, "XG$%s$0$0", currFunc->name); + emit2 ("!labeldef", buffer); + _G.lines.isDebug = 0; + } + + /* Both banked and non-banked just ret */ emit2 ("ret"); sprintf (buffer, "%s_end", sym->rname); @@ -3071,6 +3209,9 @@ genRet (iCode * ic) aopOp (IC_LEFT (ic), ic, FALSE, FALSE); size = AOP_SIZE (IC_LEFT (ic)); + aopDump("IC_LEFT", AOP(IC_LEFT(ic))); + + #if 0 if ((size == 2) && ((l = aopGetWord (AOP (IC_LEFT (ic)), 0)))) { if (IS_GB) @@ -3082,6 +3223,11 @@ genRet (iCode * ic) emit2 ("ld hl,%s", l); } } + #endif + if (size==2) + { + fetchPair(IS_GB ? PAIR_DE : PAIR_HL, AOP (IC_LEFT (ic))); + } else { if (IS_GB && size == 4 && requiresHL (AOP (IC_LEFT (ic)))) @@ -3096,7 +3242,8 @@ genRet (iCode * ic) l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE); if (strcmp (_fReturn[offset], l)) - emit2 ("ld %s,%s", _fReturn[offset++], l); + emit2 ("ld %s,%s", _fReturn[offset], l); + offset++; } } } @@ -3345,11 +3492,16 @@ setupToPreserveCarry (asmop *result, asmop *left, asmop *right) if (couldDestroyCarry (right) && couldDestroyCarry (result)) { shiftIntoPair (0, right); - shiftIntoPair (1, result); + /* check result again, in case right == result */ + if (couldDestroyCarry (result)) + shiftIntoPair (1, result); } else if (couldDestroyCarry (right)) { - shiftIntoPair (0, right); + if (getPairId (result) == PAIR_HL) + _G.preserveCarry = TRUE; + else + shiftIntoPair (0, right); } else if (couldDestroyCarry (result)) { @@ -3551,7 +3703,7 @@ genPlus (iCode * ic) goto release; } } - + setupToPreserveCarry (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)), AOP (IC_RIGHT (ic))); while (size--) @@ -3580,6 +3732,7 @@ genPlus (iCode * ic) } release: + _G.preserveCarry = FALSE; freeAsmop (IC_LEFT (ic), NULL, ic); freeAsmop (IC_RIGHT (ic), NULL, ic); freeAsmop (IC_RESULT (ic), NULL, ic); @@ -3783,6 +3936,7 @@ genMinus (iCode * ic) } release: + _G.preserveCarry = FALSE; freeAsmop (IC_LEFT (ic), NULL, ic); freeAsmop (IC_RIGHT (ic), NULL, ic); freeAsmop (IC_RESULT (ic), NULL, ic); @@ -5189,7 +5343,7 @@ genXor (iCode * ic, iCode * ifx) _moveA (aopGet (AOP (right), offset, FALSE)); emit2 ("xor a,%s", aopGet (AOP (left), offset, FALSE)); - aopPut (AOP (result), "a", 0); + aopPut (AOP (result), "a", offset); } } } @@ -6944,7 +7098,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 (rtype) || !IS_SPEC (rtype) || AOP_TYPE(right)==AOP_CRY) + if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY) { while (size--) aopPut (AOP (result), "!zero", offset++); @@ -7001,9 +7155,23 @@ genReceive (iCode * ic) static void genDummyRead (iCode * ic) { - emit2 ("; genDummyRead not implemented"); + operand *right; + int size, offset; + + right = IC_RIGHT (ic); + aopOp (right, ic, FALSE, FALSE); + + /* general case */ + size = AOP_SIZE (right); + offset = 0; + + while (size--) + { + _moveA (aopGet (AOP (right), offset, FALSE)); + offset++; + } - ic = ic; + freeAsmop (right, NULL, ic); } enum @@ -7542,12 +7710,36 @@ genZ80Code (iCode * lic) } _G.lines.head = _G.lines.current = NULL; + + /* if debug information required */ + if (options.debug && currFunc) + { + debugFile->writeFunction(currFunc); + _G.lines.isDebug = 1; + if (IS_STATIC (currFunc->etype)) + sprintf (buffer, "F%s$%s$0$0", moduleName, currFunc->name); + else + sprintf (buffer, "G$%s$0$0", currFunc->name); + emit2 ("!labeldef", buffer); + _G.lines.isDebug = 0; + } for (ic = lic; ic; ic = ic->next) { + _G.current_iCode = ic; - if (cln != ic->lineno) + if (ic->lineno && cln != ic->lineno) { + if (options.debug) + { + _G.lines.isDebug = 1; + sprintf (buffer, "C$%s$%d$%d$%d", + FileBaseName (ic->filename), ic->lineno, + ic->level, ic->block); + emit2 ("%s !equ .", buffer); + emit2 ("!global", buffer); + _G.lines.isDebug = 0; + } if (!options.noCcodeInAsm) { emit2 (";%s:%d: %s", ic->filename, ic->lineno, printCLine(ic->filename, ic->lineno)); @@ -7811,6 +8003,7 @@ genZ80Code (iCode * lic) break; case DUMMY_READ_VOLATILE: + emitDebug ("; genDummyRead"); genDummyRead (ic); break;