]> git.sur5r.net Git - cc65/blobdiff - src/cc65/optimize.c
Added the io module
[cc65] / src / cc65 / optimize.c
index 3119311b62458934102e11f85b5edae781ac52ac..48ce3fbb61233acae5c3c8dd4c2f05f0f501069d 100644 (file)
 
 
 #include <stdarg.h>
+#include <stdio.h>
 #include <string.h>
 #include <ctype.h>
 
+/* common */
+#include "attrib.h"
+#include "xmalloc.h"
+
+/* cc65 */
 #include "asmlabel.h"
 #include "asmline.h"
 #include "check.h"
+#include "cpu.h"
 #include "error.h"
 #include "global.h"
-#include "io.h"
-#include "mem.h"
 #include "optimize.h"
 
 
@@ -123,10 +128,14 @@ static const struct {
     { "\tcmp\t",                 0,    REG_A,      REG_NONE      },
     { "\tcpx\t",                 0,    REG_X,      REG_NONE      },
     { "\tcpy\t",                 0,    REG_Y,      REG_NONE      },
+    { "\tdea",           1,    REG_A,      REG_NONE      },
+    { "\tdec\ta",        1,    REG_A,      REG_NONE      },
     { "\tdec\t",                 0,    REG_NONE,   REG_NONE      },
     { "\tdex",                   1,    REG_X,      REG_NONE      },
     { "\tdey",                   1,    REG_Y,      REG_NONE      },
     { "\teor\t",                 0,    REG_A,      REG_NONE      },
+    { "\tina",           1,    REG_A,      REG_NONE      },
+    { "\tinc\ta",        1,    REG_A,      REG_NONE      },
     { "\tinc\t",                 0,    REG_NONE,   REG_NONE      },
     { "\tinx",                   1,    REG_X,      REG_NONE      },
     { "\tiny",                   1,    REG_Y,      REG_NONE      },
@@ -164,6 +173,7 @@ static const struct {
     { "\tsta\t",                 0,    REG_A,      REG_NONE      },
     { "\tstx\t",                 0,    REG_X,      REG_NONE      },
     { "\tsty\t",                 0,    REG_Y,      REG_NONE      },
+    { "\tstz\t",         0,    REG_NONE,   REG_NONE      },
     { "\ttax",                   1,    REG_A,      REG_X         },
     { "\ttay",                   1,    REG_A,      REG_Y         },
     { "\ttsx",                   1,    REG_NONE,   REG_X         },
@@ -219,7 +229,7 @@ static const char* LongBranches [] = {
 
 
 /*****************************************************************************/
-/*                                        Forwards                                  */
+/*                                        Forwards                                  */
 /*****************************************************************************/
 
 
@@ -236,10 +246,19 @@ static unsigned GetLabelNum (const char* L);
 static unsigned RVUInt1 (Line* L, LineColl* LC, unsigned Used, unsigned Unused);
 /* Subfunction for RegValUsed. Will be called recursively in case of branches. */
 
+static Line* NewLineAfter (Line* LineBefore, const char* Format, ...) attribute ((format(printf,2,3)));
+/* Create a new line, insert it after L and return it. The new line is marked
+ * as code line.
+ */
+
+static Line* ReplaceLine (Line* L, const char* Format, ...)
+       attribute ((format(printf,2,3)));
+/* Replace one line by another */
+
 
 
 /*****************************************************************************/
-/*                                       List stuff                                 */
+/*                                       List stuff                                 */
 /*****************************************************************************/
 
 
@@ -559,7 +578,7 @@ static int IsCondJump (Line* L)
 
 
 
-static int IsXIndAddrMode (Line* L)
+static int IsXAddrMode (Line* L)
 /* Return true if the given line does use the X register */
 {
     unsigned Len = strlen (L->Line);
@@ -569,15 +588,15 @@ static int IsXIndAddrMode (Line* L)
 
 
 
-static int NoXIndAddrMode (Line* L)
+static int NoXAddrMode (Line* L)
 /* Return true if the given line does use the X register */
 {
-    return !IsXIndAddrMode (L);
+    return !IsXAddrMode (L);
 }
 
 
 
-static int IsYIndAddrMode (Line* L)
+static int IsYAddrMode (Line* L)
 /* Return true if the given line does use the Y register */
 {
     unsigned Len = strlen (L->Line);
@@ -779,7 +798,13 @@ static unsigned EstimateDataSize (Line* L, unsigned Chunk)
 static unsigned EstimateSize (Line* L)
 /* Estimate the size of an instruction */
 {
-    static const char* Transfers [] = {
+    static const char* OneByteCmds [] = {
+       "\tdea",
+       "\tdex",
+       "\tdey",
+       "\tina",
+       "\tinx",
+       "\tiny"
        "\ttax",
        "\ttay",
        "\ttsx",
@@ -819,7 +844,7 @@ static unsigned EstimateSize (Line* L)
     if (LineMatchX (L, LongBranches) >= 0) {
        return 5;
     }
-    if (LineMatchX (L, Transfers) >= 0) {
+    if (LineMatchX (L, OneByteCmds) >= 0) {
        return 1;
     }
     return 3;
@@ -1091,7 +1116,7 @@ static unsigned RVUInt2 (Line* L,
        do {
 
            /* Handle jumps to local labels (continue there) */
-                   if (LineMatch (L, "\tjmp\tL")) {
+                   if (LineMatch (L, "\tjmp\tL") || LineMatch (L, "\tbra\tL")) {
                /* Get the target of the jump */
                L = GetTargetLine (L->Line+5);
            }
@@ -1101,33 +1126,33 @@ static unsigned RVUInt2 (Line* L,
 
            /* Bail out if we're done */
            if (L == 0 || IsLabel (L)) {
-               /* Something is wrong */
-               return REG_ALL;
+               /* Something is wrong */
+               return REG_ALL;
            }
 
            /* 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;
+               goto ExitPoint;
            }
 
-       } while (LineMatch (L, "\tjmp\tL"));
+       } while (LineMatch (L, "\tjmp\tL") || LineMatch (L, "\tbra\tL"));
 
        /* Special handling for branches */
        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;
+               /* 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 */
+               U1 = RVUInt1 (L, LC, Used, Unused);
+               return U1 | U2;         /* Used in any of the branches */
            }
        }
 
@@ -1141,9 +1166,9 @@ static unsigned RVUInt2 (Line* L,
 
        /* Evaluate the use flags, check for addressing modes */
        R = CmdDesc[I].Use;
-       if (IsXIndAddrMode (L)) {
+       if (IsXAddrMode (L)) {
            R |= REG_X;
-       } else if (IsYIndAddrMode (L)) {
+       } else if (IsYAddrMode (L)) {
            R |= REG_Y;
        }
        if (R) {
@@ -1323,7 +1348,7 @@ static void OptCompares1 (void)
                 (Cond = TosCmpFunc (L2[4])) >= 0) {
 
            /* Replace it */
-           if (IsXIndAddrMode (L2[0])) {
+           if (IsXAddrMode (L2[0])) {
                /* The load is X indirect, so we may not remove the load
                 * of the X register.
                 */
@@ -1377,7 +1402,7 @@ static void OptCompares1 (void)
            Offs = GetHexNum (L2[2]->Line+7) - 2;
 
            /* Replace it */
-           if (IsXIndAddrMode (L2[0])) {
+           if (IsXAddrMode (L2[0])) {
                /* The load is X indirect, so we may not remove the load
                 * of the X register.
                 */
@@ -1637,7 +1662,7 @@ static void OptLoads (void)
                 LineFullMatch (L2 [1], "\tjsr\tpushax")) {
 
            /* Be sure, X is not used in the load */
-           if (NoXIndAddrMode (L2 [0])) {
+           if (NoXAddrMode (L2 [0])) {
 
                /* Replace the subroutine call */
                L2 [1] = ReplaceLine (L2 [1], "\tjsr\tpusha0");
@@ -1667,7 +1692,7 @@ static void OptLoads (void)
                 LineMatch (L2 [1], "\tcmp\t#$")) {
 
            /* Be sure, X is not used in the load */
-           if (NoXIndAddrMode (L2 [0])) {
+           if (NoXAddrMode (L2 [0])) {
 
                /* Remove the unnecessary load */
                FreeLine (L);
@@ -1693,7 +1718,7 @@ static void OptLoads (void)
                         LineFullMatch (L2 [1], "\tjsr\tbnega")) {
 
            /* Be sure, X is not used in the load */
-           if (NoXIndAddrMode (L2 [0])) {
+           if (NoXAddrMode (L2 [0])) {
 
                /* Remove the unnecessary load */
                FreeLine (L);
@@ -1746,7 +1771,7 @@ static void OptRegLoads (void)
 
            /* Search for a load of Y and check if the value is used later */
            else if (LineMatch (L, "\tldy\t")           &&
-                              !RegYUsed (L)                    &&
+                              !RegYUsed (L)                    &&
                       !IsCondJump (NextInstruction (L))) {
 
                /* Remember to delete this line */
@@ -1832,8 +1857,8 @@ static int OptPtrOps1 (Line** Start)
            /* Cannot get lines */
            return 0;
        }
-       if (LineFullMatch (L2[3], "\tclc")                      &&
-           LineMatch (L2[4], "\tadc\t#$")                      &&
+       if (LineFullMatch (L2[3], "\tclc")                      &&
+           LineMatch (L2[4], "\tadc\t#$")                      &&
            LineFullMatch (L2[5], "\tbcc\t*+3")                 &&
            LineFullMatch (L2[6], "\tinx")) {
            /* Inlined increment */
@@ -1847,9 +1872,9 @@ static int OptPtrOps1 (Line** Start)
     }
 
     /* Check for the remainder */
-    if (!LineMatch (L3[0], "\tsta\t")                          ||
+    if (!LineMatch (L3[0], "\tsta\t")                          ||
        strcmp (L3[0]->Line+5, L->Line+5) != 0                  ||
-       !LineMatch (L3[1], "\tstx\t")                           ||
+       !LineMatch (L3[1], "\tstx\t")                           ||
        strcmp (L3[1]->Line+5, L2[0]->Line+5) != 0              ||
        !LineFullMatch (L3[2], "\tlda\tregsave")                ||
        !LineFullMatch (L3[3], "\tldx\tregsave+1")) {
@@ -1859,18 +1884,14 @@ static int OptPtrOps1 (Line** Start)
     }
 
     /* Check if AX is actually used following the code above. If not,
-     * we don't need to load A/X from regsave. Since X will never by
+     * we don't need to load A/X from regsave. Since X will never be
      * used without A, check just for A.
      */
-    NeedLoad = 1;
-    if (!RegAUsed (L3[3])) {
-       /* We don't need to load regsave */
-       NeedLoad = 0;
-    }
+    NeedLoad = RegAUsed (L3[3]);
 
     /* Special code for register variables */
     Done = 0;
-    if (LineMatch (L, "\tlda\tregbank+")       &&
+    if (LineMatch (L, "\tlda\tregbank+")       &&
                GetNextCodeLines (L3[3], &L3[4], 1)     &&
        Inc == 1) {
 
@@ -2029,8 +2050,8 @@ static int OptPtrOps1 (Line** Start)
 
        /* If we need to load a/x, add the code */
        if (NeedLoad) {
-           L = NewLineAfter (L, "\ttax");
            L = NewLineAfter (L, "\tlda\tptr1");
+           L = NewLineAfter (L, "\tldx\tptr1+1");
        }
     }
 
@@ -2144,11 +2165,7 @@ static int OptPtrOps2 (Line** Start)
      * we don't need to load A/X from regsave. Since X will never by
      * used without A, check just for A.
      */
-    NeedLoad = 1;
-    if (!RegAUsed (L3[0])) {
-       /* We don't need to load regsave */
-       NeedLoad = 0;
-    }
+    NeedLoad = RegAUsed (L3[0]);
 
     /* Replace the ldy instruction, offset must point to the low byte */
     sprintf (L->Line+7, "%02X", Offs);
@@ -2238,8 +2255,8 @@ static int OptPtrOps2 (Line** Start)
 
     /* If we need to load a/x, add the code */
     if (NeedLoad) {
-       L = NewLineAfter (L, "\ttax");
        L = NewLineAfter (L, "\tlda\tptr1");
+       L = NewLineAfter (L, "\tldx\tptr1+1");
     }
 
     /* Remove the code that is no longer needed */
@@ -3520,7 +3537,7 @@ static void OptTriples (void)
        "\tjsr\tldaxysp",
        "\tjsr\tldax0sp",
        "\tjsr\tldaysp",
-       "\tjsr\tleaysp",
+       "\tjsr\tleaasp",
        "\tjsr\tldaxi",
        0
     };
@@ -3536,7 +3553,7 @@ static void OptTriples (void)
        "\tjsr\tpushwysp",
                "\tjsr\tpushw0sp",
        "\tjsr\tpushbysp",
-       "\tjsr\tpleaysp",
+       "\tjsr\tpleaasp",
        "\tjsr\tpushw",
     };
 
@@ -3623,6 +3640,9 @@ static Line* OptOneBlock (Line* L)
                }
            }
                } else if (LineMatch (L, "\tadc\t")) {
+           if (CPU == CPU_65C02 && Y == 0 && L->Line[5] == '(' && IsYAddrMode(L)) {
+               L->Line[strlen(L->Line)-2] = '\0';
+           }
            A = -1;
        } else if (LineMatch (L, "\tand\t")) {
            A = -1;
@@ -3630,12 +3650,20 @@ static Line* OptOneBlock (Line* L)
            if (A != -1) {
                A = (A << 1) & 0xFF;
            }
+               } else if (CPU == CPU_65C02 && Y == 0 && L->Line[5] == '(' && IsYAddrMode(L)) {
+           L->Line[strlen(L->Line)-2] = '\0';
+       } else if (CPU == CPU_65C02 && (LineFullMatch (L, "\tdea") ||
+                                       LineFullMatch (L, "\tdec\ta"))) {
+           DEC (A, 1);
        } else if (LineFullMatch (L, "\tdex")) {
            DEC (X, 1);
        } else if (LineFullMatch (L, "\tdey")) {
            DEC (Y, 1);
        } else if (LineMatch (L, "\teor")) {
            A = -1;
+       } else if (CPU == CPU_65C02 && (LineFullMatch (L, "\tina") ||
+                                       LineFullMatch (L, "\tinc\ta"))) {
+           INC (A, 1);
        } else if (LineFullMatch (L, "\tinx")) {
            INC (X, 1);
        } else if (LineFullMatch (L, "\tiny")) {
@@ -3648,6 +3676,27 @@ static Line* OptOneBlock (Line* L)
            /* We know about this function */
            A = X = -1;
            INC (Y, 1);
+       } else if (LineFullMatch (L, "\tjsr\taxulong")) {
+           /* We know about this function and we're trying to replace it by
+            * inline code if we have already a register that contains zero.
+            */
+           char C;
+           if (A == 0) {
+               C = 'a';
+           } else if (X == 0) {
+               C = 'x';
+           } else if (Y == 0) {
+               C = 'y';
+           } else {
+               C = '\0';
+           }
+           if (C == '\0') {
+               /* We cannot replace the code, but we know about the results */
+               Y = 0;
+           } else {
+               L = ReplaceLine (L, "\tst%c\tsreg", C);
+               NewLineAfter (L, "\tst%c\tsreg+1", C);
+           }
        } else if (LineFullMatch (L, "\tjsr\tbnega")) {
            /* We know about this function */
            A = -1;
@@ -3660,12 +3709,35 @@ static Line* OptOneBlock (Line* L)
            /* We know about this function */
            A = -1;
            X = 0;
+       } else if (LineFullMatch (L, "\tjsr\tcomplax")) {
+           /* We know about this function */
+           if (A != -1) {
+               A ^= 0xFF;
+           }
+           if (X != -1) {
+               X ^= 0xFF;
+           }
+       } else if (LineFullMatch (L, "\tjsr\tdecax1")) {
+           /* We know about this function */
+           A = X = -1;
+       } else if (LineFullMatch (L, "\tjsr\tdecax2")) {
+           /* We know about this function */
+           A = X = -1;
+       } else if (LineFullMatch (L, "\tjsr\tdecaxy")) {
+           /* We know about this function */
+           A = X = -1;
+       } else if (LineFullMatch (L, "\tjsr\tdeceaxy")) {
+           /* We know about this function */
+           A = X = -1;
        } else if (LineFullMatch (L, "\tjsr\tincax1")) {
            /* We know about this function */
            A = X = -1;
        } else if (LineFullMatch (L, "\tjsr\tincax2")) {
            /* We know about this function */
            A = X = -1;
+       } else if (LineFullMatch (L, "\tjsr\tinceaxy")) {
+           /* We know about this function */
+           A = X = -1;
        } else if (LineFullMatch (L, "\tjsr\tladdeq")) {
            /* We know about this function */
            A = X = -1;
@@ -3674,6 +3746,17 @@ static Line* OptOneBlock (Line* L)
            /* We know about this function */
            A = X = -1;
            Y = 3;
+       } else if (LineFullMatch (L, "\tjsr\tlbneg")) {
+           /* We know about this function */
+                   A = -1;
+           X = 0;
+       } else if (LineFullMatch (L, "\tjsr\tldai")) {
+           /* We know about this function */
+           A = X = -1;
+           Y = 0;
+       } else if (LineFullMatch (L, "\tjsr\tldaidx")) {
+           /* We know about this function */
+           A = X = -1;
        } else if (LineFullMatch (L, "\tjsr\tldau00sp")) {
            /* We know about this function */
            A = -1;
@@ -3734,6 +3817,12 @@ static Line* OptOneBlock (Line* L)
            /* We know about this function */
            A = X = -1;
            Y = 3;
+               } else if (LineFullMatch (L, "\tjsr\tnegax")) {
+           /* We know about this function */
+           A = X = -1;
+               } else if (LineFullMatch (L, "\tjsr\tnegeax")) {
+           /* We know about this function */
+           A = X = -1;
        } else if (LineFullMatch (L, "\tjsr\tpush0")) {
            /* We know about this function */
            A = 0;
@@ -3777,10 +3866,6 @@ static Line* OptOneBlock (Line* L)
        } else if (LineFullMatch (L, "\tjsr\tpusha")) {
            /* We know about this function */
            Y = 0;
-       } else if (LineFullMatch (L, "\tjsr\tpusha0")) {
-           /* We know about this function */
-           X = 0;
-           Y = 1;
        } else if (LineFullMatch (L, "\tjsr\tpusha0")) {
            /* We know about this function
             * If X is already zero, we may call pushax instead and save two
@@ -3794,6 +3879,10 @@ static Line* OptOneBlock (Line* L)
        } else if (LineFullMatch (L, "\tjsr\tpushax")) {
            /* We know about this function */
            Y = 1;
+       } else if (LineFullMatch (L, "\tjsr\tpushaysp")) {
+           /* We know about this function */
+           A = -1;
+           Y = 0;
        } else if (LineFullMatch (L, "\tjsr\tpushc0")) {
            /* We know about this function */
            A = 0;
@@ -3822,6 +3911,30 @@ static Line* OptOneBlock (Line* L)
            /* We know about this function (calls pushax) */
            A = X = -1;
            Y = 1;
+       } else if (LineFullMatch (L, "\tjsr\tresteax")) {
+           /* We know about this function */
+           A = X = -1;
+       } else if (LineFullMatch (L, "\tjsr\tsaveeax")) {
+           /* We know about this function */
+           /* Changes nothing */
+       } else if (LineFullMatch (L, "\tjsr\tshrax1")) {
+           /* We know about this function */
+           A = X = -1;
+       } else if (LineFullMatch (L, "\tjsr\tshrax2")) {
+           /* We know about this function */
+           A = X = -1;
+       } else if (LineFullMatch (L, "\tjsr\tshrax3")) {
+           /* We know about this function */
+           A = X = -1;
+       } else if (LineFullMatch (L, "\tjsr\tshreax1")) {
+           /* We know about this function */
+           A = X = -1;
+       } else if (LineFullMatch (L, "\tjsr\tshreax2")) {
+           /* We know about this function */
+           A = X = -1;
+       } else if (LineFullMatch (L, "\tjsr\tshreax3")) {
+           /* We know about this function */
+           A = X = -1;
        } else if (LineFullMatch (L, "\tjsr\tstaspp")) {
            /* We know about this function */
            Y = -1;
@@ -3842,6 +3955,14 @@ static Line* OptOneBlock (Line* L)
            /* We know about this function */
            A = X = -1;
            INC (Y, 1);
+       } else if (LineFullMatch (L, "\tjsr\ttosadda0")) {
+           /* We know about this function */
+           A = X = -1;
+                   Y = 1;
+       } else if (LineFullMatch (L, "\tjsr\ttosaddax")) {
+           /* We know about this function */
+           A = X = -1;
+                   Y = 1;
        } else if (LineFullMatch (L, "\tjsr\ttosicmp")) {
            /* We know about this function */
            A = X = -1;
@@ -3860,7 +3981,7 @@ static Line* OptOneBlock (Line* L)
                /* The value loaded is not used later, remove it */
                Delete = 1;
            } else if (LineMatch (L, "\tlda\t(")) {
-               if (IsXIndAddrMode (L)) {
+               if (IsXAddrMode (L)) {
                    /* lda (zp,x) - if Y and X are both zero, replace by
                     * load indirect y and save one cycle in some cases.
                     */
@@ -3893,6 +4014,13 @@ static Line* OptOneBlock (Line* L)
                } else if (NewVal == Y) {
                    /* Requested value is already in Y */
                    L = ReplaceLine (L, "\ttya");
+               } else if (CPU == CPU_65C02 && A != -1) {
+                   /* Try ina/dea operators of 65C02 */
+                   if (NewVal == ((A - 1) & 0xFF)) {
+                       L = ReplaceLine (L, "\tdea");
+                   } else if (NewVal == ((A + 1) & 0xFF)) {
+                       L = ReplaceLine (L, "\tina");
+                   }
                }
                /* Anyway, the new value is now in A */
                A = NewVal;
@@ -3976,7 +4104,26 @@ static Line* OptOneBlock (Line* L)
        } else if (LineFullMatch (L, "\trti")) {
            A = X = Y = -1;
        } else if (LineMatch (L, "\tsbc\t")) {
+           if (CPU == CPU_65C02 && Y == 0 && L->Line[5] == '(' && IsYAddrMode(L)) {
+               L->Line[strlen(L->Line)-2] = '\0';
+           }
            A = -1;
+       } else if (CPU == CPU_65C02 && LineMatch (L, "\tst")) {
+           /* Try to replace by stz if possible */
+           if (A == 0 && LineMatch (L, "\tsta\t")) {
+               /* Not indirect and not Y allowed */
+               if (L->Line[5] != '(' && !IsYAddrMode (L)) {
+                   L->Line[3] = 'z';
+               }
+           } else if (X == 0 && LineMatch (L, "\tstx\t")) {
+               /* absolute,y not allowed */
+               if (!IsYAddrMode (L)) {
+                   L->Line[3] = 'z';
+               }
+           } else if (Y == 0 && LineMatch (L, "\tsty\t")) {
+               /* sty and stz share all addressing modes */
+               L->Line[3] = 'z';
+           }
        } else if (LineFullMatch (L, "\ttax")) {
            if (A != -1 && X == A) {
                /* Load has no effect */
@@ -4068,6 +4215,26 @@ static void OptJumps (void)
        }
        L = NextCodeLine (L);
     }
+
+    /* Special treatment for jumps on the 65C02 */
+    if (CPU == CPU_65C02) {
+
+       Line* L = FirstCode;
+       while (L) {
+           if (LineMatch (L, "\tjmp\tL")) {
+               Line* Target = GetTargetLine (L->Line+5);
+               unsigned Distance = GetJumpDistance (L, Target);
+               if (Distance < 123) {           /* Safety */
+                           L->Line [1] = 'b';          /* Make a short branch */
+                   L->Line [2] = 'r';
+                   L->Line [3] = 'a';
+                   L->Size = 2;                /* Set new size */
+               }
+           }
+           L = NextCodeLine (L);
+       }
+
+    }
 }