* src/z80/gen.c (fetchLitPair): Changed so that it properly caches direct space...
authormichaelh <michaelh@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Mon, 3 Sep 2001 04:23:48 +0000 (04:23 +0000)
committermichaelh <michaelh@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Mon, 3 Sep 2001 04:23:48 +0000 (04:23 +0000)
* support/regression/tests/addsub.c: Added cases to cover all the +, - combinations.

* support/regression/tests/uminus.c: Added a test for the unary minus operator.

* src/z80/gen.c (genUminus): Fixed add, sub, and uminus on the gbz80 port for longs.  Had to shift some functions about to do it.

git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@1218 4a8a32a2-be11-0410-ad9d-d568d2c75423

ChangeLog
src/z80/gen.c
src/z80/gen.h
src/z80/peeph-gbz80.def
src/z80/peeph.def
support/regression/tests/addsub.c
support/regression/tests/muldiv.c
support/regression/tests/uminus.c [new file with mode: 0644]

index 9c46fc01abe44137b8ec03c17670ff7c9cf5e129..36483d0188be4c3770edb7c480a3a7a00c5039a8 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,18 @@
+2001-09-02  Michael Hope  <michaelh@juju.net.nz>
+
+       * src/z80/gen.c (fetchLitPair): Changed so that it properly caches direct space references.
+
+       * support/regression/tests/addsub.c: Added cases to cover all the +, - combinations.
+
+       * support/regression/tests/uminus.c: Added a test for the unary minus operator.
+
+       * src/z80/gen.c (genUminus): Fixed add, sub, and uminus on the gbz80 port for longs.  Had to shift some functions about to do it.
+
 2001-09-01  Michael Hope  <michaelh@juju.net.nz>
 
+       * src/z80/gen.c: Fixed up generator to pass the regresion tests, specifically fixing loads for longs, genCmp, and turned on the map file.
+       (genCmp): Fixed up genCmp for the GB with longs.
+
        * device/lib/gbz80/Makefile: Fixed up all the libraries to pass the regression tests.
 
        * support/regression/ports/host/spec.mk: Updated to compile with the new type specifiers.
index f065a37e76e2f74d4267f0b05ab92da52f16aa6c..7c15dcaa646585bf0d34ca440730f039d98b0e81 100644 (file)
@@ -180,7 +180,7 @@ static struct
   struct 
   {
     AOP_TYPE last_type;
-    const char *lit;
+    const char *base;
     int offset;
   } pairs[NUM_PAIRS];
   struct 
@@ -482,6 +482,19 @@ genPairPush (asmop * aop)
   emit2 ("push %s", getPairName (aop));
 }
 
+static void
+_push (PAIR_ID pairId)
+{
+  emit2 ("push %s", _pairs[pairId].name);
+  _G.stack.pushed += 2;
+}
+
+static void
+_pop (PAIR_ID pairId)
+{
+  emit2 ("pop %s", _pairs[pairId].name);
+  _G.stack.pushed -= 2;
+}
 
 /*-----------------------------------------------------------------*/
 /* newAsmop - creates a new asmOp                                  */
@@ -902,10 +915,17 @@ aopGetLitWordLong (asmop * aop, int offset, bool with_hash)
     case AOP_IMMD:
       /* PENDING: for re-target */
       if (with_hash)
-       tsprintf (s, "!hashedstr + %d", aop->aopu.aop_immd, offset);
+        {
+          tsprintf (s, "!hashedstr + %d", aop->aopu.aop_immd, offset);
+        }
+      else if (offset == 0)
+        {
+          tsprintf (s, "%s", aop->aopu.aop_immd);
+        }
       else
-       tsprintf (s, "%s + %d", aop->aopu.aop_immd, offset);
-
+        {
+          tsprintf (s, "%s + %d", aop->aopu.aop_immd, offset);
+        }
       return gc_strdup(s);
 
     case AOP_LIT:
@@ -994,7 +1014,7 @@ static void
 spillPair (PAIR_ID pairId)
 {
   _G.pairs[pairId].last_type = AOP_INVALID;
-  _G.pairs[pairId].lit = NULL;
+  _G.pairs[pairId].base = NULL;
 }
 
 static void
