/*-------------------------------------------------------------------------
gen.c - Z80 specific code generator.
+
+ Michael Hope <michaelh@juju.net.nz> 2000
+ Based on the mcs51 generator -
+ Sandeep Dutta . sandeep.dutta@usa.net (1998)
+ and - Jean-Louis VERN.jlvern@writeme.com (1999)
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any
+ later version.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ In other words, you are welcome to use, share and improve this program.
+ You are forbidden to forbid anyone else to use, share and improve
+ what you give them. Help stamp out software-hoarding!
+
+-------------------------------------------------------------------------*/
+
+/*
Benchmarks on dhry.c 2.1 with 32766 loops and a 10ms clock:
ticks dhry size
Base with asm strcpy / strcmp / memcpy: 23198 141 1A14
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
- Michael Hope <michaelh@juju.net.nz> 2000
- Based on the mcs51 generator -
- Sandeep Dutta . sandeep.dutta@usa.net (1998)
- and - Jean-Louis VERN.jlvern@writeme.com (1999)
-
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 2, or (at your option) any
- later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
- In other words, you are welcome to use, share and improve this program.
- You are forbidden to forbid anyone else to use, share and improve
- what you give them. Help stamp out software-hoarding!
-
--------------------------------------------------------------------------*/
+ 10 and below are with asm strings off.
+
+ Apparent advantage of turning on regparams:
+ 1. Cost of push
+ 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
+ - ld hl,#2; add hl,sp; (ld bc,(hl); hl+=2)*nargs
+ 10+11+(7+6+7+6)*nargs
+ 3. Cost of fixing stack
+ - pop hl*nargs
+ 10*nargs
+
+ 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
+ At 192 d/s for 682411768t, speed up to 199. Hmm.
+*/
#include <stdio.h>
#include <stdlib.h>
*/
enum {
- DISABLE_DEBUG = 1
+ DISABLE_DEBUG = 0
};
static char *_z80_return[] =
static const char *aopGet (asmop * aop, int offset, bool bit16);
+static PAIR_ID
+_getTempPairId(void)
+{
+ if (IS_GB)
+ {
+ return PAIR_DE;
+ }
+ else
+ {
+ return PAIR_HL;
+ }
+}
+
+static const char *
+_getTempPairName(void)
+{
+ return _pairs[_getTempPairId()].name;
+}
+
+#if 0
+static const char *
+_getTempPairPart(int idx)
+{
+ wassertl (idx == LSB || idx == MSB16, "Invalid pair offset");
+
+ if (idx == LSB)
+ {
+ return _pairs[_getTempPairId()].l;
+ }
+ else
+ {
+ return _pairs[_getTempPairId()].h;
+ }
+}
+#endif
+
static void
_tidyUp (char *buf)
{
}
}
-static char *
-fetchLitSpecial (asmop * aop, bool negate, bool xor)
-{
- unsigned long v;
- value *val = aop->aopu.aop_lit;
-
- wassert (aop->type == AOP_LIT);
- wassert (!IS_FLOAT (val->type));
-
- v = (unsigned long) floatFromVal (val);
-
- if (xor)
- v ^= 0x8000;
- if (negate)
- v = 0-v;
- v &= 0xFFFF;
-
- tsprintf (buffer, "!immedword", v);
- return gc_strdup (buffer);
-}
-
static void
fetchLitPair (PAIR_ID pairId, asmop * left, int offset)
{
/* we need to get it byte by byte */
if (pairId == PAIR_HL && IS_GB && requiresHL (aop)) {
aopGet (aop, offset, FALSE);
- switch (aop->size) {
+ switch (aop->size - offset) {
case 1:
emit2 ("ld l,!*hl");
emit2 ("ld h,!immedbyte", 0);
break;
case 2:
+ // PENDING: Requires that you are only fetching two bytes.
+ case 4:
emit2 ("!ldahli");
emit2 ("ld h,!*hl");
emit2 ("ld l,a");
break;
default:
- emitDebug ("; WARNING: mlh woosed out. This code is invalid.");
+ wassertl (0, "Attempted to fetch too much data into HL");
+ break;
}
}
else if (IS_Z80 && aop->type == AOP_IY) {
_push (PAIR_HL);
aopPut (AOP (oper), _fReturn[0], 0);
aopPut (AOP (oper), _fReturn[1], 1);
- emit2 ("pop de");
- _G.stack.pushed -= 2;
+ _pop (PAIR_DE);
aopPut (AOP (oper), _fReturn[0], 2);
aopPut (AOP (oper), _fReturn[1], 3);
}
if (genPlusIncr (ic) == TRUE)
goto release;
- emitDebug ("; genPlusIncr failed");
+ emitDebug ("; Can't optimise plus by inc, falling back to the normal way");
size = getDataSize (IC_RESULT (ic));
if (isPair (AOP (IC_RESULT (ic))))
{
char *left, *right;
-
left = aopGetLitWordLong (AOP (IC_LEFT (ic)), 0, FALSE);
right = aopGetLitWordLong (AOP (IC_RIGHT (ic)), 0, FALSE);
- if (left && right)
+
+ if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT && AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT &&
+ left && right)
{
/* It's a pair */
/* PENDING: fix */
}
else if (size == 4)
{
- emitDebug ("; WARNING: This add is probably broken.\n");
+ // Fall through
}
}
}
/* if increment 16 bits in register */
if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
- (size == 2))
+ (size == 2)
+ )
{
- fetchPair (PAIR_HL, AOP (IC_RESULT (ic)));
+ fetchPair (_getTempPairId(), AOP (IC_RESULT (ic)));
while (icount--) {
- emit2 ("dec hl");
+ emit2 ("dec %s", _getTempPairName());
}
- aopPut (AOP (IC_RESULT (ic)), "l", LSB);
- aopPut (AOP (IC_RESULT (ic)), "h", MSB16);
+
+ commitPair (AOP (IC_RESULT (ic)), _getTempPairId());
return TRUE;
}
}
else if (size == 4)
{
+ /* Anything could be on the stack, and we can't afford
+ to setup the base pointer as that may nuke the carry.
+ */
emitDebug ("; WARNING: This sub is probably broken.\n");
}
}
ic->generated = 1;
}
+#if DISABLED
static const char *
_getPairIdName (PAIR_ID id)
{
return _pairs[id].name;
}
+#endif
/** Generic compare for > or <
*/
}
else
{
+#if 0
+ // PENDING: Doesn't work around zero
+
/* Special cases:
On the GB:
If the left or the right is a lit:
emit2 ("add hl,%s", _getPairIdName (id));
goto release;
}
+#endif
if (AOP_TYPE (right) == AOP_LIT)
{
lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
return ret;
}
+static char *
+fetchLitSpecial (asmop * aop, bool negate, bool xor)
+{
+ unsigned long v;
+ value *val = aop->aopu.aop_lit;
+
+ wassert (aop->type == AOP_LIT);
+ wassert (!IS_FLOAT (val->type));
+
+ v = (unsigned long) floatFromVal (val);
+
+ if (xor)
+ v ^= 0x8000;
+ if (negate)
+ v = 0-v;
+ v &= 0xFFFF;
+
+ tsprintf (buffer, "!immedword", v);
+ return gc_strdup (buffer);
+}
+
+
*/