]> git.sur5r.net Git - cc65/blobdiff - src/cc65/codegen.c
Small but significant shift optimization
[cc65] / src / cc65 / codegen.c
index 029525a9433bae6bf75ea2ff2876d839a2515459..40dcd46ab3a48b63f8e390835d233d0fb7727d0c 100644 (file)
@@ -6,7 +6,7 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 1998-2001 Ullrich von Bassewitz                                       */
+/* (C) 1998-2002 Ullrich von Bassewitz                                       */
 /*               Wacholderweg 14                                             */
 /*               D-70597 Stuttgart                                           */
 /* EMail:        uz@cc65.org                                                 */
@@ -96,31 +96,39 @@ static void CheckLocalOffs (unsigned Offs)
 
 
 
-static char* GetLabelName (unsigned flags, unsigned long label, long offs)
+static const char* GetLabelName (unsigned Flags, unsigned long Label, long Offs)
 {
-    static char lbuf [256];            /* Label name */
+    static char Buf [256];             /* Label name */
 
     /* Create the correct label name */
-    switch (flags & CF_ADDRMASK) {
+    switch (Flags & CF_ADDRMASK) {
 
        case CF_STATIC:
                    /* Static memory cell */
-           xsprintf (lbuf, sizeof (lbuf), "%s%+ld", LocalLabelName (label), offs);
+           if (Offs) {
+               xsprintf (Buf, sizeof (Buf), "%s%+ld", LocalLabelName (Label), Offs);
+           } else {
+                       xsprintf (Buf, sizeof (Buf), "%s", LocalLabelName (Label));
+           }
            break;
 
        case CF_EXTERNAL:
            /* External label */
-           xsprintf (lbuf, sizeof (lbuf), "_%s%+ld", (char*) label, offs);
+           if (Offs) {
+               xsprintf (Buf, sizeof (Buf), "_%s%+ld", (char*) Label, Offs);
+           } else {
+               xsprintf (Buf, sizeof (Buf), "_%s", (char*) Label);
+           }
            break;
 
        case CF_ABSOLUTE:
            /* Absolute address */
-           xsprintf (lbuf, sizeof (lbuf), "$%04X", (unsigned)((label+offs) & 0xFFFF));
+           xsprintf (Buf, sizeof (Buf), "$%04X", (int)((Label+Offs) & 0xFFFF));
            break;
 
        case CF_REGVAR:
            /* Variable in register bank */
-           xsprintf (lbuf, sizeof (lbuf), "regbank+%u", (unsigned)((label+offs) & 0xFFFF));
+           xsprintf (Buf, sizeof (Buf), "regbank+%u", (unsigned)((Label+Offs) & 0xFFFF));
            break;
 
        default:
@@ -128,13 +136,13 @@ static char* GetLabelName (unsigned flags, unsigned long label, long offs)
     }
 
     /* Return a pointer to the static buffer */
-    return lbuf;
+    return Buf;
 }
 
 
 
 /*****************************************************************************/
-/*                           Pre- and postamble                             */
+/*                           Pre- and postamble                             */
 /*****************************************************************************/
 
 
@@ -442,7 +450,7 @@ void g_leave (void)
 {
     /* How many bytes of locals do we have to drop? */
     int k = -oursp;
-
+                                  
     /* If we didn't have a variable argument list, don't call leave */
     if (funcargs >= 0) {
 
@@ -590,25 +598,25 @@ void g_getimmed (unsigned Flags, unsigned long Val, long Offs)
                break;
 
            case CF_LONG:
-               /* Split the value into 4 bytes */
-               B1 = (unsigned char) (Val >>  0);
-               B2 = (unsigned char) (Val >>  8);
-               B3 = (unsigned char) (Val >> 16);
-               B4 = (unsigned char) (Val >> 24);
-
-               /* Remember which bytes are done */
-               Done = 0;
-
-               /* Load the value */
-               AddCodeLine ("ldx #$%02X", B2);
-               Done |= 0x02;
-               if (B2 == B3) {
-                   AddCodeLine ("stx sreg");
-                   Done |= 0x04;
-               }
-               if (B2 == B4) {
-                   AddCodeLine ("stx sreg+1");
-                   Done |= 0x08;
+               /* Split the value into 4 bytes */
+               B1 = (unsigned char) (Val >>  0);
+               B2 = (unsigned char) (Val >>  8);
+               B3 = (unsigned char) (Val >> 16);
+               B4 = (unsigned char) (Val >> 24);
+
+               /* Remember which bytes are done */
+               Done = 0;
+
+               /* Load the value */
+               AddCodeLine ("ldx #$%02X", B2);
+               Done |= 0x02;
+               if (B2 == B3) {
+                   AddCodeLine ("stx sreg");
+                   Done |= 0x04;
+               }
+               if (B2 == B4) {
+                   AddCodeLine ("stx sreg+1");
+                   Done |= 0x08;
                }
                if ((Done & 0x04) == 0 && B1 != B3) {
                    AddCodeLine ("lda #$%02X", B3);
@@ -656,7 +664,7 @@ void g_getstatic (unsigned flags, unsigned long label, long offs)
 /* Fetch an static memory cell into the primary register */
 {
     /* Create the correct label name */
-    char* lbuf = GetLabelName (flags, label, offs);
+    const char* lbuf = GetLabelName (flags, label, offs);
 
     /* Check the size and generate the correct load operation */
     switch (flags & CF_TYPE) {
@@ -905,7 +913,7 @@ void g_putstatic (unsigned flags, unsigned long label, long offs)
 /* Store the primary register into the specified static memory cell */
 {
     /* Create the correct label name */
-    char* lbuf = GetLabelName (flags, label, offs);
+    const char* lbuf = GetLabelName (flags, label, offs);
 
     /* Check the size and generate the correct store operation */
     switch (flags & CF_TYPE) {
@@ -1438,7 +1446,7 @@ void g_addstatic (unsigned flags, unsigned long label, long offs)
     unsigned L;
 
     /* Create the correct label name */
-    char* lbuf = GetLabelName (flags, label, offs);
+    const char* lbuf = GetLabelName (flags, label, offs);
 
     switch (flags & CF_TYPE) {
 
@@ -1487,7 +1495,7 @@ void g_addeqstatic (unsigned flags, unsigned long label, long offs,
 /* Emit += for a static variable */
 {
     /* Create the correct label name */
-    char* lbuf = GetLabelName (flags, label, offs);
+    const char* lbuf = GetLabelName (flags, label, offs);
 
     /* Check the size and determine operation */
     switch (flags & CF_TYPE) {
@@ -1566,7 +1574,7 @@ void g_addeqstatic (unsigned flags, unsigned long label, long offs,
                if (val < 0x100) {
                    AddCodeLine ("ldy #<(%s)", lbuf);
                    AddCodeLine ("sty ptr1");
-                   AddCodeLine ("ldy #>(%s+1)", lbuf);
+                   AddCodeLine ("ldy #>(%s)", lbuf);
                    if (val == 1) {
                        AddCodeLine ("jsr laddeq1");
                    } else {
@@ -1581,7 +1589,7 @@ void g_addeqstatic (unsigned flags, unsigned long label, long offs,
            } else {
                AddCodeLine ("ldy #<(%s)", lbuf);
                AddCodeLine ("sty ptr1");
-               AddCodeLine ("ldy #>(%s+1)", lbuf);
+               AddCodeLine ("ldy #>(%s)", lbuf);
                AddCodeLine ("jsr laddeq");
            }
                    break;
@@ -1730,7 +1738,7 @@ void g_subeqstatic (unsigned flags, unsigned long label, long offs,
 /* Emit -= for a static variable */
 {
     /* Create the correct label name */
-    char* lbuf = GetLabelName (flags, label, offs);
+    const char* lbuf = GetLabelName (flags, label, offs);
 
     /* Check the size and determine operation */
     switch (flags & CF_TYPE) {
@@ -1801,7 +1809,7 @@ void g_subeqstatic (unsigned flags, unsigned long label, long offs,
                if (val < 0x100) {
                    AddCodeLine ("ldy #<(%s)", lbuf);
                    AddCodeLine ("sty ptr1");
-                   AddCodeLine ("ldy #>(%s+1)", lbuf);
+                   AddCodeLine ("ldy #>(%s)", lbuf);
                    AddCodeLine ("lda #$%02X", (unsigned char)val);
                    AddCodeLine ("jsr lsubeqa");
                } else {
@@ -1812,7 +1820,7 @@ void g_subeqstatic (unsigned flags, unsigned long label, long offs,
            } else {
                AddCodeLine ("ldy #<(%s)", lbuf);
                AddCodeLine ("sty ptr1");
-               AddCodeLine ("ldy #>(%s+1)", lbuf);
+               AddCodeLine ("ldy #>(%s)", lbuf);
                AddCodeLine ("jsr lsubeq");
                    }
                    break;
@@ -1983,7 +1991,7 @@ void g_addaddr_static (unsigned flags, unsigned long label, long offs)
 /* Add the address of a static variable to ax */
 {
     /* Create the correct label name */
-    char* lbuf = GetLabelName (flags, label, offs);
+    const char* lbuf = GetLabelName (flags, label, offs);
 
     /* Add the address to the current ax value */
     AddCodeLine ("clc");
@@ -3485,7 +3493,7 @@ void g_le (unsigned flags, unsigned long val)
                        }
                    } else {
                        /* Signed compare */
-                       if (val < 0x7F) {
+                       if ((long) val < 0x7F) {
                            /* Use < instead of <= because the former gives
                             * better code on the 6502 than the latter.
                             */
@@ -3515,7 +3523,7 @@ void g_le (unsigned flags, unsigned long val)
                    }
                } else {
                    /* Signed compare */
-                   if (val < 0x7FFF) {
+                   if ((long) val < 0x7FFF) {
                        g_lt (flags, val+1);
                    } else {
                        /* Always true */
@@ -3540,7 +3548,7 @@ void g_le (unsigned flags, unsigned long val)
                    }
                } else {
                    /* Signed compare */
-                   if (val < 0x7FFFFFFF) {
+                   if ((long) val < 0x7FFFFFFF) {
                        g_lt (flags, val+1);
                    } else {
                        /* Always true */
@@ -3571,7 +3579,7 @@ void g_gt (unsigned flags, unsigned long val)
 /* Test for greater than */
 {
     static char* ops [12] = {
-       "tosgt00",      "tosgta0",      "tosgtax",
+       "tosgt00",      "tosgta0",      "tosgtax",
        "tosugt00",     "tosugta0",     "tosugtax",
        0,              0,              "tosgteax",
        0,              0,              "tosugteax",
@@ -3606,7 +3614,7 @@ void g_gt (unsigned flags, unsigned long val)
                            AddCodeLine ("jsr return0");
                        }
                    } else {
-                       if (val < 0x7F) {
+                       if ((long) val < 0x7F) {
                            /* Use >= instead of > because the former gives
                             * better code on the 6502 than the latter.
                             */
@@ -3642,7 +3650,7 @@ void g_gt (unsigned flags, unsigned long val)
                    }
                        } else {
                    /* Signed compare */
-                   if (val < 0x7FFF) {
+                   if ((long) val < 0x7FFF) {
                        g_ge (flags, val+1);
                    } else {
                        /* Never true */
@@ -3673,7 +3681,7 @@ void g_gt (unsigned flags, unsigned long val)
                    }
                        } else {
                    /* Signed compare */
-                   if (val < 0x7FFFFFFF) {
+                   if ((long) val < 0x7FFFFFFF) {
                        g_ge (flags, val+1);
                    } else {
                        /* Never true */
@@ -3905,6 +3913,65 @@ void g_zerobytes (unsigned n)
 
 
 
+void g_initauto (unsigned Label, unsigned Size)
+/* Initialize a local variable at stack offset zero from static data */
+{
+    unsigned CodeLabel = GetLocalLabel ();
+
+    CheckLocalOffs (Size);
+    if (Size <= 128) {
+        ldyconst (Size-1);
+       g_defcodelabel (CodeLabel);
+        AddCodeLine ("lda %s,y", GetLabelName (CF_STATIC, Label, 0));
+        AddCodeLine ("sta (sp),y");
+        AddCodeLine ("dey");
+        AddCodeLine ("bpl %s", LocalLabelName (CodeLabel));
+    } else if (Size <= 256) {
+        ldyconst (0);
+       g_defcodelabel (CodeLabel);
+        AddCodeLine ("lda %s,y", GetLabelName (CF_STATIC, Label, 0));
+        AddCodeLine ("sta (sp),y");
+        AddCodeLine ("iny");
+        AddCodeLine ("cpy #$%02X", (unsigned char) Size);
+        AddCodeLine ("bne %s", LocalLabelName (CodeLabel));
+    }
+}
+
+
+
+void g_initstatic (unsigned InitLabel, unsigned VarLabel, unsigned Size)
+/* Initialize a static local variable from static initialization data */
+{
+    if (Size <= 128) {
+        unsigned CodeLabel = GetLocalLabel ();
+        ldyconst (Size-1);
+        g_defcodelabel (CodeLabel);
+        AddCodeLine ("lda %s,y", GetLabelName (CF_STATIC, InitLabel, 0));
+        AddCodeLine ("sta %s,y", GetLabelName (CF_STATIC, VarLabel, 0));
+        AddCodeLine ("dey");
+        AddCodeLine ("bpl %s", LocalLabelName (CodeLabel));
+    } else if (Size <= 256) {
+        unsigned CodeLabel = GetLocalLabel ();
+        ldyconst (0);
+       g_defcodelabel (CodeLabel);
+        AddCodeLine ("lda %s,y", GetLabelName (CF_STATIC, InitLabel, 0));
+        AddCodeLine ("sta %s,y", GetLabelName (CF_STATIC, VarLabel, 0));
+        AddCodeLine ("iny");
+        AddCodeLine ("cpy #$%02X", (unsigned char) Size);
+        AddCodeLine ("bne %s", LocalLabelName (CodeLabel));
+    } else {
+        /* Use the easy way here: memcpy */
+        g_getimmed (CF_STATIC, VarLabel, 0);
+        AddCodeLine ("jsr pushax");
+        g_getimmed (CF_STATIC, InitLabel, 0);
+        AddCodeLine ("jsr pushax");
+        g_getimmed (CF_INT | CF_UNSIGNED | CF_CONST, Size, 0);
+        AddCodeLine ("jsr %s", GetLabelName (CF_EXTERNAL, (unsigned long) "memcpy", 0));
+    }
+}
+
+
+
 /*****************************************************************************/
 /*                                    Switch statement                              */
 /*****************************************************************************/
@@ -4013,7 +4080,7 @@ void g_strlen (unsigned flags, unsigned long val, long offs)
     if (flags & CF_CONST) {
 
        /* The address of the string is constant. Create the correct label name */
-       char* lbuf = GetLabelName (flags, val, offs);
+       const char* lbuf = GetLabelName (flags, val, offs);
 
        /* Generate the strlen code */
        AddCodeLine ("ldy #$FF");