* src/z80/ralloc.c (packRegsForHLUse3): Changed to not pack into HL if anything...
authormichaelh <michaelh@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Sat, 24 Nov 2001 04:44:41 +0000 (04:44 +0000)
committermichaelh <michaelh@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Sat, 24 Nov 2001 04:44:41 +0000 (04:44 +0000)
(packRegsForHLUse3): Added packing support for send, cast, and return value from a call.

* src/z80/peeph.def: Added rules for optimising pushes of part of a pair.

* src/z80/gen.c (emitCall): Changed the stack fixup to not use HL.

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

ChangeLog
doc/choices.txt
src/z80/gen.c
src/z80/main.c
src/z80/peeph.def
src/z80/ralloc.c

index 32f70621a9a39253a3d91bd6690c5fe05141ace9..a315314b8c3c7212d1f95e9cf56bcca5f8f995bc 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2001-11-23  Michael Hope  <michaelh@juju.net.nz>
+
+       * src/z80/ralloc.c (packRegsForHLUse3): Changed to not pack into HL if anything is in direct space.
+       (packRegsForHLUse3): Added packing support for send, cast, and return value from a call.
+
+       * src/z80/peeph.def: Added rules for optimising pushes of part of a pair.
+
+       * src/z80/gen.c (emitCall): Changed the stack fixup to not use HL.
+
 2001-11-18  Michael Hope  <michaelh@juju.net.nz>
 
        * src/z80/gen.c (genCmp): Fixed compare on unsigned.
index fd6cbab859d01cca36a164247512711ee00c6bab..d6fbe90c9b05b3e43273b0616e16ccffae8c351c 100644 (file)
@@ -192,3 +192,30 @@ Pending optimisations:
         ...
         push    iTemp4
 
+Swaps:
+        ld      hl,bc           ; 8
+        ld      bc,de           ; 8
+        ld      de,hl           ; 8
+
+vs
+        push    bc             ; 11
+        ld      bc,de           ; 8
+        pop     de              ; 11
+
+Swaps 2:
+        ld      a,h
+        ld      h,b
+        ld      b,a
+        ld      a,l
+        ld      l,c
+        ld      c,aq            ; 6*4 = 24
+
+Cleaning up the arguments to a call:
+         ld     iy,#n           ; 14
+         add    iy,sp           ; 15
+         ld     sp,iy           ; 10 = 39
+
+         pop    af              ; 5/byte
+
+
+So for 8 bytes and above use the first form.
\ No newline at end of file
index 4572471a53ccc7a58b21dc5d3de29cf895285652..d2af3cd5dc735fdd44eda630b804cfb7a5ec7538 100644 (file)
@@ -2435,8 +2435,6 @@ emitCall (iCode * ic, bool ispcall)
 {
   sym_link *dtype = operandType (IC_LEFT (ic));
 
-  bitVect *rInUse = bitVectCplAnd (bitVectCopy (ic->rMask), ic->rUsed);
-
   /* if caller saves & we have not saved then */
   if (!ic->regsSaved)
     {
@@ -2581,21 +2579,23 @@ emitCall (iCode * ic, bool ispcall)
       else
        {
          spillCached ();
-         if (i > 6)
+         if (i > 8)
            {
-             emit2 ("ld hl,#%d", i);
-             emit2 ("add hl,sp");
-             emit2 ("ld sp,hl");
+             emit2 ("ld iy,#%d", i);
+             emit2 ("add iy,sp");
+             emit2 ("ld sp,iy");
            }
          else
            {
              while (i > 1)
                {
-                 emit2 ("pop hl");
+                 emit2 ("pop af");
                  i -= 2;
                }
              if (i)
-               emit2 ("inc sp");
+                {
+                  emit2 ("inc sp");
+                }
            }
        }
     }
@@ -2604,54 +2604,58 @@ emitCall (iCode * ic, bool ispcall)
 
   if (_G.stack.pushedDE) 
     {
-      bool dInUse = bitVectBitValue(rInUse, D_IDX);
-      bool eInUse = bitVectBitValue(rInUse, E_IDX);
+      bool dInRet = bitVectBitValue(ic->rUsed, D_IDX);
+      bool eInRet = bitVectBitValue(ic->rUsed, E_IDX);
 
-      if (dInUse && eInUse) 
+      if (dInRet && eInRet)
         {
-          _pop (PAIR_DE);
+          wassertl (0, "Shouldn't push DE if it's wiped out by the return");
         }
-      else if (dInUse)
+      else if (dInRet)
         {
-          _pop(PAIR_HL);
-          emit2 ("ld d,h");
+          /* Only restore E */
+          emit2 ("ld a,d");
+          _pop (PAIR_DE);
+          emit2 ("ld d,a");
         }
-      else if (eInUse)
+      else if (eInRet)
         {
-          _pop(PAIR_HL);
-          emit2 ("ld e,l");
+          /* Only restore D */
+          _pop (PAIR_AF);
+          emit2 ("ld d,a");
         }
       else
         {
-          wassertl (0, "Neither D or E were in use but it was pushed.");
+          _pop (PAIR_DE);
         }
       _G.stack.pushedDE = FALSE;
     }
   
   if (_G.stack.pushedBC) 
     {
-      bool bInUse = bitVectBitValue(rInUse, B_IDX);
-      bool cInUse = bitVectBitValue(rInUse, C_IDX);
+      bool bInRet = bitVectBitValue(ic->rUsed, B_IDX);
+      bool cInRet = bitVectBitValue(ic->rUsed, C_IDX);
 
-      // If both B and C are used in the return value, then we won't get
-      // here.
-      if (bInUse && cInUse) 
+      if (bInRet && cInRet)
         {
-          _pop (PAIR_BC);
+          wassertl (0, "Shouldn't push BC if it's wiped out by the return");
         }
-      else if (bInUse)
+      else if (bInRet)
         {
-          _pop(PAIR_HL);
-          emit2 ("ld b,h");
+          /* Only restore C */
+          emit2 ("ld a,b");
+          _pop (PAIR_BC);
+          emit2 ("ld b,a");
         }
-      else if (cInUse)
+      else if (cInRet)
         {
-          _pop(PAIR_HL);
-          emit2 ("ld c,l");
+          /* Only restore B */
+          _pop (PAIR_AF);
+          emit2 ("ld b,a");
         }
       else
         {
-          wassertl (0, "Neither B or C were in use but it was pushed.");
+          _pop (PAIR_BC);
         }
       _G.stack.pushedBC = FALSE;
     }
@@ -4220,7 +4224,9 @@ gencjneshort (operand * left, operand * right, symbol * lbl)
     }
 
   if (AOP_TYPE (right) == AOP_LIT)
