]> git.sur5r.net Git - cc65/commitdiff
Working on the new backend
authorcuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Tue, 15 May 2001 19:42:17 +0000 (19:42 +0000)
committercuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Tue, 15 May 2001 19:42:17 +0000 (19:42 +0000)
git-svn-id: svn://svn.cc65.org/cc65/trunk@724 b7a2c559-68d2-44c3-8de9-860c34a00d81

src/cc65/codeent.c
src/cc65/codegen.c
src/cc65/codeinfo.c
src/cc65/codeinfo.h
src/cc65/codeopt.c
src/cc65/codeseg.c
src/cc65/codeseg.h
src/cc65/coptind.c
src/cc65/coptind.h

index 2a0c6164f30434fadad8ce9aff3e30b296c38110..14e9a539d4a9e1b1b3eec54b29a5a13be28a40f3 100644 (file)
@@ -409,8 +409,6 @@ void OutputCodeEntry (const CodeEntry* E, FILE* F)
                                  (E->Chg & REG_Y)? 'Y' : '_');
 //    }
 
-    /* Terminate the line */
-    fprintf (F, "\n");
 }
 
 
index 898ce17fb5a6f89b8fc65b8e09bc2788055cb2ca..1cafa0c2858ec35810f279cb8bffb412122d8e3e 100644 (file)
@@ -619,9 +619,10 @@ void g_getstatic (unsigned flags, unsigned long label, unsigned offs)
                AddCodeLine ("lda %s", lbuf);   /* load A from the label */
                if (!(flags & CF_UNSIGNED)) {
                    /* Must sign extend */
-                   AddCodeLine ("bpl *+3");
+                   unsigned L = GetLocalLabel ();
+                   AddCodeLine ("bpl %s", LocalLabelName (L));
                    AddCodeLine ("dex");
-                   AddCodeHint ("x:!");                /* X is invalid now */
+                   g_defcodelabel (L);
                }
            }
            break;
@@ -684,9 +685,10 @@ void g_getlocal (unsigned flags, int offs)
                    AddCodeLine ("lda (sp),y");
                }
                if ((flags & CF_UNSIGNED) == 0) {
-                   AddCodeLine ("bpl *+3");
+                   unsigned L = GetLocalLabel();
+                   AddCodeLine ("bpl %s", LocalLabelName (L));
                    AddCodeLine ("dex");
-                   AddCodeHint ("x:!");        /* X is invalid now */
+                   g_defcodelabel (L);
                }
            }
            break;
@@ -824,22 +826,22 @@ void g_leasp (int offs)
                    ldaconst (offs);                    /* Load A with offset value */
                    AddCodeLine ("jsr leaasp"); /* Load effective address */
                } else {
+           unsigned L = GetLocalLabel ();
                    if (CPU == CPU_65C02 && offs == 1) {
                        AddCodeLine ("lda sp");
                        AddCodeLine ("ldx sp+1");
                        AddCodeLine ("ina");
-                       AddCodeLine ("bne *+3");
+                       AddCodeLine ("bne %s", LocalLabelName (L));
                        AddCodeLine ("inx");
-                       AddCodeHint ("x:!");            /* Invalidate X */
                    } else {
                        ldaconst (offs);
                        AddCodeLine ("clc");
                        AddCodeLine ("ldx sp+1");
                        AddCodeLine ("adc sp");
-                       AddCodeLine ("bcc *+3");
+                       AddCodeLine ("bcc %s", LocalLabelName (L));
                        AddCodeLine ("inx");
-                       AddCodeHint ("x:!");            /* Invalidate X */
                    }
+           g_defcodelabel (L);
                }
     }
 }
@@ -873,12 +875,13 @@ void g_leavariadic (int Offs)
 
     /* Add the value of the stackpointer */
     if (CodeSizeFactor > 250) {
+       unsigned L = GetLocalLabel();
                AddCodeLine ("ldx sp+1");
                AddCodeLine ("clc");
                AddCodeLine ("adc sp");
-               AddCodeLine ("bcc *+3");
+               AddCodeLine ("bcc %s", LocalLabelName (L));
                AddCodeLine ("inx");
-               AddCodeHint ("x:!");            /* Invalidate X */
+       g_defcodelabel (L);
     } else {
                AddCodeLine ("jsr leaasp");
     }
@@ -1421,6 +1424,8 @@ void g_scale (unsigned flags, long val)
 void g_addlocal (unsigned flags, int offs)
 /* Add a local variable to ax */
 {
+    unsigned L;
+
     /* Correct the offset and check it */
     offs -= oursp;
     CheckLocalOffs (offs);
@@ -1428,12 +1433,13 @@ void g_addlocal (unsigned flags, int offs)
     switch (flags & CF_TYPE) {
 
        case CF_CHAR:
+           L = GetLocalLabel();
            AddCodeLine ("ldy #$%02X", offs & 0xFF);
            AddCodeLine ("clc");
            AddCodeLine ("adc (sp),y");
-           AddCodeLine ("bcc *+3");
+           AddCodeLine ("bcc %s", LocalLabelName (L));
            AddCodeLine ("inx");
-           AddCodeHint ("x:!");
+           g_defcodelabel (L);
            break;
 
        case CF_INT:
@@ -1466,17 +1472,20 @@ void g_addlocal (unsigned flags, int offs)
 void g_addstatic (unsigned flags, unsigned long label, unsigned offs)
 /* Add a static variable to ax */
 {
+    unsigned L;
+
     /* Create the correct label name */
     char* lbuf = GetLabelName (flags, label, offs);
 
     switch (flags & CF_TYPE) {
 
        case CF_CHAR:
+           L = GetLocalLabel();
            AddCodeLine ("clc");
            AddCodeLine ("adc %s", lbuf);
-           AddCodeLine ("bcc *+3");
+           AddCodeLine ("bcc %s", LocalLabelName (L));
            AddCodeLine ("inx");
-           AddCodeHint ("x:!");
+           g_defcodelabel (L);
            break;
 
        case CF_INT:
@@ -1561,9 +1570,10 @@ void g_addeqstatic (unsigned flags, unsigned long label, unsigned offs,
                    AddCodeLine ("sta %s", lbuf);
                        }
                if ((flags & CF_UNSIGNED) == 0) {
-                   AddCodeLine ("bpl *+3");
+                   unsigned L = GetLocalLabel();
+                   AddCodeLine ("bpl %s", LocalLabelName (L));
                    AddCodeLine ("dex");
-                   AddCodeHint ("x:!");                /* Invalidate X */
+                   g_defcodelabel (L);
                }
                        break;
                    }
@@ -1681,9 +1691,10 @@ void g_addeqlocal (unsigned flags, int offs, unsigned long val)
                    }
                }
                if ((flags & CF_UNSIGNED) == 0) {
-                   AddCodeLine ("bpl *+3");
+                   unsigned L = GetLocalLabel();
+                   AddCodeLine ("bpl %s", LocalLabelName (L));
                    AddCodeLine ("dex");
-                   AddCodeHint ("x:!");        /* Invalidate X */
+                   g_defcodelabel (L);
                }
                        break;
                    }
