]> git.sur5r.net Git - cc65/commitdiff
Generate special memcpy code if the target is less than 256 bytes in size and
authoruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Thu, 7 Jun 2012 13:30:21 +0000 (13:30 +0000)
committeruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Thu, 7 Jun 2012 13:30:21 +0000 (13:30 +0000)
located at the stack bottom.

git-svn-id: svn://svn.cc65.org/cc65/trunk@5693 b7a2c559-68d2-44c3-8de9-860c34a00d81

src/cc65/stdfunc.c

index 0e61f1fb1aac518d6a07ab2d526fd8e425c2c3fb..1490d59d0b446c3ec18c46c1706d46468338964d 100644 (file)
@@ -202,6 +202,7 @@ static void StdFunc_memcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
     ArgDesc  Arg1, Arg2, Arg3;
     unsigned ParamSize = 0;
     unsigned Label;
+    int      Offs;
 
     /* Argument #1 */
     ParseArg (&Arg1, Arg1Type);
@@ -328,7 +329,7 @@ static void StdFunc_memcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
                             !(ED_IsLocAbs (&Arg2.Expr) && Arg2.Expr.IVal < 256);
 
         /* Calculate the real stack offset */
-        int Offs = ED_GetStackOffs (&Arg1.Expr, 0);
+        Offs = ED_GetStackOffs (&Arg1.Expr, 0);
 
         /* Drop the generated code */
         RemoveCode (&Arg1.Expr.Start);
@@ -402,7 +403,7 @@ static void StdFunc_memcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
                             !(ED_IsLocAbs (&Arg1.Expr) && Arg1.Expr.IVal < 256);
 
         /* Calculate the real stack offset */
-        int Offs = ED_GetStackOffs (&Arg2.Expr, 0);
+        Offs = ED_GetStackOffs (&Arg2.Expr, 0);
 
         /* Drop the generated code */
         RemoveCode (&Arg1.Expr.Start);
@@ -460,6 +461,43 @@ static void StdFunc_memcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
          */
         *Expr = Arg1.Expr;
 
+    } else if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256   &&
+               ED_IsRVal (&Arg2.Expr) && ED_IsLocStack (&Arg2.Expr)     &&
+               (Offs = ED_GetStackOffs (&Arg2.Expr, 0)) == 0) {
+
+        /* Drop the generated code but leave the load of the first argument*/
+        RemoveCode (&Arg1.Push);
+
+        /* We need a label */
+        Label = GetLocalLabel ();
+
+        /* Generate memcpy code */
+        AddCodeLine ("sta ptr1");
+        AddCodeLine ("stx ptr1+1");
+        if (Arg3.Expr.IVal <= 127) {
+            AddCodeLine ("ldy #$%02X", (unsigned char) (Arg3.Expr.IVal - 1));
+            g_defcodelabel (Label);
+            AddCodeLine ("lda (ptr1),y");
+            AddCodeLine ("sta (sp),y");
+            AddCodeLine ("dey");
+            AddCodeLine ("bpl %s", LocalLabelName (Label));
+        } else {
+            AddCodeLine ("ldy #$00");
+            g_defcodelabel (Label);
+            AddCodeLine ("lda (ptr1),y");
+            AddCodeLine ("sta (sp),y");
+            AddCodeLine ("iny");
+            AddCodeLine ("cpy #$%02X", (unsigned char) Arg3.Expr.IVal);
+            AddCodeLine ("bne %s", LocalLabelName (Label));
+        }
+
+        /* Reload result - X hasn't changed by the code above */
+        AddCodeLine ("lda ptr1");
+
+        /* The function result is an rvalue in the primary register */
+        ED_MakeRValExpr (Expr);
+        Expr->Type = GetFuncReturn (Expr->Type);
+
     } else {
 
         /* The function result is an rvalue in the primary register */