@@ -1021,10 +1041,11 @@ requiresHL (asmop * aop)
 static void
 fetchLitPair (PAIR_ID pairId, asmop * left, int offset)
 {
-  const char *l;
+  const char *l, *base;
   const char *pair = _pairs[pairId].name;
   l = aopGetLitWordLong (left, offset, FALSE);
-  wassert (l && pair);
+  base = aopGetLitWordLong (left, 0, FALSE);
+  wassert (l && pair && base);
 
   if (isPtr (pair))
     {
@@ -1032,7 +1053,7 @@ fetchLitPair (PAIR_ID pairId, asmop * left, int offset)
        {
          if (_G.pairs[pairId].last_type == left->type)
            {
-             if (_G.pairs[pairId].lit && !strcmp (_G.pairs[pairId].lit, l))
+             if (_G.pairs[pairId].base && !strcmp (_G.pairs[pairId].base, base))
                {
                  if (pairId == PAIR_HL && abs (_G.pairs[pairId].offset - offset) < 3)
                    {
@@ -1047,21 +1068,7 @@ fetchLitPair (PAIR_ID pairId, asmop * left, int offset)
            }
        }
       _G.pairs[pairId].last_type = left->type;
-      _G.pairs[pairId].lit = gc_strdup (l);
-      _G.pairs[pairId].offset = offset;
-    }
-  if (IS_GB && pairId == PAIR_DE && 0)
-    {
-      if (_G.pairs[pairId].lit && !strcmp (_G.pairs[pairId].lit, l))
-       {
-         if (abs (_G.pairs[pairId].offset - offset) < 3)
-           {
-             adjustPair (pair, &_G.pairs[pairId].offset, offset);
-             return;
-           }
-       }
-      _G.pairs[pairId].last_type = left->type;
-      _G.pairs[pairId].lit = gc_strdup (l);
+      _G.pairs[pairId].base = gc_strdup (base);
       _G.pairs[pairId].offset = offset;
     }
   /* Both a lit on the right and a true symbol on the left */
@@ -1286,6 +1293,15 @@ aopGet (asmop * aop, int offset, bool bit16)
     case AOP_LIT:
       return aopLiteral (aop->aopu.aop_lit, offset);
 
+    case AOP_SIMPLELIT:
+      {
+        unsigned long v = aop->aopu.aop_simplelit;
+        
+        v >>= (offset * 8);
+        tsprintf (s, "!immedbyte", (unsigned int) v & 0xff);
+        
+        return gc_strdup(s);
+      }
     case AOP_STR:
       aop->coff = offset;
       return aop->aopu.aop_str[offset];
@@ -1689,6 +1705,59 @@ genCpl (iCode * ic)
   freeAsmop (IC_RESULT (ic), NULL, ic);
 }
 
+static void
+_gbz80_emitAddSubLongLong (iCode *ic, asmop *left, asmop *right, bool isAdd)
+{
+  /* Logic:
+       ld de,right.lw
+       setup hl to left
+       de = hl - de
+       push flags
+       store de into result
+       pop flags
+       ld de,right.hw
+       setup hl
+       de = hl -de
+       store de into result
+  */
+  const char *first = isAdd ? "add" : "sub";
+  const char *later = isAdd ? "adc" : "sbc";
+
+  wassertl (IS_GB, "Code is only relevent to the gbz80");
+  wassertl (AOP( IC_RESULT (ic))->size == 4, "Only works for four bytes");
+
+  fetchPair (PAIR_DE, left);
+
+  emit2 ("ld a,e");
+  emit2 ("%s a,%s", first, aopGet( right, LSB, FALSE));
+  emit2 ("ld e,a");
+  emit2 ("ld a,d");
+  emit2 ("%s a,%s", later, aopGet( right, MSB16, FALSE));
+
+  _push (PAIR_AF);
+  aopPut ( AOP (IC_RESULT (ic)), "a", MSB16);
+  aopPut ( AOP (IC_RESULT (ic)), "e", LSB);
+
+  fetchPairLong (PAIR_DE, left, MSB24);
+  aopGet (right, MSB24, FALSE);
+
+  _pop (PAIR_AF);
+  emit2 ("ld a,e");
+  emit2 ("%s a,%s", later, aopGet( right, MSB24, FALSE));
+  emit2 ("ld e,a");
+  emit2 ("ld a,d");
+  emit2 ("%s a,%s", later, aopGet( right, MSB32, FALSE));
+
+  aopPut ( AOP (IC_RESULT (ic)), "a", MSB32);
+  aopPut ( AOP (IC_RESULT (ic)), "e", MSB24);
+}
+
+static void
+_gbz80_emitAddSubLong (iCode *ic, bool isAdd)
+{
+  _gbz80_emitAddSubLongLong (ic, AOP (IC_LEFT (ic)), AOP (IC_RIGHT (ic)), isAdd);
+}
+
 /*-----------------------------------------------------------------*/
 /* genUminus - unary minus code generation                         */
 /*-----------------------------------------------------------------*/
@@ -1721,6 +1790,16 @@ genUminus (iCode * ic)
       goto release;
     }
 
+  if (AOP_SIZE (IC_RESULT (ic)) == 4 && IS_GB)
+    {
+      /* Create a new asmop with value zero */
+      asmop *azero = newAsmop (AOP_SIMPLELIT);
+      azero->aopu.aop_simplelit = 0;
+      azero->size = size;
+      _gbz80_emitAddSubLongLong (ic, azero, AOP (IC_LEFT (ic)), FALSE);
+      goto release;
+    }
+
   /* otherwise subtract from zero */
   size = AOP_SIZE (IC_LEFT (ic));
   offset = 0;
@@ -1749,21 +1828,6 @@ release:
   freeAsmop (IC_RESULT (ic), NULL, ic);
 }
 