@@ -1818,9 +1829,10 @@ void g_subeqstatic (unsigned flags, unsigned long label, unsigned offs,
                            AddCodeLine ("sta %s", lbuf);
                        }
                        if ((flags & CF_UNSIGNED) == 0) {
-                           AddCodeLine ("bpl *+3");
+                   unsigned L = GetLocalLabel();
+                           AddCodeLine ("bpl %s", LocalLabelName (L));
                            AddCodeLine ("dex");
-                           AddCodeHint ("x:!");                /* Invalidate X */
+                   g_defcodelabel (L);
                        }
                        break;
                    }
@@ -1916,9 +1928,10 @@ void g_subeqlocal (unsigned flags, int offs, unsigned long val)
                }
                        AddCodeLine ("sta (sp),y");
                if ((flags & CF_UNSIGNED) == 0) {
-                   AddCodeLine ("bpl *+3");
+                   unsigned L = GetLocalLabel();
+                   AddCodeLine ("bpl %s", LocalLabelName (L));
                    AddCodeLine ("dex");
-                   AddCodeHint ("x:!");                /* Invalidate X */
+                   g_defcodelabel (L);
                }
                        break;
                    }
@@ -2031,20 +2044,27 @@ void g_subeqind (unsigned flags, unsigned offs, unsigned long val)
 void g_addaddr_local (unsigned flags, int offs)
 /* Add the address of a local variable to ax */
 {
+    unsigned L = 0;
+
     /* Add the offset */
     offs -= oursp;
     if (offs != 0) {
        /* We cannot address more then 256 bytes of locals anyway */
+       L = GetLocalLabel();
        CheckLocalOffs (offs);
        AddCodeLine ("clc");
        AddCodeLine ("adc #$%02X", offs & 0xFF);
-               AddCodeLine ("bcc *+4");        /* Do also skip the CLC insn below */
+       /* Do also skip the CLC insn below */
+               AddCodeLine ("bcc %s", LocalLabelName (L));
        AddCodeLine ("inx");
-       AddCodeHint ("x:!");                    /* Invalidate X */
     }
 
     /* Add the current stackpointer value */
     AddCodeLine ("clc");
+    if (L != 0) {
+       /* Label was used above */
+       g_defcodelabel (L);
+    }
     AddCodeLine ("adc sp");
     AddCodeLine ("tay");
     AddCodeLine ("txa");
@@ -2142,20 +2162,24 @@ void g_cmp (unsigned flags, unsigned long val)
  * will be set.
  */
 {
+    unsigned L;
+
     /* Check the size and determine operation */
     switch (flags & CF_TYPE) {
 
        case CF_CHAR:
            if (flags & CF_FORCECHAR) {
                AddCodeLine ("cmp #$%02X", (unsigned char)val);
-               break;
+               break;
            }
            /* FALLTHROUGH */
 
        case CF_INT:
+           L = GetLocalLabel();
            AddCodeLine ("cmp #$%02X", (unsigned char)val);
-                   AddCodeLine ("bne *+4");
+                   AddCodeLine ("bne %s", LocalLabelName (L));
            AddCodeLine ("cpx #$%02X", (unsigned char)(val >> 8));
+           g_defcodelabel (L);
            break;
 
         case CF_LONG:
@@ -2949,9 +2973,10 @@ void g_asr (unsigned flags, unsigned long val)
                    AddCodeLine ("ldy #$00");
                    AddCodeLine ("ldx sreg+1");
                    if ((flags & CF_UNSIGNED) == 0) {
-                       AddCodeLine ("bpl *+3");
+                       unsigned L = GetLocalLabel();
+                       AddCodeLine ("bpl %s", LocalLabelName (L));
                        AddCodeLine ("dey");
-                       AddCodeHint ("y:!");
+                       g_defcodelabel (L);
                    }
                    AddCodeLine ("lda sreg");
                    AddCodeLine ("sty sreg+1");
@@ -3146,11 +3171,11 @@ void g_inc (unsigned flags, unsigned long val)
 
        case CF_INT:
            if (CPU == CPU_65C02 && val == 1) {
+               unsigned L = GetLocalLabel();
                AddCodeLine ("ina");
-               AddCodeLine ("bne *+3");
+               AddCodeLine ("bne %s", LocalLabelName (L));
                AddCodeLine ("inx");
-               /* Tell the optimizer that the X register may be invalid */
-               AddCodeHint ("x:!");
+               g_defcodelabel (L);
            } else if (CodeSizeFactor < 200) {
                /* Use jsr calls */
                if (val <= 8) {
@@ -3165,12 +3190,12 @@ void g_inc (unsigned flags, unsigned long val)
                /* Inline the code */
                if (val < 0x300) {
                    if ((val & 0xFF) != 0) {
+                       unsigned L = GetLocalLabel();
                        AddCodeLine ("clc");
                        AddCodeLine ("adc #$%02X", (unsigned char) val);
-                       AddCodeLine ("bcc *+3");
+                       AddCodeLine ("bcc %s", LocalLabelName (L));
                        AddCodeLine ("inx");
-                       /* Tell the optimizer that the X register may be invalid */
-                               AddCodeHint ("x:!");
+                       g_defcodelabel (L);
                    }
                    if (val >= 0x100) {
                        AddCodeLine ("inx");
@@ -3252,12 +3277,12 @@ void g_dec (unsigned flags, unsigned long val)
                /* Inline the code */
                if (val < 0x300) {
                    if ((val & 0xFF) != 0) {
+                       unsigned L = GetLocalLabel();
                        AddCodeLine ("sec");
                        AddCodeLine ("sbc #$%02X", (unsigned char) val);
-                       AddCodeLine ("bcs *+3");
+                       AddCodeLine ("bcs %s", LocalLabelName (L));
                        AddCodeLine ("dex");
-                       /* Tell the optimizer that the X register may be invalid */
-                               AddCodeHint ("x:!");
+                       g_defcodelabel (L);
                    }
                    if (val >= 0x100) {
                        AddCodeLine ("dex");
@@ -3312,10 +3337,12 @@ void g_eq (unsigned flags, unsigned long val)
     static char* ops [12] = {
        "toseq00",      "toseqa0",      "toseqax",
        "toseq00",      "toseqa0",      "toseqax",
-       0,              0,              "toseqeax",
-       0,              0,              "toseqeax",
+       0,              0,              "toseqeax",
+       0,              0,              "toseqeax",
     };
 
+    unsigned L;
+
     /* If the right hand side is const, the lhs is not on stack but still
      * in the primary register.
      */
@@ -3332,9 +3359,11 @@ void g_eq (unsigned flags, unsigned long val)
                /* FALLTHROUGH */
 
            case CF_INT:
+               L = GetLocalLabel();
                AddCodeLine ("cpx #$%02X", (unsigned char)(val >> 8));
-                       AddCodeLine ("bne *+4");
+                       AddCodeLine ("bne %s", LocalLabelName (L));
                AddCodeLine ("cmp #$%02X", (unsigned char)val);
+               g_defcodelabel (L);
                AddCodeLine ("jsr booleq");
                return;
 
@@ -3368,6 +3397,7 @@ void g_ne (unsigned flags, unsigned long val)
        0,              0,              "tosneeax",
     };
 
+    unsigned L;
 
     /* If the right hand side is const, the lhs is not on stack but still
      * in the primary register.
@@ -3385,9 +3415,11 @@ void g_ne (unsigned flags, unsigned long val)
                /* FALLTHROUGH */
 
            case CF_INT:
+               L = GetLocalLabel();
                AddCodeLine ("cpx #$%02X", (unsigned char)(val >> 8));
-               AddCodeLine ("bne *+4");
+               AddCodeLine ("bne %s", LocalLabelName (L));
                AddCodeLine ("cmp #$%02X", (unsigned char)val);
+               g_defcodelabel (L);
                AddCodeLine ("jsr boolne");
                return;
 
@@ -3415,10 +3447,10 @@ void g_lt (unsigned flags, unsigned long val)
 /* Test for less than */
 {
     static char* ops [12] = {
-       "toslt00",      "toslta0",      "tosltax",
-       "tosult00",     "tosulta0",     "tosultax",
-       0,              0,              "toslteax",
-       0,              0,              "tosulteax",
+       "toslt00",      "toslta0",      "tosltax",
+       "tosult00",     "tosulta0",     "tosultax",
+       0,              0,              "toslteax",
+       0,              0,              "tosulteax",
     };
 
     /* If the right hand side is const, the lhs is not on stack but still
@@ -3435,31 +3467,33 @@ void g_lt (unsigned flags, unsigned long val)
        switch (flags & CF_TYPE) {
 
            case CF_CHAR:
-               if (flags & CF_FORCECHAR) {
-                   AddCodeLine ("cmp #$%02X", (unsigned char)val);
-                   if (flags & CF_UNSIGNED) {
-                       AddCodeLine ("jsr boolult");
-                   } else {
-                       AddCodeLine ("jsr boollt");
-                   }
-                   return;
-               }
-               /* FALLTHROUGH */
+               if (flags & CF_FORCECHAR) {
+                   AddCodeLine ("cmp #$%02X", (unsigned char)val);
+                   if (flags & CF_UNSIGNED) {
+                       AddCodeLine ("jsr boolult");
+                   } else {
+                       AddCodeLine ("jsr boollt");
+                   }
+                   return;
+               }
+               /* FALLTHROUGH */
 
            case CF_INT:
-               if ((flags & CF_UNSIGNED) == 0 && val == 0) {
-                   /* If we have a signed compare against zero, we only need to
-                    * test the high byte.
-                    */
-                   AddCodeLine ("txa");
-                   AddCodeLine ("jsr boollt");
-                   return;
-               }
-               /* Direct code only for unsigned data types */
-               if (flags & CF_UNSIGNED) {
-                   AddCodeLine ("cpx #$%02X", (unsigned char)(val >> 8));
-                           AddCodeLine ("bne *+4");
-                   AddCodeLine ("cmp #$%02X", (unsigned char)val);
+               if ((flags & CF_UNSIGNED) == 0 && val == 0) {
+                   /* If we have a signed compare against zero, we only need to
+                    * test the high byte.
+                    */
+                   AddCodeLine ("txa");
+                   AddCodeLine ("jsr boollt");
+                   return;
+               }
+               /* Direct code only for unsigned data types */
+               if (flags & CF_UNSIGNED) {
+                   unsigned L = GetLocalLabel();
+                   AddCodeLine ("cpx #$%02X", (unsigned char)(val >> 8));
+                           AddCodeLine ("bne %s", LocalLabelName (L));
+                   AddCodeLine ("cmp #$%02X", (unsigned char)val);
+                   g_defcodelabel (L);
                    AddCodeLine ("jsr boolult");
                    return;
                }
@@ -3483,7 +3517,7 @@ void g_lt (unsigned flags, unsigned long val)
        /* If we go here, we didn't emit code. Push the lhs on stack and fall
         * into the normal, non-optimized stuff.
         */
-       g_push (flags & ~CF_CONST, 0);      
+       g_push (flags & ~CF_CONST, 0);
 
     }
 
@@ -3526,9 +3560,11 @@ void g_le (unsigned flags, unsigned long val)
 
            case CF_INT:
                if (flags & CF_UNSIGNED) {
+                   unsigned L = GetLocalLabel();
                    AddCodeLine ("cpx #$%02X", (unsigned char)(val >> 8));
-                           AddCodeLine ("bne *+4");
+                           AddCodeLine ("bne %s", LocalLabelName (L));
                    AddCodeLine ("cmp #$%02X", (unsigned char)val);
+                   g_defcodelabel (L);
                    AddCodeLine ("jsr boolule");
                    return;
                }
@@ -3604,9 +3640,11 @@ void g_gt (unsigned flags, unsigned long val)
                        AddCodeLine ("ora tmp1");
                        AddCodeLine ("jsr boolne");
                    } else {
+                       unsigned L = GetLocalLabel();
                                AddCodeLine ("cpx #$%02X", (unsigned char)(val >> 8));
-                       AddCodeLine ("bne *+4");
+                       AddCodeLine ("bne %s", LocalLabelName (L));
                        AddCodeLine ("cmp #$%02X", (unsigned char)val);
+                       g_defcodelabel (L);
                                AddCodeLine ("jsr boolugt");
                    }
                    return;
@@ -3680,9 +3718,11 @@ void g_ge (unsigned flags, unsigned long val)
                }
                /* Direct code only for unsigned data types */
                if (flags & CF_UNSIGNED) {
+                   unsigned L = GetLocalLabel();
                            AddCodeLine ("cpx #$%02X", (unsigned char)(val >> 8));
-                           AddCodeLine ("bne *+4");
+                           AddCodeLine ("bne %s", LocalLabelName (L));
                    AddCodeLine ("cmp #$%02X", (unsigned char)val);
+                   g_defcodelabel (L);
                    AddCodeLine ("jsr booluge");
                    return;
                }
index 1f89ef14a050c2fb4f9611ccf44860e02ffc0125..84309174b54dad0ca41e2c578792c5d740e05912 100644 (file)
@@ -40,6 +40,9 @@
 #include "coll.h"
 
 /* cc65 */
+#include "codeent.h"
+#include "codeseg.h"
+#include "error.h"
 #include "codeinfo.h"
 
 
@@ -61,49 +64,52 @@ struct FuncInfo {
 };
 
 static const FuncInfo FuncInfoTable[] = {
-    { "booleq",                REG_NONE,       REG_AX  },
-    { "boolge",                REG_NONE,       REG_AX  },
-    { "boolgt",                REG_NONE,       REG_AX  },
-    { "boolle",                REG_NONE,       REG_AX  },
-    { "boollt",                REG_NONE,       REG_AX  },
-    { "boolne",                REG_NONE,       REG_AX  },
-    { "booluge",       REG_NONE,       REG_AX  },
-    { "boolugt",       REG_NONE,       REG_AX  },
-    { "boolule",       REG_NONE,       REG_AX  },
-    { "boolult",       REG_NONE,       REG_AX  },
-    { "decax1",        REG_AX,         REG_AX  },
-    { "decax2",        REG_AX,         REG_AX  },
-    { "decax3",        REG_AX,         REG_AX  },
-    { "decax4",        REG_AX,         REG_AX  },
-    { "decax5",        REG_AX,         REG_AX  },
-    { "decax6",        REG_AX,         REG_AX  },
-    { "decax7",        REG_AX,         REG_AX  },
-    { "decax8",        REG_AX,         REG_AX  },
-    { "decaxy",                REG_AXY,        REG_AX  },
-    { "decsp2",        REG_NONE,       REG_A   },
-    { "decsp3",        REG_NONE,       REG_A   },
-    { "decsp4",        REG_NONE,       REG_A   },
-    { "decsp5",        REG_NONE,       REG_A   },
-    { "decsp6",        REG_NONE,       REG_A   },
-    { "decsp7",        REG_NONE,       REG_A   },
-    { "decsp8",        REG_NONE,       REG_A   },
-    { "ldax0sp",       REG_Y,          REG_AX  },
-    { "ldaxysp",       REG_Y,          REG_AX  },
-    { "pusha",         REG_A,          REG_Y   },
-    { "pusha0",                REG_A,          REG_XY  },
-    { "pushax",                REG_AX,         REG_Y   },
-    { "pushw0sp",      REG_NONE,       REG_AXY },
-    { "pushwysp",      REG_Y,          REG_AXY },
-    { "tosicmp",       REG_AX,         REG_AXY },
+    { "addysp",                REG_Y,          REG_NONE        },
+    { "booleq",                REG_NONE,       REG_AX          },
+    { "boolge",                REG_NONE,       REG_AX          },
+    { "boolgt",                REG_NONE,       REG_AX          },
+    { "boolle",                REG_NONE,       REG_AX          },
+    { "boollt",                REG_NONE,       REG_AX          },
+    { "boolne",                REG_NONE,       REG_AX          },
+    { "booluge",       REG_NONE,       REG_AX          },
+    { "boolugt",       REG_NONE,       REG_AX          },
+    { "boolule",       REG_NONE,       REG_AX          },
+    { "boolult",       REG_NONE,       REG_AX          },
+    { "decax1",        REG_AX,         REG_AX          },
+    { "decax2",        REG_AX,         REG_AX          },
+    { "decax3",        REG_AX,         REG_AX          },
+    { "decax4",        REG_AX,         REG_AX          },
+    { "decax5",        REG_AX,         REG_AX          },
+    { "decax6",        REG_AX,         REG_AX          },
+    { "decax7",        REG_AX,         REG_AX          },
+    { "decax8",        REG_AX,         REG_AX          },
+    { "decaxy",                REG_AXY,        REG_AX          },
+    { "decsp2",        REG_NONE,       REG_A           },
+    { "decsp3",        REG_NONE,       REG_A           },
+    { "decsp4",        REG_NONE,       REG_A           },
+    { "decsp5",        REG_NONE,       REG_A           },
+    { "decsp6",        REG_NONE,       REG_A           },
+    { "decsp7",        REG_NONE,       REG_A           },
+    { "decsp8",        REG_NONE,       REG_A           },
+    { "incsp1",                REG_NONE,       REG_NONE        },
+    { "incsp2",                REG_NONE,       REG_Y           },
+    { "incsp3",                REG_NONE,       REG_Y           },
+    { "incsp4",                REG_NONE,       REG_Y           },
+    { "incsp5",                REG_NONE,       REG_Y           },
+    { "incsp6",                REG_NONE,       REG_Y           },
+    { "incsp7",                REG_NONE,       REG_Y           },
+    { "incsp8",                REG_NONE,       REG_Y           },
+    { "ldax0sp",       REG_Y,          REG_AX          },
+    { "ldaxysp",       REG_Y,          REG_AX          },
+    { "pusha",         REG_A,          REG_Y           },
+    { "pusha0",                REG_A,          REG_XY          },
+    { "pushax",                REG_AX,         REG_Y           },
+    { "pushw0sp",      REG_NONE,       REG_AXY         },
+    { "pushwysp",      REG_Y,          REG_AXY         },
+    { "tosicmp",       REG_AX,         REG_AXY         },
 };
 #define FuncInfoCount  (sizeof(FuncInfoTable) / sizeof(FuncInfoTable[0]))
 
-/* Structure used to pass information to the RegValUsedInt1 and 2 functions */
-typedef struct RVUInfo RVUInfo;
-struct RVUInfo {
-    Collection VisitedLines;           /* Lines already visited */
-};
-
 
 
 /*****************************************************************************/
@@ -137,177 +143,190 @@ void GetFuncInfo (const char* Name, unsigned char* Use, unsigned char* Chg)
        *Use |= Info->Use;
        *Chg |= Info->Chg;
     } else {
+       /* Assume all registers used */
        *Use |= REG_AXY;
        *Chg |= REG_AXY;
     }
 }
 
-                                       
-#if 0
 
-static unsigned RVUInt2 (Line* L,
-                        LineColl* LC,      /* To remember visited lines */
-                        unsigned Used,     /* Definitely used registers */
-                        unsigned Unused)   /* Definitely unused registers */
-/* Subfunction for RegValUsed. Will be called recursively in case of branches. */
-{
-    int I;
 
-    /* Check the following instructions. We classifiy them into primary
-     * loads (register value not used), neutral (check next instruction),
-     * and unknown (assume register was used).
-     */
+static unsigned char GetRegInfo2 (CodeSeg* S,
+                                 CodeEntry* E,
+                                 int Index,
+                                 Collection* Visited,
+                                 unsigned char Used,
+                                 unsigned char Unused)
+/* Recursively called subfunction for GetRegInfo. */
+{
+    /* Follow the instruction flow recording register usage. */
     while (1) {
 
-       unsigned R;
-
-       /* Get the next line and follow jumps */
-       do {
-
-           /* Handle jumps to local labels (continue there) */
-                   if (LineMatch (L, "\tjmp\tL") || LineMatch (L, "\tbra\tL")) {
-               /* Get the target of the jump */
-               L = GetTargetLine (L->Line+5);
-           }
-
-           /* Get the next line, skip local labels */
-           do {
-                       L = NextCodeSegLine (L);
-           } while (L && (IsLocalLabel (L) || L->Line[0] == '\0'));
-
-           /* Bail out if we're done */
-           if (L == 0 || IsExtLabel (L)) {
-               /* End of function reached */
-               goto ExitPoint;
-           }
-
-           /* Check if we had this line already. If so, bail out, if not,
-            * add it to the list of known lines.
-            */
-           if (LCHasLine (LC, L) || !LCAddLine (LC, L)) {
-               goto ExitPoint;
-           }
-
-       } while (LineMatch (L, "\tjmp\tL") || LineMatch (L, "\tbra\tL"));
-
-       /* Special handling of code hints */
-               if (IsHintLine (L)) {
-
-           if (IsHint (L, "a:-") && (Used & REG_A) == 0) {
-               Unused |= REG_A;
-           } else if (IsHint (L, "x:-") && (Used & REG_X) == 0) {
-               Unused |= REG_X;
-           } else if (IsHint (L, "y:-") && (Used & REG_Y) == 0) {
-               Unused |= REG_Y;
-           }
-
-       /* Special handling for branches */
-       } else if (LineMatchX (L, ShortBranches) >= 0 ||
-           LineMatchX (L, LongBranches) >= 0) {
-           const char* Target = L->Line+5;
-           if (Target[0] == 'L') {
-               /* Jump to local label. Check the register usage starting at
-                * the branch target and at the code following the branch.
-                * All registers that are unused in both execution flows are
-                * returned as unused.
-                */
-               unsigned U1, U2;
-                       U2 = RVUInt1 (GetTargetLine (Target), LC, Used, Unused);
-               U1 = RVUInt1 (L, LC, Used, Unused);
-               return U1 | U2;         /* Used in any of the branches */
-           }
-       } else {
-
-           /* Search for the instruction in this line */
-           I = FindCmd (L);
-
-           /* If we don't find it, assume all other registers are used */
-           if (I < 0) {
-               break;
-           }
-
-           /* Evaluate the use flags, check for addressing modes */
-           R = CmdDesc[I].Use;
-           if (IsXAddrMode (L)) {
-               R |= REG_X;
-           } else if (IsYAddrMode (L)) {
-               R |= REG_Y;
-           }
-           if (R) {
-               /* Remove registers that were already new loaded */
-               R &= ~Unused;
-
-               /* Remember the remaining registers */
-               Used |= R;
-           }
-
-           /* Evaluate the load flags */
-           R = CmdDesc[I].Load;
-           if (R) {
-               /* Remove registers that were already used */
-               R &= ~Used;
-
-               /* Remember the remaining registers */
-               Unused |= R;
-           }
-
-       }
-
-               /* If we know about all registers, bail out */
-               if ((Used | Unused) == REG_ALL) {
+       unsigned char R;
+
+       /* Check if we have already visited the current code entry. If so,
+        * bail out.
+        */
+       if (CodeEntryHasMark (E)) {
+           break;
+       }
+
+       /* Mark this entry as already visited */
+       CodeEntrySetMark (E);
+       CollAppend (Visited, E);
+
+       /* Evaluate the used registers */
+       if ((R = E->Use) != REG_NONE) {
+           /* We are not interested in the use of any register that has been
+            * used before.
+            */
+           R &= ~Unused;
+           /* Remember the remaining registers */
+           Used |= R;
+       }
+
+       /* Evaluate the changed registers */
+               if ((R = E->Chg) != REG_NONE) {
+           /* We are not interested in the use of any register that has been
+            * used before.
+            */
+           R &= ~Used;
+           /* Remember the remaining registers */
+           Unused |= R;
+       }
+
+               /* If we know about all registers now, bail out */
+               if ((Used | Unused) == REG_AXY) {
            break;
        }
+
+       /* If the instruction is an RTS or RTI, we're done */
+       if (E->OPC == OPC_RTS || E->OPC == OPC_RTI) {
+           break;
+       }
+
+       /* If we have an unconditional branch, follow this branch if possible,
+        * otherwise we're done.
+        */
+       if ((E->Info & OF_UBRA) != 0) {
+
+           /* Does this jump have a valid target? */
+           if (E->JumpTo) {
+
+               /* Unconditional jump */
+               E     = E->JumpTo->Owner;
+               Index = -1;             /* Invalidate */
+
+           } else {
+               /* Jump outside means we're done */
+               break;
+           }
+
+               /* In case of conditional branches, follow the branch if possible and
+        * follow the normal flow (branch not taken) afterwards. If we cannot
+        * follow the branch, we're done.
+        */
+       } else if ((E->Info & OF_CBRA) != 0) {
+
+           if (E->JumpTo) {
+
+               /* Recursively determine register usage at the branch target */
+               unsigned char U1;
+               unsigned char U2;
+
+               U1 = GetRegInfo2 (S, E->JumpTo->Owner, -1, Visited, Used, Unused);
+               if (U1 == REG_AXY) {
+                   /* All registers used, no need for second call */
+                   return REG_AXY;
+               }
+               if (Index < 0) {
+                   Index = GetCodeEntryIndex (S, E);
+               }
+                       if ((E = GetCodeEntry (S, ++Index)) == 0) {
+                   Internal ("GetRegInfo2: No next entry!");
+               }
+               U2 = GetRegInfo2 (S, E, Index, Visited, Used, Unused);
+               return U1 | U2;         /* Used in any of the branches */
+
+           } else {
+               /* Jump to global symbol */
+               break;
+           }
+
+               } else {
+
+           /* Just go to the next instruction */
+           if (Index < 0) {
+               Index = GetCodeEntryIndex (S, E);
+           }
+           E = GetCodeEntry (S, ++Index);
+           if (E == 0) {
+               /* No next entry */
+               Internal ("GetRegInfo2: No next entry!");
+           }
+
+       }
+
     }
 
-ExitPoint:
     /* Return to the caller the complement of all unused registers */
-    return ~Unused & REG_ALL;
+    return Used;
 }
 
 
 
-static unsigned RVUInt1 (Line* L,
-                        LineColl* LC,      /* To remember visited lines */
-                        unsigned Used,     /* Definitely used registers */
-                        unsigned Unused)   /* Definitely unused registers */
-/* Subfunction for RegValUsed. Will be called recursively in case of branches. */
+static unsigned char GetRegInfo1 (CodeSeg* S,
+                                 CodeEntry* E,
+                                 int Index,
+                                 Collection* Visited,
+                                 unsigned char Used,
+                                 unsigned char Unused)
+/* Recursively called subfunction for GetRegInfo. */
 {
     /* Remember the current count of the line collection */
-    unsigned Count = LC->Count;
+    unsigned Count = CollCount (Visited);
 
     /* Call the worker routine */
-    unsigned R = RVUInt2 (L, LC, Used, Unused);
-
-    /* Restore the old count */
-    LC->Count = Count;
+    unsigned char R = GetRegInfo2 (S, E, Index, Visited, Used, Unused);
+
+    /* Restore the old count, unmarking all new entries */
+    unsigned NewCount = CollCount (Visited);
+    while (NewCount-- > Count) {
+       CodeEntry* E = CollAt (Visited, NewCount);
+       CodeEntryResetMark (E);
+       CollDelete (Visited, NewCount);
+    }
 
-    /* Return the result */
+    /* Return the registers used */
     return R;
 }
 
 
 
-static unsigned RegValUsed (Line* Start)
-/* Check the next instructions after the one in L for register usage. If
- * a register is used as an index, or in a store or other instruction, it
- * is assumed to be used. If a register is loaded with a value, before it
- * was used by one of the actions described above, it is assumed unused.
- * If the end of the lookahead is reached, all registers that are uncertain
- * are marked as used.
- * The result of the search is returned.
+unsigned char GetRegInfo (struct CodeSeg* S, unsigned Index)
+/* Determine register usage information for the instructions starting at the
+ * given index.
  */
 {
-    unsigned R;
+    CodeEntry*     E;
+    Collection     Visited;    /* Visited entries */
+    unsigned char   R;
+
+    /* Get the code entry for the given index */
+    if (Index >= GetCodeEntryCount (S)) {
+       /* There is no such code entry */
+       return REG_NONE;
+    }
+    E = GetCodeEntry (S, Index);
 
-    /* Create a new line collection and enter the start line */
-    LineColl* LC = NewLineColl (256);
-    LCAddLine (LC, Start);
+    /* Initialize the data structure used to collection information */
+    InitCollection (&Visited);
 
     /* Call the recursive subfunction */
-    R = RVUInt1 (Start, LC, REG_NONE, REG_NONE);
+    R = GetRegInfo1 (S, E, Index, &Visited, REG_NONE, REG_NONE);
 
     /* Delete the line collection */
-    FreeLineColl (LC);
+    DoneCollection (&Visited);
 
     /* Return the registers used */
     return R;
@@ -315,28 +334,27 @@ static unsigned RegValUsed (Line* Start)
 
 
 
-static int RegAUsed (Line* Start)
+int RegAUsed (struct CodeSeg* S, unsigned Index)
 /* Check if the value in A is used. */
 {
-    return (RegValUsed (Start) & REG_A) != 0;
+    return (GetRegInfo (S, Index) & REG_A) != 0;
 }
 
 
 
-static int RegXUsed (Line* Start)
+int RegXUsed (struct CodeSeg* S, unsigned Index)
 /* Check if the value in X is used. */
 {
-    return (RegValUsed (Start) & REG_X) != 0;
+    return (GetRegInfo (S, Index) & REG_X) != 0;
 }
 
 
 
-static int RegYUsed (Line* Start)
+int RegYUsed (struct CodeSeg* S, unsigned Index)
 /* Check if the value in Y is used. */
 {
-    return (RegValUsed (Start) & REG_Y) != 0;
+    return (GetRegInfo (S, Index) & REG_Y) != 0;
 }
 
 
 
-#endif     
index d9a2506a6d8ba0bc054ff5482435dc77f36209f0..85b726dc0a5773b8beb9d833122cf2b3b5566c1b 100644 (file)
 
 
 
+/*****************************************************************************/
+/*                                Forwards                                  */
+/*****************************************************************************/
+
+
+
+struct CodeSeg;
+
+
+
 /*****************************************************************************/
 /*                                  Data                                    */
 /*****************************************************************************/
@@ -72,6 +82,20 @@ void GetFuncInfo (const char* Name, unsigned char* Use, unsigned char* Chg);
  * will use all registers and load all registers.
  */
 
+unsigned char GetRegInfo (struct CodeSeg* S, unsigned Index);
+/* Determine register usage information for the instructions starting at the
+ * given index.
+ */
+
+int RegAUsed (struct CodeSeg* S, unsigned Index);
+/* Check if the value in A is used. */
+
+int RegXUsed (struct CodeSeg* S, unsigned Index);
+/* Check if the value in X is used. */
+
+int RegYUsed (struct CodeSeg* S, unsigned Index);
+/* Check if the value in Y is used. */
+
 
 
 /* End of codeinfo.h */
index c97cfa06fe0d7af38110e7e7675d590da924d881..a422c48f690c5bfe7c3d745022d2eb304249de0c 100644 (file)
@@ -270,10 +270,12 @@ static OptFunc OptFuncs [] = {
     { OptDeadCode,                 "OptDeadCode",              0       },
     /* Optimize jump targets */
     { OptJumpTarget,               "OptJumpTarget",            0       },
-    /* Remove dead conditional branches */
-    { OptDeadCondBranches,  "OptDeadCondBranches",     0       },
+    /* Optimize conditional branches */
+    { OptCondBranches,     "OptCondBranches",          0       },
     /* Remove calls to the bool transformer subroutines        */
     { OptBoolTransforms,    "OptBoolTransforms",       0       },
+    /* Remove unused loads */
+    { OptUnusedLoads,      "OptUnusedLoads",           0       },
 };
 
 
@@ -325,6 +327,11 @@ void RunOpt (CodeSeg* S)
     unsigned Pass = 0;
     unsigned OptChanges;
 
+    /* If we shouldn't run the optimizer, bail out */
+    if (!Optimize) {
+       return;
+    }
+
     /* Print the name of the function we are working on */
     if (S->Func) {
        Print (stdout, 1, "Running optimizer for function `%s'\n", S->Func->Name);
index 1ca80601b154e315a0d60d93d019690a044921f8..75cc471de5a09ebdd261c2a9c9ddf2715db0f010 100644 (file)
@@ -451,6 +451,17 @@ void AddCodeEntry (CodeSeg* S, const char* Format, va_list ap)
 
 
 
+void InsertCodeEntry (CodeSeg* S, struct CodeEntry* E, unsigned Index)
+/* Insert the code entry at the index given. Following code entries will be
+ * moved to slots with higher indices.
+ */
+{
+    /* Insert the entry into the collection */
+    CollInsert (&S->Entries, E, Index);
+}
+
+
+
 void DelCodeEntry (CodeSeg* S, unsigned Index)
 /* Delete an entry from the code segment. This includes moving any associated
  * labels, removing references to labels and even removing the referenced labels
@@ -513,6 +524,22 @@ struct CodeEntry* GetCodeEntry (CodeSeg* S, unsigned Index)
 
 
 
+struct CodeEntry* GetNextCodeEntry (CodeSeg* S, unsigned Index)
+/* Get the code entry following the one with the index Index. If there is no
+ * following code entry, return NULL.
+ */
+{
+    if (Index >= CollCount (&S->Entries)-1) {
+       /* This is the last entry */
+       return 0;
+    } else {
+       /* Code entries left */
+       return CollAt (&S->Entries, Index+1);
+    }
+}
+
+
+
 unsigned GetCodeEntryIndex (CodeSeg* S, struct CodeEntry* E)
 /* Return the index of a code entry */
 {
@@ -610,7 +637,7 @@ void DelCodeLabel (CodeSeg* S, CodeLabel* L)
      * errors to slip through.
      */
     if (L->Owner) {
-       CollDeleteItem (&L->Owner->Labels, L);
+       CollDeleteItem (&L->Owner->Labels, L);
     }
 
     /* All references removed, delete the label itself */
@@ -737,7 +764,7 @@ void RemoveCodeLabelRef (CodeSeg* S, struct CodeEntry* E)
 
     /* If there are no more references, delete the label */
     if (CollCount (&L->JumpFrom) == 0) {
-       DelCodeLabel (S, L);
+               DelCodeLabel (S, L);
     }
 }
 
@@ -790,29 +817,45 @@ void DelCodeSegAfter (CodeSeg* S, unsigned Last)
     /* Get the number of entries in this segment */
     unsigned Count = GetCodeEntryCount (S);
 
-    /* Check if we have to delete anything */
-    if (Last < Count) {
+    /* First pass: Delete all references to labels. If the reference count
+     * for a label drops to zero, delete it.
+     */
+    unsigned C = Count;
+    while (Last < C--) {
+
+       /* Get the next entry */
+       CodeEntry* E = GetCodeEntry (S, C);
 
-       /* Remove all entries after the given one */
-       while (Last < Count--) {
+       /* Check if this entry has a label reference */
+       if (E->JumpTo) {
+           /* Remove the reference to the label */
+           RemoveCodeLabelRef (S, E);
+       }
 
-           /* Get the next entry */
-           CodeEntry* E = GetCodeEntry (S, Count);
+    }
 
-           /* If the code entry has labels, delete them */
-           while (CodeEntryHasLabel (E)) {
+    /* Second pass: Delete the instructions. If a label attached to an
+     * instruction still has references, it must be references from outside
+     * the deleted area. Don't delete the label in this case, just make it
+     * ownerless and move it to the label pool.
+     */
+    C = Count;
+    while (Last < C--) {
 
-               /* Get the label */
-               CodeLabel* L = GetCodeLabel (E, 0);
+       /* Get the next entry */
+       CodeEntry* E = GetCodeEntry (S, C);
 
-               /* Delete it */
-               DelCodeLabel (S, L);
+       /* Check if this entry has a label attached */
+       if (CodeEntryHasLabel (E)) {
+           /* Move the labels to the pool and clear the owner pointer */
+           MoveLabelsToPool (S, E);
+       }
 
-           }
+       /* Delete the pointer to the entry */
+       CollDelete (&S->Entries, C);
 
-           /* Delete the entry itself */
-           DelCodeEntry (S, Count);
-       }
+       /* Delete the entry itself */
+       FreeCodeEntry (E);
     }
 }
 
@@ -841,7 +884,18 @@ void OutputCodeSeg (const CodeSeg* S, FILE* F)
 
     /* Output all entries */
     for (I = 0; I < Count; ++I) {
+
+       unsigned char Use;
+
        OutputCodeEntry (CollConstAt (&S->Entries, I), F);
+
+       /* Print usage info */
+       Use = GetRegInfo ((CodeSeg*) S, I+1);
+       fprintf (F,
+                "  Use: %c%c%c\n",
+                (Use & REG_A)? 'A' : '_',
+                (Use & REG_X)? 'X' : '_',
+                (Use & REG_Y)? 'Y' : '_');
     }
 
     /* If this is a segment for a function, leave the function */
index a90e31b1a7a5b8d2d2c49c3aaa29e76a96144ae4..0f8bc4d3c00d0c7777bf6812ac29c9709d4f71bc 100644 (file)
@@ -94,6 +94,11 @@ CodeSeg* NewCodeSeg (const char* SegName, SymEntry* Func);
 void AddCodeEntry (CodeSeg* S, const char* Format, va_list ap) attribute ((format(printf,2,0)));
 /* Add a line to the given code segment */
 
+void InsertCodeEntry (CodeSeg* S, struct CodeEntry* E, unsigned Index);
+/* Insert the code entry at the index given. Following code entries will be
+ * moved to slots with higher indices.
+ */
+
 void DelCodeEntry (CodeSeg* S, unsigned Index);
 /* Delete an entry from the code segment. This includes moving any associated
  * labels, removing references to labels and even removing the referenced labels
@@ -103,6 +108,11 @@ void DelCodeEntry (CodeSeg* S, unsigned Index);
 struct CodeEntry* GetCodeEntry (CodeSeg* S, unsigned Index);
 /* Get an entry from the given code segment */
 
+struct CodeEntry* GetNextCodeEntry (CodeSeg* S, unsigned Index);
+/* Get the code entry following the one with the index Index. If there is no
+ * following code entry, return NULL.
+ */
+
 unsigned GetCodeEntryIndex (CodeSeg* S, struct CodeEntry* E);
 /* Return the index of a code entry */
 
index f01546d1f63fcbfc4125a563c45c6a664a506e82..9a76c186623fef8576d5946469d3ff6d00afb915 100644 (file)
@@ -241,8 +241,47 @@ unsigned OptJumpCascades (CodeSeg* S)
             * the second branch will never be taken, and we may jump directly
             * to the instruction behind this one.
             */
-           goto NextEntry;
+           if ((E->Info & OF_CBRA) != 0 && (N->Info & OF_CBRA) != 0) {
 
+               unsigned NI;    /* Index of N */
+               CodeEntry* X;   /* Instruction behind N */
+               CodeLabel* LX;  /* Label attached to X */
+
+               /* Get the branch conditions of both branches */
+               bc_t BC1 = GetBranchCond (E->OPC);
+               bc_t BC2 = GetBranchCond (N->OPC);
+
+               /* Check the branch conditions */
+               if (BC1 != GetInverseCond (BC2)) {
+                   /* Condition not met */
+                   goto NextEntry;
+               }
+
+               /* We may jump behind this conditional branch. This means that
+                * N may not be the last entry.
+                */
+               NI = GetCodeEntryIndex (S, N);
+               if (NI >= Count-1) {
+                   /* N is last entry */
+                   goto NextEntry;
+               }
+
+               /* Get the pointer to the next instruction */
+               X = GetCodeEntry (S, NI+1);
+
+               /* Get the label attached to X, create a new one if needed */
+               LX = GenCodeLabel (S, X);
+
+               /* Move the reference from E to the new label */
+               MoveCodeLabelRef (S, E, LX);
+
+               /* Remember, we had changes */
+               ++Changes;
+
+               /* Done */
+               continue;
+
+           }
        }
 
 NextEntry:
@@ -270,7 +309,7 @@ unsigned OptRTS (CodeSeg* S)
  */
 {
     unsigned Changes = 0;
-    unsigned I;          
+    unsigned I;
 
     /* Get the number of entries, bail out if we have less than 2 entries */
     unsigned Count = GetCodeEntryCount (S);
@@ -405,15 +444,22 @@ NextEntry:
 
 
 /*****************************************************************************/
-/*                  Remove conditional jumps never taken                    */
+/*                      Optimize conditional branches                       */
 /*****************************************************************************/
 
 
 
-unsigned OptDeadCondBranches (CodeSeg* S)
-/* If an immidiate load of a register is followed by a conditional jump that
- * is never taken because the load of the register sets the flags in such a
- * manner, remove the conditional branch.
+unsigned OptCondBranches (CodeSeg* S)
+/* Performs several optimization steps:
+ *
+ *  - If an immidiate load of a register is followed by a conditional jump that
+ *    is never taken because the load of the register sets the flags in such a
+ *    manner, remove the conditional branch.
+ *  - If the conditional branch is always taken because of the register load,
+ *    replace it by a jmp.
+ *  - If a conditional branch jumps around an unconditional branch, remove the
+ *    conditional branch and make the jump a conditional branch with the
+ *    inverse condition of the first one.
  */
 {
     unsigned Changes = 0;
@@ -429,36 +475,131 @@ unsigned OptDeadCondBranches (CodeSeg* S)
     I = 0;
     while (I < Count-1) {
 
+       CodeEntry* N;
+       CodeLabel* L;
+
        /* Get next entry */
                CodeEntry* E = GetCodeEntry (S, I);
 
        /* Check if it's a register load */
-               if ((E->Info & OF_LOAD) != 0 && E->AM == AM_IMM && (E->Flags & CEF_NUMARG) != 0) {
+               if ((E->Info & OF_LOAD) != 0            &&  /* It's a load instruction */
+           E->AM == AM_IMM                     &&  /* ..with immidiate addressing */
+           (E->Flags & CEF_NUMARG) != 0        &&  /* ..and a numeric argument. */
+           (N = GetNextCodeEntry (S, I)) != 0  &&  /* There is a following entry */
+                   (N->Info & OF_CBRA) != 0            &&  /* ..which is a conditional branch */
+           !CodeEntryHasLabel (N)) {               /* ..and does not have a label */
+
+           /* Get the branch condition */
+           bc_t BC = GetBranchCond (N->OPC);
 
-           bc_t BC;
+           /* Check the argument against the branch condition */
+                   if ((BC == BC_EQ && E->Num != 0)            ||
+               (BC == BC_NE && E->Num == 0)            ||
+               (BC == BC_PL && (E->Num & 0x80) != 0)   ||
+               (BC == BC_MI && (E->Num & 0x80) == 0)) {
 
-           /* Immidiate register load, get next instruction */
-           CodeEntry* N = GetCodeEntry (S, I+1);
+               /* Remove the conditional branch */
+               DelCodeEntry (S, I+1);
+               --Count;
 
-           /* Check if the following insn is a conditional branch or if it
-            * has a label attached.
-            */
-           if ((N->Info & OF_CBRA) == 0 || CodeEntryHasLabel (E)) {
-               /* No conditional jump or label attached, bail out */
+               /* Remember, we had changes */
+               ++Changes;
+
+           } else if ((BC == BC_EQ && E->Num == 0)             ||
+                      (BC == BC_NE && E->Num != 0)             ||
+                      (BC == BC_PL && (E->Num & 0x80) == 0)    ||
+                      (BC == BC_MI && (E->Num & 0x80) != 0)) {
+
+               /* The branch is always taken, replace it by a jump */
+               ReplaceOPC (N, OPC_JMP);
+
+               /* Remember, we had changes */
+               ++Changes;
+           }
+
+       }
+
+       if ((E->Info & OF_CBRA) != 0            &&  /* It's a conditional branch */
+           (L = E->JumpTo) != 0                &&  /* ..referencing a local label */
+                   (N = GetNextCodeEntry (S, I)) != 0  &&  /* There is a following entry */
+           (N->Info & OF_UBRA) != 0            &&  /* ..which is an uncond branch, */
+           !CodeEntryHasLabel (N)              &&  /* ..has no label attached */
+           L->Owner == GetNextCodeEntry (S, I+1)) {/* ..and jump target follows */
+
+           /* Replace the jump by a conditional branch with the inverse branch
+            * condition than the branch around it.
+            */
+           ReplaceOPC (N, GetInverseBranch (E->OPC));
+
+           /* Remove the conditional branch */
+           DelCodeEntry (S, I);
+           --Count;
+
+           /* Remember, we had changes */
+           ++Changes;
+
+       }
+
+       /* Next entry */
+       ++I;
+
+    }
+
+    /* Return the number of changes made */
+    return Changes;
+}
+
+
+
+/*****************************************************************************/
+/*                           Remove unused loads                            */
+/*****************************************************************************/
+
+
+
+unsigned OptUnusedLoads (CodeSeg* S)
+/* Remove loads of registers where the value loaded is not used later. */
+{
+    unsigned Changes = 0;
+    unsigned I;
+
+    /* Get the number of entries, bail out if we have not enough */
+    unsigned Count = GetCodeEntryCount (S);
+    if (Count < 2) {
+       return 0;
+    }
+
+    /* Walk over the entries */
+    I = 0;
+    while (I < Count-1) {
+
+       /* Get next entry */
+               CodeEntry* E = GetCodeEntry (S, I);
+
+       /* Check if it's a register load */
+               if ((E->Info & OF_LOAD) != 0) {
+
+           unsigned char R;
+
+           /* Get the next instruction, it must not be a conditional branch */
+           CodeEntry* N = GetCodeEntry (S, I+1);
+           if ((N->Info & OF_CBRA) != 0) {
                goto NextEntry;
            }
 
-           /* Get the branch condition */
-           BC = GetBranchCond (N->OPC);
+           /* Check which sort of load it is */
+           switch (E->OPC) {
+               case OPC_LDA:   R = REG_A;      break;
+                       case OPC_LDX:   R = REG_X;      break;
+               case OPC_LDY:   R = REG_Y;      break;
+               default:        goto NextEntry;         /* OOPS */
+           }
 
-           /* Check the argument against the branch condition */
-                   if ((BC == BC_EQ && E->Num != 0)            ||
-               (BC == BC_NE && E->Num == 0)            ||
-               (BC == BC_PL && (E->Num & 0x80) != 0)   ||
-               (BC == BC_MI && (E->Num & 0x80) == 0)) {
+           /* Get register usage and check if the register value is used later */
+           if ((GetRegInfo (S, I+1) & R) == 0) {
 
-               /* Remove the conditional branch */
-               DelCodeEntry (S, I+1);
+               /* Register value is not used, remove the load */
+               DelCodeEntry (S, I);
                --Count;
 
                /* Remember, we had changes */
@@ -475,7 +616,7 @@ NextEntry:
 
     /* Return the number of changes made */
     return Changes;
-}       
+}
 
 
 
index bcb9e5a40d2f878ccc3294257db23b52fd8d9d66..7ade6eeff39a30757536c9108ffb3a080f661427 100644 (file)
@@ -77,12 +77,15 @@ unsigned OptJumpTarget (CodeSeg* S);
  * the branch gets removed.
  */
 
-unsigned OptDeadCondBranches (CodeSeg* S);
+unsigned OptCondBranches (CodeSeg* S);
 /* If an immidiate load of a register is followed by a conditional jump that
  * is never taken because the load of the register sets the flags in such a
  * manner, remove the conditional branch.
  */
 
+unsigned OptUnusedLoads (CodeSeg* S);
+/* Remove loads of registers where the value loaded is not used later. */
+
 
 
 /* End of coptind.h */