From 03b3668528ccfa4536c21702385aabcc3593d17c Mon Sep 17 00:00:00 2001 From: spth Date: Wed, 20 Feb 2008 15:51:15 +0000 Subject: [PATCH] Fixed bugs #1596270, #1736867 git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@5028 4a8a32a2-be11-0410-ad9d-d568d2c75423 --- ChangeLog | 4 ++++ src/z80/gen.c | 59 ++++++++++++++++++++++++++++++++++++++------------- 2 files changed, 48 insertions(+), 15 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6666b199..f18af531 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2008-02-20 Philipp Klaus Krause + + * src/z80/gen.c: fixed bugs #1596270, #1736867 + 2008-02-20 Philipp Klaus Krause * src/z80/gen.c: fixed bug in register pair loading when swapping register contents, diff --git a/src/z80/gen.c b/src/z80/gen.c index 97dfd410..9e995211 100644 --- a/src/z80/gen.c +++ b/src/z80/gen.c @@ -3922,28 +3922,57 @@ genPlus (iCode * ic) setupToPreserveCarry (ic); - while (size--) + /* This is ugly, but it fixes the worst code generation bug on Z80. */ + /* Probably something similar has to be done for addition of larger numbers, too. */ + if(size == 2) { - if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC) + _moveA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE)); + emit2 ("add a,%s", aopGet (AOP (IC_RIGHT (ic)), 0, FALSE)); + if(strcmp (aopGet (AOP (IC_RESULT (ic)), 0, FALSE), aopGet (AOP (IC_LEFT (ic)), 1, FALSE))) { - _moveA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE)); - if (offset == 0) - emit2 ("add a,%s", - aopGet (AOP (IC_RIGHT (ic)), offset, FALSE)); - else - emit2 ("adc a,%s", - aopGet (AOP (IC_RIGHT (ic)), offset, FALSE)); + aopPut (AOP (IC_RESULT (ic)), "a", 0); + _moveA (aopGet (AOP (IC_LEFT (ic)), 1, FALSE)); } else { - _moveA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE)); - if (offset == 0) - emit2 ("add a,%s", - aopGet (AOP (IC_RIGHT (ic)), offset, FALSE)); + emitDebug ("; Addition result is in same register as operand of next addition."); + if(strchr (aopGet (AOP (IC_RESULT (ic)), 0, FALSE), 'c') || + strchr (aopGet (AOP (IC_RESULT (ic)), 0, FALSE), 'b') ) + { + emit2 ("push de"); + emit2 ("ld e, a"); + emit2 ("ld a, %s", aopGet (AOP (IC_LEFT (ic)), 1, FALSE)); + emit2 ("ld d, a"); + emit2 ("ld a, e"); + emit2 ("ld %s, a", aopGet (AOP (IC_RESULT (ic)), 0, FALSE)); + emit2 ("ld a, d"); + emit2 ("pop de"); + } else - emit2 ("adc a,%s", - aopGet (AOP (IC_RIGHT (ic)), offset, FALSE)); + { + emit2 ("push bc"); + emit2 ("ld c, a"); + emit2 ("ld a, %s", aopGet (AOP (IC_LEFT (ic)), 1, FALSE)); + emit2 ("ld b, a"); + emit2 ("ld a, c"); + emit2 ("ld %s, a", aopGet (AOP (IC_RESULT (ic)), 0, FALSE)); + emit2 ("ld a, b"); + emit2 ("pop bc"); + } + } + emit2 ("adc a,%s", aopGet (AOP (IC_RIGHT (ic)), 1, FALSE)); + aopPut (AOP (IC_RESULT (ic)), "a", 1); + goto release; + } + + while (size--) + { + _moveA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE)); + if (offset == 0) + emit2 ("add a,%s", aopGet (AOP (IC_RIGHT (ic)), offset, FALSE)); + else + emit2 ("adc a,%s", aopGet (AOP (IC_RIGHT (ic)), offset, FALSE)); aopPut (AOP (IC_RESULT (ic)), "a", offset++); } -- 2.30.2