-static void
-_push (PAIR_ID pairId)
-{
-  emit2 ("push %s", _pairs[pairId].name);
-  _G.stack.pushed += 2;
-}
-
-static void
-_pop (PAIR_ID pairId)
-{
-  emit2 ("pop %s", _pairs[pairId].name);
-  _G.stack.pushed -= 2;
-}
-
-
 /*-----------------------------------------------------------------*/
 /* assignResultValue -               */
 /*-----------------------------------------------------------------*/
@@ -2857,11 +2921,15 @@ genPlus (iCode * ic)
              commitPair (AOP (IC_RESULT (ic)), PAIR_HL);
              goto release;
            }
-         else if (size == 4)
-           {
-              // Fall through
-           }
        }
+      if (size == 4)
+        {
+          /* Be paranoid on the GB with 4 byte variables due to how C
+             can be trashed by lda hl,n(sp).
+          */
+          _gbz80_emitAddSubLong (ic, TRUE);
+          goto release;
+        }
     }
 
   while (size--)
@@ -3046,14 +3114,15 @@ genMinus (iCode * ic)
              aopPut (AOP (IC_RESULT (ic)), "e", 0);
              goto release;
            }
-         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");
-           }
        }
+      if (size == 4)
+        {
+          /* Be paranoid on the GB with 4 byte variables due to how C
+             can be trashed by lda hl,n(sp).
+          */
+          _gbz80_emitAddSubLong (ic, FALSE);
+          goto release;
+        }
     }
 
   /* if literal, add a,#-lit, else normal subb */
@@ -3241,6 +3310,47 @@ genCmp (operand * left, operand * right,
          else
            emit2 ("cp %s", aopGet (AOP (right), offset, FALSE));
        }
