X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Fz80%2Fgen.c;h=7231edf2b9ef1cf9894c46ede6d6745f1fbb0149;hb=51da61d71d46c2b96789bb6f536c48b83964e138;hp=826a2cf4114a071b472c5e33bd82f7907fab601e;hpb=ef203f08aa15a9f5e4f2ad806374a6a1667dcff1;p=fw%2Fsdcc diff --git a/src/z80/gen.c b/src/z80/gen.c index 826a2cf4..7231edf2 100644 --- a/src/z80/gen.c +++ b/src/z80/gen.c @@ -87,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" @@ -205,6 +207,13 @@ static struct int pushedBC; int pushedDE; } stack; + + struct + { + int pushedBC; + int pushedDE; + } calleeSaves; + int frameId; int receiveOffset; bool flushStatics; @@ -389,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 ? @@ -417,11 +426,11 @@ emitDebug (const char *szFormat,...) if (!DISABLE_DEBUG) { va_list ap; - + va_start (ap, szFormat); - + _vemit2 (szFormat, ap); - + va_end (ap); } } @@ -462,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); } @@ -484,6 +493,7 @@ aopDump(const char *plabel, asmop *aop) break; default: /* No information. */ + break; } } @@ -1026,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) @@ -1060,8 +1075,6 @@ isLitWord (asmop * aop) char * aopGetLitWordLong (asmop * aop, int offset, bool with_hash) { - char *s = buffer; - /* depending on type */ switch (aop->type) { @@ -1071,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: { @@ -1106,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)); } @@ -1124,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)); } @@ -1457,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 */ @@ -1474,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; @@ -1513,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"); @@ -1556,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: @@ -1572,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; @@ -1582,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; @@ -1640,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 */ @@ -1898,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) { @@ -2847,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)); @@ -2889,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++) @@ -2924,7 +2946,7 @@ genFunction (iCode * ic) _G.stack.param_offset += 2; } - _G.stack.pushedBC = bcInUse; + _G.calleeSaves.pushedBC = bcInUse; if (deInUse) { @@ -2932,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; @@ -2979,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) { @@ -5371,9 +5390,12 @@ shiftL2Left2Result (operand * left, int offl, movLeft2Result (left, offl + 1, result, offr + 1, 0); } - if (shCount == 1 && getPairId (AOP (result)) == PAIR_HL) + if (getPairId (AOP (result)) == PAIR_HL) { - emit2 ("add hl,hl"); + while (shCount--) + { + emit2 ("add hl,hl"); + } } else { @@ -5385,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); + } } } } @@ -5846,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) @@ -5911,13 +5965,16 @@ genRightShift (iCode * ic) return; } + emit2 ("ld a,%s", aopGet (AOP (right), 0, FALSE)); + emit2 ("inc a"); + freeAsmop (right, NULL, ic); + aopOp (left, ic, FALSE, FALSE); aopOp (result, ic, FALSE, FALSE); /* now move the left to the result if they are not the same */ - if (!sameRegs (AOP (left), AOP (result)) && - AOP_SIZE (result) > 1) + if (!sameRegs (AOP (left), AOP (result))) { size = AOP_SIZE (result); @@ -5930,10 +5987,6 @@ genRightShift (iCode * ic) } } - emit2 ("ld a,%s", aopGet (AOP (right), 0, FALSE)); - emit2 ("inc a"); - freeAsmop (right, NULL, ic); - tlbl = newiTempLabel (NULL); tlbl1 = newiTempLabel (NULL); size = AOP_SIZE (result); @@ -5986,7 +6039,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 @@ -6005,7 +6059,7 @@ genGenPointerGet (operand * left, while (size--) { char at[20]; - tsprintf (at, "!*iyx", offset); + tsprintf (at, sizeof(at), "!*iyx", offset); aopPut (AOP (result), at, offset); offset++; } @@ -6030,6 +6084,7 @@ genGenPointerGet (operand * left, emit2 ("inc hl"); emit2 ("ld h,!*hl"); emit2 ("ld l,a"); + spillPair (PAIR_HL); } else if (getPairId (AOP (left)) == PAIR_HL && !isLastUse (ic, left)) { @@ -6651,6 +6706,17 @@ genReceive (iCode * ic) freeAsmop (IC_RESULT (ic), NULL, ic); } +/*-----------------------------------------------------------------*/ +/* genDummyRead - generate code for dummy read of volatiles */ +/*-----------------------------------------------------------------*/ +static void +genDummyRead (iCode * ic) +{ + emit2 ("; genDummyRead not implemented"); + + ic = ic; +} + enum { /** Maximum number of bytes to emit per line. */ @@ -7193,9 +7259,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 @@ -7448,7 +7520,11 @@ genZ80Code (iCode * lic) emitDebug ("; genArrayInit"); genArrayInit(ic); break; - + + case DUMMY_READ_VOLATILE: + genDummyRead (ic); + break; + default: ic = ic; } @@ -7516,7 +7592,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)); }