X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Fz80%2Fgen.c;h=f957a6ac9ab98aa2655727e6c1e92542efa56a10;hb=2004a3562e7ee5bfc7b62ec0c843cea8d5f01aaf;hp=697c3e09a5672f524c1a6dd40eef05448df55c9d;hpb=193aa0c8689791ae7d723d428ebd84e3d06fe7fd;p=fw%2Fsdcc diff --git a/src/z80/gen.c b/src/z80/gen.c index 697c3e09..f957a6ac 100644 --- a/src/z80/gen.c +++ b/src/z80/gen.c @@ -1508,8 +1508,18 @@ fetchPairLong (PAIR_ID pairId, asmop * aop, iCode *ic, int offset) } else { - emit2 ("ld %s,%s", _pairs[pairId].l, aopGet (aop, offset, FALSE)); - emit2 ("ld %s,%s", _pairs[pairId].h, aopGet (aop, offset + 1, FALSE)); + /* Swapping register contents within register pair */ + if(!strcmp(aopGet (aop, offset, FALSE), _pairs[pairId].h)) + { + emit2 ("ld a,%s",aopGet (aop, offset + 1, FALSE)); + emit2 ("ld %s,%s", _pairs[pairId].l, aopGet (aop, offset, FALSE)); + emit2 ("ld %s,a", _pairs[pairId].h); + } + 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) @@ -3912,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++); } @@ -4192,7 +4231,9 @@ genMult (iCode * ic) _G.stack.pushedDE = TRUE; } - if ( AOP_SIZE (IC_LEFT (ic)) == 1 && !SPEC_USIGN (getSpec (operandType ( IC_LEFT (ic))))) + if (byteResult) + emit2 ("ld a,%s", aopGet (AOP (IC_LEFT (ic)), LSB, FALSE)); + else if ( AOP_SIZE (IC_LEFT (ic)) == 1 && !SPEC_USIGN (getSpec (operandType ( IC_LEFT (ic))))) { emit2 ("ld e,%s", aopGet (AOP (IC_LEFT (ic)), LSB, FALSE)); if (!byteResult) @@ -4210,25 +4251,33 @@ genMult (iCode * ic) i = val; - /* Fully unroled version of mul.s. Not the most efficient. - */ for (count = 0; count < 16; count++) { if (count != 0 && active) { - emit2 ("add hl,hl"); + if (byteResult) + emit2 ("add a,a"); + else + emit2 ("add hl,hl"); } if (i & 0x8000U) { if (active == FALSE) { - emit2 ("ld l,e"); - if (!byteResult) - emit2 ("ld h,d"); + if (byteResult) + emit2("ld e,a"); + else + { + emit2 ("ld l,e"); + emit2 ("ld h,d"); + } } else { - emit2 ("add hl,de"); + if (byteResult) + emit2 ("add a,e"); + else + emit2 ("add hl,de"); } active = TRUE; } @@ -4244,7 +4293,7 @@ genMult (iCode * ic) } if (byteResult) - aopPut (AOP (IC_RESULT (ic)), _pairs[PAIR_HL].l, 0); + aopPut (AOP (IC_RESULT (ic)), "a", 0); else commitPair ( AOP (IC_RESULT (ic)), PAIR_HL); @@ -6010,13 +6059,25 @@ shiftL1Left2Result (operand * left, int offl, operand * result, int offr, int shCount) { const char *l; - l = aopGet (AOP (left), offl, FALSE); - _moveA (l); - /* shift left accumulator */ - AccLsh (shCount); - aopPut (AOP (result), "a", offr); -} + /* If operand and result are the same we can shift in place. + However shifting in acc using add is cheaper than shifting + in place using sla; when shifting by more than 2 shifting in + acc is worth the additional effort for loading from/to acc. */ + if (sameRegs (AOP (left), AOP (result)) && shCount <= 2 && offr == offl) + { + while (shCount--) + emit2 ("sla %s", aopGet (AOP (result), 0, FALSE)); + } + else + { + l = aopGet (AOP (left), offl, FALSE); + _moveA (l); + /* shift left accumulator */ + AccLsh (shCount); + aopPut (AOP (result), "a", offr); + } +} /*-----------------------------------------------------------------*/ /* genlshTwo - left shift two bytes by known amount */