+      else if (size == 4 && IS_GB && requiresHL(AOP(right)) && requiresHL(AOP(left)))
+        {
+          // On the Gameboy we can't afford to adjust HL as it may trash the carry.
+          // Pull left into DE and right into HL
+          aopGet (AOP(left), LSB, FALSE);
+          emit2 ("ld d,h");
+          emit2 ("ld e,l");
+          aopGet (AOP(right), LSB, FALSE);
+
+          while (size--)
+            {
+              if (size == 0 && sign)
+                {
+                  // Highest byte when signed needs the bits flipped
+                  // Save the flags
+                  emit2 ("push af");
+                  emit2 ("ld a,(de)");
+                  emit2 ("xor #0x80");
+                  emit2 ("ld e,a");
+                  emit2 ("ld a,(hl)");
+                  emit2 ("xor #0x80");
+                  emit2 ("ld d,a");
+                  emit2 ("pop af");
+                  emit2 ("ld a,e");
+                  emit2 ("%s a,d", offset == 0 ? "sub" : "sbc");
+                }
+              else
+                {
+                  emit2 ("ld a,(de)");
+                  emit2 ("%s a,(hl)", offset == 0 ? "sub" : "sbc");
+                }
+              
+              if (size != 0)
+                {
+                  emit2 ("inc hl");
+                  emit2 ("inc de");
+                }
+              offset++;
+            }
+          spillPair (PAIR_HL);
+        }
       else
        {
 #if 0
@@ -3344,12 +3454,6 @@ genCmp (operand * left, operand * right,
                  emit2 ("ld %s,a", _fTmp[1]);
                  fDidXor = TRUE;
                }
-             if (!fDidXor)
-               _clearCarry();
-           }
-         else
-           {
-             _clearCarry();
            }
          while (size--)
            {
@@ -3361,12 +3465,12 @@ genCmp (operand * left, operand * right,
              if (sign && size == 0)
                {
                  emit2 ("ld a,%s", _fTmp[0]);
-                 emit2 ("sbc a,%s", _fTmp[1]);
+                 emit2 ("%s a,%s", offset == 0 ? "sub" : "sbc", _fTmp[1]);
                }
              else
                {
                  /* Subtract through, propagating the carry */
-                 emit2 ("sbc a,%s", aopGet (AOP (right), offset++, FALSE));
+                 emit2 ("%s a,%s", offset == 0 ? "sub" : "sbc", aopGet (AOP (right), offset++, FALSE));
                }
            }
        }
@@ -4492,12 +4596,18 @@ shiftL2Left2Result (operand * left, int offl,
        emitLabel (tlbl->key + 100);
       }
 
-    emit2 ("or a,a");
     while (size--)
       {
        l = aopGet (AOP (result), offset, FALSE);
 
-       emit2 ("rl %s", l);
+        if (offset == 0)
+          {
+            emit2 ("sla %s", l);
+          }
+        else
+          {
+            emit2 ("rl %s", l);
+          }
 
         offset++;
       }
@@ -4523,34 +4633,34 @@ AccRol (int shCount)
     case 0:
       break;
     case 1:
-      emit2 ("rl a");
+      emit2 ("sla a");
       break;
     case 2:
-      emit2 ("rl a");
+      emit2 ("sla a");
       emit2 ("rl a");
       break;
     case 3:
-      emit2 ("rl a");
+      emit2 ("sla a");
       emit2 ("rl a");
       emit2 ("rl a");
       break;
     case 4:
-      emit2 ("rl a");
+      emit2 ("sla a");
       emit2 ("rl a");
       emit2 ("rl a");
       emit2 ("rl a");
       break;
     case 5:
-      emit2 ("rr a");
+      emit2 ("srl a");
       emit2 ("rr a");
       emit2 ("rr a");
       break;
     case 6:
-      emit2 ("rr a");
+      emit2 ("srl a");
       emit2 ("rr a");
       break;
     case 7:
-      emit2 ("rr a");
+      emit2 ("srl a");
       break;
     }
 }
@@ -4788,12 +4898,19 @@ genLeftShift (iCode * ic)
   emitLabel (tlbl->key + 100);
   l = aopGet (AOP (result), offset, FALSE);
 
-  emit2 ("or a,a");
-
   while (size--)
     {
-      l = aopGet (AOP (result), offset++, FALSE);
-      emit2 ("rl %s", l);
+      l = aopGet (AOP (result), offset, FALSE);
+
+      if (offset == 0)
+        {
+          emit2 ("sla %s", l);
+        }
+      else
+        {
+          emit2 ("rl %s", l);
+        }
+      offset++;
     }
   emitLabel (tlbl1->key + 100);
   emit2 ("dec a");
@@ -5441,6 +5558,28 @@ genAssign (iCode * ic)
       aopPut (AOP (result), "a", 0);
       aopPut (AOP (result), "e", 1);
     }