-    lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
+    {
+      lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
+    }
 
   /* if the right side is a literal then anything goes */
   if (AOP_TYPE (right) == AOP_LIT &&
@@ -4345,11 +4351,9 @@ genCmpEq (iCode * ic, iCode * ifx)
       else
        {
          tlbl = newiTempLabel (NULL);
-          emitDebug(";1");
          gencjneshort (left, right, tlbl);
          if (IC_TRUE (ifx))
            {
-              emitDebug(";2");
              emit2 ("jp !tlabel", IC_TRUE (ifx)->key + 100);
              emitLabel (tlbl->key + 100);
            }
@@ -4357,7 +4361,6 @@ genCmpEq (iCode * ic, iCode * ifx)
            {
              /* PENDING: do this better */
              symbol *lbl = newiTempLabel (NULL);
-              emitDebug(";3");
              emit2 ("!shortjp !tlabel", lbl->key + 100);
              emitLabel (tlbl->key + 100);
              emit2 ("jp !tlabel", IC_FALSE (ifx)->key + 100);
@@ -6679,6 +6682,284 @@ genArrayInit (iCode * ic)
   freeAsmop (IC_LEFT(ic), NULL, ic);
 }
 
+static void
+_swap (PAIR_ID one, PAIR_ID two)
+{
+  if ((one == PAIR_DE && two == PAIR_HL) || (one == PAIR_HL && two == PAIR_DE))
+    {
+      emit2 ("ex de,hl");
+    }
+  else
+    {
+      emit2 ("ld a,%s", _pairs[one].l);
+      emit2 ("ld %s,%s", _pairs[one].l, _pairs[two].l);
+      emit2 ("ld %s,a", _pairs[two].l);
+      emit2 ("ld a,%s", _pairs[one].h);
+      emit2 ("ld %s,%s", _pairs[one].h, _pairs[two].h);
+      emit2 ("ld %s,a", _pairs[two].h);
+    }
+}
+
+/* The problem is that we may have all three pairs used and they may
+   be needed in a different order.
+
+   Note: Have ex de,hl
+
+   Combinations:
+     hl = hl           => unity, fine
+     bc = bc
+     de = de
+
+     hl = hl           hl = hl, swap de <=> bc
+     bc = de
+     de = bc
+
+     hl = bc           Worst case
+     bc = de
+     de = hl
+     
+     hl = bc           de = de, swap bc <=> hl
+     bc = hl
+     de = de
+
+     hl = de           Worst case
+     bc = hl
+     de = bc
+
+     hl = de           bc = bc, swap hl <=> de
+     bc = bc
+     de = hl
+
+   Break it down into:
+    * Any pair = pair are done last
+    * Any pair = iTemp are done last
+    * Any swaps can be done any time
+
+   A worst case:
+    push p1
+    p1 = p2
+    p2 = p3
+    pop  p3
+
+   So how do we detect the cases?
+   How about a 3x3 matrix?
+       source
+   dest x x x x
+        x x x x
+        x x x x (Fourth for iTemp/other)
+
+   First determin which mode to use by counting the number of unity and
+   iTemp assigns.
+     Three - any order
+     Two - Assign the pair first, then the rest
+     One - Swap the two, then the rest
+     Zero - Worst case.
+*/
+static void
+setupForBuiltin3 (iCode *ic, int nparams, operand **pparams)
+{
+  PAIR_ID ids[NUM_PAIRS][NUM_PAIRS];
+  PAIR_ID dest[3] = {
+    PAIR_BC, PAIR_HL, PAIR_DE
+  };
+  int i, j, nunity = 0;
+  memset (ids, PAIR_INVALID, sizeof (ids));
+
+  /* Sanity checks */
+  wassert (nparams == 3);
+
+  /* First save everything that needs to be saved. */
+  _saveRegsForCall (ic, 0);
+
+  /* Loading HL first means that DE is always fine. */
+  for (i = 0; i < nparams; i++)
+    {
+      aopOp (pparams[i], ic, FALSE, FALSE);
+      ids[dest[i]][getPairId (AOP (pparams[i]))] = TRUE;
+    }
+
+  /* Count the number of unity or iTemp assigns. */
+  for (i = 0; i < 3; i++) 
+    {
+      if (ids[dest[i]][dest[i]] == TRUE || ids[dest[i]][PAIR_INVALID] == TRUE)
+        {
+          nunity++;
+        }
+    }
+
+  if (nunity == 3)
+    {
+      /* Any order, fall through. */
+    }
+  else if (nunity == 2)
+    {
+      /* One is assigned.  Pull it out and assign. */
+      for (i = 0; i < 3; i++)
+        {
+          for (j = 0; j < NUM_PAIRS; j++)
+            {
+              if (ids[dest[i]][j] == TRUE)
+                {
+                  /* Found it.  See if it's the right one. */
+                  if (j == PAIR_INVALID || j == dest[i])
+                    {
+                      /* Keep looking. */
+                    }
+                  else
+                    {
+                      fetchPair(dest[i], AOP (pparams[i]));
+                      goto done;
+                    }
+                }
+            }
+        }
+    }
+  else if (nunity == 1)
+    {
+      /* Find the pairs to swap. */
+      for (i = 0; i < 3; i++)
+        {
+          for (j = 0; j < NUM_PAIRS; j++)
+            {
+              if (ids[dest[i]][j] == TRUE)
+                {
+                  if (j == PAIR_INVALID || j == dest[i])
+                    {
+                      /* Keep looking. */
+                    }
+                  else
+                    {
+                      _swap (j, dest[i]);
+                      goto done;
+                    }
+                }
+            }
+        }
+    }
+  else
+    {
+      int next = getPairId (AOP (pparams[0]));
+      emit2 ("push %s", _pairs[next].name);
+
+      if (next == dest[1])
+        {
+          fetchPair (dest[1], AOP (pparams[1]));
+          fetchPair (dest[2], AOP (pparams[2]));
+        }
+      else
+        {
+          fetchPair (dest[2], AOP (pparams[2]));
+          fetchPair (dest[1], AOP (pparams[1]));
+        }
+      emit2 ("pop %s", _pairs[dest[0]].name);
+    }
+ done:
+  /* Finally pull out all of the iTemps */
+  for (i = 0; i < 3; i++)
+    {
+      if (ids[dest[i]][PAIR_INVALID] == 1)
+        {
+          fetchPair (dest[i], AOP (pparams[i]));
+        }
+    }
+}
+
+static void
+genBuiltInStrcpy (iCode *ic, int nParams, operand **pparams)
+{
+  operand *from, *to;
+  symbol *label;
+  bool deInUse;
+
+  wassertl (nParams == 2, "Built-in strcpy must have two parameters");
+  to = pparams[0];
+  from = pparams[1];
+
+  deInUse = bitVectBitValue (ic->rMask, D_IDX) || bitVectBitValue(ic->rMask, E_IDX);
+
+  setupForBuiltin3 (ic, nParams, pparams);
+
+  label = newiTempLabel(NULL);
+
+  emitLabel (label->key);
+  emit2 ("ld a,(hl)");
+  emit2 ("ldi");
+  emit2 ("or a");
+  emit2 ("!shortjp nz,!tlabel ; 1", label->key);
+
+  freeAsmop (from, NULL, ic->next);
+  freeAsmop (to, NULL, ic);
+}
+
+static void
+genBuiltInMemcpy (iCode *ic, int nParams, operand **pparams)
+{
+  operand *from, *to, *count;
+  symbol *label;
+  bool deInUse;
+  iCode *pcall;
+
+  wassertl (nParams == 3, "Built-in memcpy must have two parameters");
+  to = pparams[2];
+  from = pparams[1];
+  count = pparams[0];
+
+  deInUse = bitVectBitValue (ic->rMask, D_IDX) || bitVectBitValue(ic->rMask, E_IDX);
+
+  setupForBuiltin3 (ic, nParams, pparams);
+
+  emit2 ("ldir");
+
+  freeAsmop (count, NULL, ic->next->next);
+  freeAsmop (from, NULL, ic);
+
+  _restoreRegsAfterCall();
+
+  /* if we need assign a result value */
+  if ((IS_ITEMP (IC_RESULT (ic)) &&
+       (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
+       OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
+      IS_TRUE_SYMOP (IC_RESULT (ic)))
+    {
+      aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
+      movLeft2ResultLong (to, 0, IC_RESULT (ic), 0, 0, 2);
+      freeAsmop (IC_RESULT (ic), NULL, ic);
+    }
+
+  freeAsmop (to, NULL, ic->next);
+}
+
+/*-----------------------------------------------------------------*/
+/* genBuiltIn - calls the appropriate function to  generating code */
+/* for a built in function                                        */
+/*-----------------------------------------------------------------*/
+static void genBuiltIn (iCode *ic)
+{
+    operand *bi_parms[MAX_BUILTIN_ARGS];
+    int nbi_parms;
+    iCode *bi_iCode;
+    symbol *bif;
+
+    /* get all the arguments for a built in function */
+    bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
+
+    /* which function is it */
+    bif = OP_SYMBOL(IC_LEFT(bi_iCode));
+
+    if (strcmp(bif->name,"__builtin_strcpy")==0) 
+      {
+       genBuiltInStrcpy(bi_iCode, nbi_parms, bi_parms);
+      } 
+    else if (strcmp(bif->name,"__builtin_memcpy")==0) 
+      {
+       genBuiltInMemcpy(bi_iCode, nbi_parms, bi_parms);
+      } 
+    else 
+      {
+       wassertl (0, "Unknown builtin function encountered");
+      }
+}
+
 /*-----------------------------------------------------------------*/
 /* genZ80Code - generate code for Z80 based controllers            */
 /*-----------------------------------------------------------------*/
@@ -6946,8 +7227,16 @@ genZ80Code (iCode * lic)
          break;
 
        case SEND:
-         emitDebug ("; addSet");
-         addSet (&_G.sendSet, ic);
+         if (ic->builtinSEND)
+            {
+              emitDebug ("; genBuiltIn");
+              genBuiltIn(ic);
+            }
+          else
+            {
+              emitDebug ("; addSet");
+              addSet (&_G.sendSet, ic);
+            }
          break;
 
        case ARRAYINIT:
index 8622ae90a9291e367df25aa93484fb954b4009c9..0f9f5a81221f7b90582c0a1d4e6632244c0e74b3 100644 (file)
@@ -71,6 +71,14 @@ extern PORT z80_port;
 
 #include "mappings.i"
 
+static builtins _z80_builtins[] = {
+  /* Disabled for now.
+    { "__builtin_strcpy", "v", 2, {"cg*", "cg*" } },
+    { "__builtin_memcpy", "cg*", 3, {"cg*", "cg*", "ui" } },
+  */
+    { NULL , NULL,0, {NULL}}
+};    
+
 static void
 _z80_init (void)
 {
@@ -383,7 +391,7 @@ _getRegName (struct regs *reg)
     {
       return reg->name;
     }
-  assert (0);
+  //  assert (0);
   return "err";
 }
 
@@ -513,7 +521,7 @@ PORT z80_port =
   0,                           /* leave == */
   TRUE,                         /* Array initializer support. */       
   0,                            /* no CSE cost estimation yet */
-  NULL,                        /* no builtin functions */
+  _z80_builtins,               /* no builtin functions */
   PORT_MAGIC
 };
 
@@ -597,6 +605,6 @@ PORT gbz80_port =
   0,                           /* leave == */
   TRUE,                         /* Array initializer support. */
   0,                            /* no CSE cost estimation yet */
-  NULL,                        /* no builtin functions */
+  NULL,                                /* no builtin functions */
   PORT_MAGIC
 };
index a00fd659c13633cb4d20a6532b012532a47ff28c..fdf65c5fd6a418949ae6b6dc203a9a170b1eae69 100644 (file)
@@ -142,3 +142,39 @@ replace {
 } by {
         and     a,#%1
 }
+replace {
+       ld      b,l
+       ld      a,b
+       pop     bc
+       ld      b,a
+} by {
+       ld      a,l
+       pop     bc
+       ld      b,a
+}
+replace {
+       ld      d,l
+       ld      a,d
+       pop     de
+       ld      d,a
+} by {
+       ld      a,l
+       pop     de
+       ld      d,a
+}
+replace {
+       ld      a,b
+       push    af
+       inc     sp
+} by {
+        push    bc
+        inc     sp
+}
+replace {
+       ld      a,d
+       push    af
+       inc     sp
+} by {
+        push    de
+        inc     sp
+}
index 320fa781dbc2e92a43dd1fa64855541547768301..f6265e4639ef60838e72201dcd4a296b4400151b 100644 (file)
@@ -2128,7 +2128,7 @@ packRegsForHLUse3 (iCode * lic, operand * op, eBBlock * ebp)
   if (bitVectnBitsOn (OP_DEFS (op)) > 1)
     return NULL;
 
-  if (getSize (operandType (op)) != 2)
+  if (getSize (operandType (op)) > 2)
     return NULL;
 
   /* And this is the definition */
@@ -2174,6 +2174,18 @@ packRegsForHLUse3 (iCode * lic, operand * op, eBBlock * ebp)
             continue;
         }
 
+      if (IC_RESULT(ic) && IS_SYMOP(IC_RESULT(ic))
+          && isOperandInDirSpace (IC_RESULT (ic)))
+        return NULL;
+
+      if (IC_LEFT(ic) && IS_SYMOP(IC_LEFT(ic))
+          && isOperandInDirSpace (IC_LEFT (ic)))
+        return NULL;
+
+      if (IC_RIGHT(ic) && IS_SYMOP(IC_RIGHT(ic))
+          && isOperandInDirSpace (IC_RIGHT (ic)))
+        return NULL;
+
       /* Handle the non left/right/result ones first */
       if (ic->op == IFX)
         continue;
@@ -2183,9 +2195,18 @@ packRegsForHLUse3 (iCode * lic, operand * op, eBBlock * ebp)
       if (SKIP_IC2(ic))
         continue;
 
+      if (ic->op == CAST)
+        continue;
+
       if (ic->op == IPUSH && isOperandEqual (op, IC_LEFT (ic)))
         continue;
 
+      if (ic->op == SEND && isOperandEqual (op, IC_LEFT (ic)))
+        continue;
+
+      if (ic->op == CALL && isOperandEqual (op, IC_RESULT (ic)))
+        continue;
+
       if ((ic->op == '=' && !POINTER_SET(ic)) ||
           ic->op == UNARYMINUS ||
           ic->op == '+' ||