+  else if (size == 4 && requiresHL (AOP (right)) && requiresHL (AOP (result)) && IS_GB)
+    {
+      /* Special case - simple memcpy */
+      aopGet (AOP (right), LSB, FALSE);
+      emit2 ("ld d,h");
+      emit2 ("ld e,l");
+      aopGet (AOP (result), LSB, FALSE);
+
+      while (size--)
+        {
+          emit2 ("ld a,(de)");
+          /* Peephole will optimise this. */
+          emit2 ("ld (hl),a");
+
+          if (size != 0)
+            {
+              emit2 ("inc hl");
+              emit2 ("inc de");
+            }
+        }
+      spillPair (PAIR_HL);
+    }
   else
     {
       while (size--)
index 902e11f0b356d5e260123d6f9d4a06e5913f6b1f..57277a34f4a19fdab3c1fa2fcec2b7d018ef73df 100644 (file)
@@ -51,7 +51,9 @@ typedef enum
     /* Is in A */
     AOP_ACC,
     /* Is in H and L */
-    AOP_HLREG
+    AOP_HLREG,
+    /* Simple literal. */
+    AOP_SIMPLELIT
   }
 AOP_TYPE;
 
@@ -74,6 +76,7 @@ typedef struct asmop
         char *aop_immd;         /* if immediate others are implied */
         int aop_stk;            /* stack offset when AOP_STK */
         const char *aop_str[4]; /* just a string array containing the location */
+        unsigned long aop_simplelit; /* Just the value. */
       }
     aopu;
   }
index 36ee9c577276eabc2369c11ee368f7b300fc65b2..178a3fb4d7ea1fe35be240737a4e54789e0dcab3 100644 (file)
@@ -10,6 +10,12 @@ replace restart {
 } by {
        ld      a,(hl+)
 }
+replace restart {
+        ld      (hl),a
+        dec     hl
+} by {
+        ld      (hl-),a
+}
 replace restart {
        ld      a,[hl]
        inc     hl
index 8e5464978cdd4ed141ead177d9ce4d674b7052b6..0f9ed47ae455a42ccbac992d6c073d984e831bc0 100644 (file)
@@ -102,4 +102,9 @@ replace restart {
 } by {
         xor     a,a
 }
-        
\ No newline at end of file
+replace restart {
+        ld      e,#0x00
+        ld      d,#0x00
+} by {
+        ld      de,#0x0000
+}
index ae3ce224ea2f7e114e18eab20736e14fbb2bd90b..3c07a87f31ce0764b0e3b7e73431a2f9cb3d02d3 100644 (file)
@@ -22,6 +22,18 @@ testAdd(void)
   
   result = left+right;
   ASSERT(result == (39-120));
+
+  left = -39;
+  right = 80;
+  
+  result = left+right;
+  ASSERT(result == (-39+80));
+
+  left = -39;
+  right = -70;
+  
+  result = left+right;
+  ASSERT(result == (-39-70));
 }
 
 void 
@@ -40,4 +52,16 @@ testSub(void)
   
   result = left-right;
   ASSERT(result == (39+76));
+
+  left = -12;
+  right = 56;
+  
+  result = left-right;
+  ASSERT(result == (-12-56));
+  
+  left = -39;
+  right = -20;
+  
+  result = left-right;
+  ASSERT(result == (-39+20));
 }
index 474afd35394c502986859340acf2cb666b0af0c4..dc8bd801e1f7dbe2da63c59ad00627f59a1280a0 100644 (file)
@@ -64,6 +64,10 @@ testMul(void)
     ASSERT(i*-3 == 30);
 }
 
+void mark(void)
+{
+}
+
 void
 testDiv(void)
 {
@@ -73,6 +77,7 @@ testDiv(void)
     LOG(("i/5 == 20 = %u\n", (int)i/5));
     ASSERT(i/5 == 20);
     LOG(("i/-4 == -25 = %u\n", (int)i/-4));
+    mark();
     ASSERT(i/-4 == -25);
 
     i = -50;
diff --git a/support/regression/tests/uminus.c b/support/regression/tests/uminus.c
new file mode 100644 (file)
index 0000000..1a5732b
--- /dev/null
@@ -0,0 +1,26 @@
+/* Test unary minus
+
+    lefttype: int, char, short, long
+    resulttype: int, char, short, long
+    storage: static,
+    attr: volatile,
+ */
+#include <testfwk.h>
+
+void
+testUMinus(void)
+{
+  {storage} {attr} {lefttype} left;
+  {storage} {attr} {resulttype} result;
+
+  left = 53;
+  result = -left;
+
+  ASSERT(result == -53);
+
+  left = -76;
+  result = -left;
+  
+  ASSERT(result == 76);
+}
+