]> git.sur5r.net Git - cc65/blobdiff - src/cc65/codegen.c
Renamed ExprDesc.Val to ExprDesc.IVal. Added an FVal field for a floating
[cc65] / src / cc65 / codegen.c
index 7732f7f3437f794049b623a23a099fd6633e4c84..88cebe9a4b734ead469354eb1fb8d466a06a88f9 100644 (file)
@@ -6,9 +6,9 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 1998-2001 Ullrich von Bassewitz                                       */
-/*               Wacholderweg 14                                             */
-/*               D-70597 Stuttgart                                           */
+/* (C) 1998-2004 Ullrich von Bassewitz                                       */
+/*               Römerstraße 52                                              */
+/*               D-70794 Filderstadt                                         */
 /* EMail:        uz@cc65.org                                                 */
 /*                                                                           */
 /*                                                                           */
@@ -39,6 +39,8 @@
 
 /* common */
 #include "check.h"
+#include "cpu.h"
+#include "strbuf.h"
 #include "version.h"
 #include "xmalloc.h"
 #include "xsprintf.h"
 /* cc65 */
 #include "asmcode.h"
 #include "asmlabel.h"
+#include "casenode.h"
 #include "codeseg.h"
-#include "cpu.h"
 #include "dataseg.h"
 #include "error.h"
 #include "global.h"
 #include "segments.h"
+#include "stackptr.h"
 #include "textseg.h"
 #include "util.h"
 #include "codegen.h"
 
 
 
-/*****************************************************************************/
-/*                                  Data                                    */
-/*****************************************************************************/
-
-
-
-/* Compiler relative stack pointer */
-int oursp      = 0;
-
-
-
 /*****************************************************************************/
 /*                                         Helpers                                  */
 /*****************************************************************************/
@@ -94,45 +86,53 @@ static void CheckLocalOffs (unsigned Offs)
 
 
 
-static char* GetLabelName (unsigned flags, unsigned long label, unsigned offs)
+static const char* GetLabelName (unsigned Flags, unsigned long Label, long Offs)
 {
-    static char lbuf [128];            /* 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 */
-           sprintf (lbuf, "%s+%u", 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 */
-           sprintf (lbuf, "_%s+%u", (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 */
-           sprintf (lbuf, "$%04X", (unsigned)((label+offs) & 0xFFFF));
+           xsprintf (Buf, sizeof (Buf), "$%04X", (int)((Label+Offs) & 0xFFFF));
            break;
 
        case CF_REGVAR:
            /* Variable in register bank */
-           sprintf (lbuf, "regbank+%u", (unsigned)((label+offs) & 0xFFFF));
+           xsprintf (Buf, sizeof (Buf), "regbank+%u", (unsigned)((Label+Offs) & 0xFFFF));
            break;
 
        default:
-           Internal ("Invalid address flags");
+           Internal ("Invalid address flags: %04X", Flags);
     }
 
     /* Return a pointer to the static buffer */
-    return lbuf;
+    return Buf;
 }
 
 
 
 /*****************************************************************************/
-/*                           Pre- and postamble                             */
+/*                           Pre- and postamble                             */
 /*****************************************************************************/
 
 
@@ -147,18 +147,26 @@ void g_preamble (void)
     /* Identify the compiler version */
     AddTextLine (";");
     AddTextLine ("; File generated by cc65 v %u.%u.%u",
-                VER_MAJOR, VER_MINOR, VER_PATCH);
+                VER_MAJOR, VER_MINOR, VER_PATCH);
     AddTextLine (";");
 
     /* Insert some object file options */
     AddTextLine ("\t.fopt\t\tcompiler,\"cc65 v %u.%u.%u\"",
-                   VER_MAJOR, VER_MINOR, VER_PATCH);
+                   VER_MAJOR, VER_MINOR, VER_PATCH);
 
     /* If we're producing code for some other CPU, switch the command set */
-    if (CPU == CPU_65C02) {
-       AddTextLine ("\t.pc02");
+    switch (CPU) {
+        case CPU_6502:      AddTextLine ("\t.setcpu\t\t\"6502\"");      break;
+        case CPU_6502X:     AddTextLine ("\t.setcpu\t\t\"6502X\"");     break;
+        case CPU_65SC02:    AddTextLine ("\t.setcpu\t\t\"65SC02\"");    break;
+        case CPU_65C02:     AddTextLine ("\t.setcpu\t\t\"65C02\"");     break;
+        case CPU_65816:     AddTextLine ("\t.setcpu\t\t\"65816\"");     break;
+        default:            Internal ("Unknown CPU: %d", CPU);
     }
 
+    /* Use smart mode */
+    AddTextLine ("\t.smart\t\ton");
+
     /* Allow auto import for runtime library routines */
     AddTextLine ("\t.autoimport\ton");
 
@@ -169,7 +177,7 @@ void g_preamble (void)
     AddTextLine ("\t.debuginfo\t%s", (DebugInfo != 0)? "on" : "off");
 
     /* Import the stack pointer for direct auto variable access */
-    AddTextLine ("\t.importzp\tsp, sreg, regsave, regbank, tmp1, ptr1");
+    AddTextLine ("\t.importzp\tsp, sreg, regsave, regbank, tmp1, ptr1, ptr2");
 
     /* Define long branch macros */
     AddTextLine ("\t.macpack\tlongbranch");
@@ -220,15 +228,11 @@ void g_usebss (void)
 
 
 
-void g_segname (segment_t Seg, const char* Name)
-/* Set the name of a segment */
+void g_segname (segment_t Seg)
+/* Emit the name of a segment if necessary */
 {
-    DataSeg* S;
-
-    /* Remember the new name */
-    NewSegName (Seg, Name);
-
     /* Emit a segment directive for the data style segments */
+    DataSeg* S;
     switch (Seg) {
        case SEG_RODATA: S = CS->ROData; break;
        case SEG_DATA:   S = CS->Data;   break;
@@ -236,7 +240,7 @@ void g_segname (segment_t Seg, const char* Name)
        default:         S = 0;          break;
     }
     if (S) {
-               DS_AddLine (S, ".segment\t\"%s\"", Name);
+               DS_AddLine (S, ".segment\t\"%s\"", GetSegName (Seg));
     }
 }
 
@@ -262,6 +266,9 @@ unsigned sizeofarg (unsigned flags)
        case CF_LONG:
            return 4;
 
+        case CF_FLOAT:
+            return 4;
+
        default:
            typeerror (flags);
            /* NOTREACHED */
@@ -274,7 +281,7 @@ unsigned sizeofarg (unsigned flags)
 int pop (unsigned flags)
 /* Pop an argument of the given size */
 {
-    return oursp += sizeofarg (flags);
+    return StackPtr += sizeofarg (flags);
 }
 
 
@@ -282,7 +289,7 @@ int pop (unsigned flags)
 int push (unsigned flags)
 /* Push an argument of the given size */
 {
-    return oursp -= sizeofarg (flags);
+    return StackPtr -= sizeofarg (flags);
 }
 
 
@@ -377,6 +384,14 @@ void g_defimport (const char* Name, int ZP)
 
 
 
+void g_importmainargs (void)
+/* Forced import of a special symbol that handles arguments to main */
+{
+    AddTextLine ("\t.forceimport\tinitmainargs");
+}
+
+
+
 /*****************************************************************************/
 /*                          Load functions for various registers                    */
 /*****************************************************************************/
@@ -439,21 +454,22 @@ void g_leave (void)
 /* Function epilogue */
 {
     /* How many bytes of locals do we have to drop? */
-    int k = -oursp;
+    unsigned k = (unsigned) -StackPtr;
 
     /* If we didn't have a variable argument list, don't call leave */
     if (funcargs >= 0) {
 
-       /* Drop stackframe if needed */
+       /* Drop stackframe if needed. We can only drop 255 bytes at a time. */
        k += funcargs;
-               if (k > 0) {
-           if (k <= 8) {
-           AddCodeLine ("jsr incsp%d", k);
+               while (k > 0) {
+            unsigned ToDrop = (k > 255)? 255 : k;
+           if (ToDrop <= 8) {
+               AddCodeLine ("jsr incsp%d", k);
            } else {
-               CheckLocalOffs (k);
-               ldyconst (k);
-               AddCodeLine ("jsr addysp");
+               ldyconst (ToDrop);
+               AddCodeLine ("jsr addysp");
            }
+            k -= ToDrop;
        }
 
     } else {
@@ -463,6 +479,11 @@ void g_leave (void)
            AddCodeLine ("jsr leave");
        } else {
            /* We've a stack frame to drop */
+            while (k > 255) {
+                ldyconst (255);
+                AddCodeLine ("jsr addysp");
+                k -= 255;
+            }
            ldyconst (k);
            AddCodeLine ("jsr leavey");
        }
@@ -475,11 +496,51 @@ void g_leave (void)
 
 
 /*****************************************************************************/
-/*                           Register variables                             */
+/*                                   Register variables                             */
 /*****************************************************************************/
 
 
 
+void g_swap_regvars (int StackOffs, int RegOffs, unsigned Bytes)
+/* Swap a register variable with a location on the stack */
+{
+    /* Calculate the actual stack offset and check it */
+    StackOffs -= StackPtr;
+    CheckLocalOffs (StackOffs);
+
+    /* Generate code */
+    if (Bytes == 1) {
+
+        if (CodeSizeFactor < 165) {
+            ldyconst (StackOffs);
+            ldxconst (RegOffs);
+            AddCodeLine ("jsr regswap1");
+        } else {
+            ldyconst (StackOffs);
+            AddCodeLine ("lda (sp),y");
+            AddCodeLine ("ldx regbank%+d", RegOffs);
+            AddCodeLine ("sta regbank%+d", RegOffs);
+            AddCodeLine ("txa");
+            AddCodeLine ("sta (sp),y");
+        }
+
+    } else if (Bytes == 2) {
+
+        ldyconst (StackOffs);
+        ldxconst (RegOffs);
+        AddCodeLine ("jsr regswap2");
+
+    } else {
+
+        ldyconst (StackOffs);
+        ldxconst (RegOffs);
+        ldaconst (Bytes);
+        AddCodeLine ("jsr regswap");
+    }
+}
+
+
+
 void g_save_regvars (int RegOffs, unsigned Bytes)
 /* Save register variables */
 {
@@ -512,7 +573,7 @@ void g_save_regvars (int RegOffs, unsigned Bytes)
     }
 
     /* We pushed stuff, correct the stack pointer */
-    oursp -= Bytes;
+    StackPtr -= Bytes;
 }
 
 
@@ -521,37 +582,68 @@ void g_restore_regvars (int StackOffs, int RegOffs, unsigned Bytes)
 /* Restore register variables */
 {
     /* Calculate the actual stack offset and check it */
-    StackOffs -= oursp;
+    StackOffs -= StackPtr;
     CheckLocalOffs (StackOffs);
 
     /* Don't loop for up to two bytes */
     if (Bytes == 1) {
 
-       ldyconst (StackOffs);
-       AddCodeLine ("lda (sp),y");
-       AddCodeLine ("sta regbank%+d", RegOffs);
+               ldyconst (StackOffs);
+               AddCodeLine ("lda (sp),y");
+               AddCodeLine ("sta regbank%+d", RegOffs);
 
     } else if (Bytes == 2) {
 
+               ldyconst (StackOffs);
+               AddCodeLine ("lda (sp),y");
+               AddCodeLine ("sta regbank%+d", RegOffs);
+               AddCodeLine ("iny");
+               AddCodeLine ("lda (sp),y");
+               AddCodeLine ("sta regbank%+d", RegOffs+1);
+
+    } else if (Bytes == 3 && CodeSizeFactor >= 133) {
+
+               ldyconst (StackOffs);
+               AddCodeLine ("lda (sp),y");
+               AddCodeLine ("sta regbank%+d", RegOffs);
+               AddCodeLine ("iny");
+               AddCodeLine ("lda (sp),y");
+               AddCodeLine ("sta regbank%+d", RegOffs+1);
+               AddCodeLine ("iny");
+               AddCodeLine ("lda (sp),y");
+               AddCodeLine ("sta regbank%+d", RegOffs+2);
+
+    } else if (StackOffs <= RegOffs) {
+
+        /* More bytes, but the relation between the register offset in the
+         * register bank and the stack offset allows us to generate short
+         * code that uses just one index register.
+         */
+               unsigned Label = GetLocalLabel ();
        ldyconst (StackOffs);
+               g_defcodelabel (Label);
        AddCodeLine ("lda (sp),y");
-       AddCodeLine ("sta regbank%+d", RegOffs);
-       AddCodeLine ("iny");
-       AddCodeLine ("lda (sp),y");
-       AddCodeLine ("sta regbank%+d", RegOffs+1);
+       AddCodeLine ("sta regbank%+d,y", RegOffs - StackOffs);
+       AddCodeLine ("iny");
+       AddCodeLine ("cpy #$%02X", StackOffs + Bytes);
+       AddCodeLine ("bne %s", LocalLabelName (Label));
 
     } else {
 
-       /* More than two bytes - loop */
-       unsigned Label = GetLocalLabel ();
-       ldyconst (StackOffs+Bytes-1);
-       ldxconst (Bytes);
-       g_defcodelabel (Label);
-       AddCodeLine ("lda (sp),y");
-       AddCodeLine ("sta regbank%+d,x", RegOffs-1);
-       AddCodeLine ("dey");
-       AddCodeLine ("dex");
-       AddCodeLine ("bne %s", LocalLabelName (Label));
+        /* Ok, this is the generic code. We need to save X because the
+         * caller will only save A.
+         */
+               unsigned Label = GetLocalLabel ();
+        AddCodeLine ("stx tmp1");
+       ldyconst (StackOffs + Bytes - 1);
+        ldxconst (Bytes - 1);
+               g_defcodelabel (Label);
+       AddCodeLine ("lda (sp),y");
+               AddCodeLine ("sta regbank%+d,x", RegOffs);
+       AddCodeLine ("dey");
+        AddCodeLine ("dex");
+       AddCodeLine ("bpl %s", LocalLabelName (Label));
+        AddCodeLine ("ldx tmp1");
 
     }
 }
@@ -559,12 +651,12 @@ void g_restore_regvars (int StackOffs, int RegOffs, unsigned Bytes)
 
 
 /*****************************************************************************/
-/*                          Fetching memory cells                           */
+/*                                  Fetching memory cells                           */
 /*****************************************************************************/
 
 
 
-void g_getimmed (unsigned Flags, unsigned long Val, unsigned Offs)
+void g_getimmed (unsigned Flags, unsigned long Val, long Offs)
 /* Load a constant into the primary register */
 {
     unsigned char B1, B2, B3, B4;
@@ -588,46 +680,46 @@ void g_getimmed (unsigned Flags, unsigned long Val, unsigned 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;
-               }
-               if ((Done & 0x04) == 0 && B1 != B3) {
-                   AddCodeLine ("lda #$%02X", B3);
-                   AddCodeLine ("sta sreg");
-                   Done |= 0x04;
-               }
-               if ((Done & 0x08) == 0 && B1 != B4) {
-                   AddCodeLine ("lda #$%02X", B4);
-                   AddCodeLine ("sta sreg+1");
-                   Done |= 0x08;
-               }
-               AddCodeLine ("lda #$%02X", B1);
-               Done |= 0x01;
-               if ((Done & 0x04) == 0) {
-                   CHECK (B1 == B3);
-                   AddCodeLine ("sta sreg");
-               }
-               if ((Done & 0x08) == 0) {
-                   CHECK (B1 == B4);
-                   AddCodeLine ("sta sreg+1");
-               }
+               /* 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);
+                   AddCodeLine ("sta sreg");
+                   Done |= 0x04;
+               }
+               if ((Done & 0x08) == 0 && B1 != B4) {
+                   AddCodeLine ("lda #$%02X", B4);
+                   AddCodeLine ("sta sreg+1");
+                   Done |= 0x08;
+               }
+               AddCodeLine ("lda #$%02X", B1);
+               Done |= 0x01;
+               if ((Done & 0x04) == 0) {
+                   CHECK (B1 == B3);
+                   AddCodeLine ("sta sreg");
+               }
+               if ((Done & 0x08) == 0) {
+                   CHECK (B1 == B4);
+                   AddCodeLine ("sta sreg+1");
+               }
                break;
 
            default:
@@ -638,23 +730,23 @@ void g_getimmed (unsigned Flags, unsigned long Val, unsigned Offs)
 
     } else {
 
-       /* Some sort of label */
-       const char* Label = GetLabelName (Flags, Val, Offs);
+       /* Some sort of label */
+       const char* Label = GetLabelName (Flags, Val, Offs);
 
-       /* Load the address into the primary */
-       AddCodeLine ("lda #<(%s)", Label);
-       AddCodeLine ("ldx #>(%s)", Label);
+       /* Load the address into the primary */
+       AddCodeLine ("lda #<(%s)", Label);
+       AddCodeLine ("ldx #>(%s)", Label);
 
     }
 }
 
 
 
-void g_getstatic (unsigned flags, unsigned long label, unsigned offs)
+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) {
@@ -711,18 +803,14 @@ void g_getstatic (unsigned flags, unsigned long label, unsigned offs)
 void g_getlocal (unsigned flags, int offs)
 /* Fetch specified local object (local var). */
 {
-    offs -= oursp;
+    offs -= StackPtr;
     CheckLocalOffs (offs);
     switch (flags & CF_TYPE) {
 
        case CF_CHAR:
            if ((flags & CF_FORCECHAR) || (flags & CF_TEST)) {
-               if (CPU == CPU_65C02 && offs == 0) {
-                   AddCodeLine ("lda (sp)");
-               } else {
-                   ldyconst (offs);
-                   AddCodeLine ("lda (sp),y");
-               }
+               ldyconst (offs);
+               AddCodeLine ("lda (sp),y");
            } else {
                ldyconst (offs);
                AddCodeLine ("ldx #$00");
@@ -744,30 +832,14 @@ void g_getlocal (unsigned flags, int offs)
                AddCodeLine ("dey");
                AddCodeLine ("ora (sp),y");
            } else {
-               if (CodeSizeFactor > 180) {
-                   ldyconst (offs + 1);
-                   AddCodeLine ("lda (sp),y");
-                   AddCodeLine ("tax");
-                   AddCodeLine ("dey");
-                   AddCodeLine ("lda (sp),y");
-               } else {
-                   if (offs) {
-                       ldyconst (offs+1);
-                               AddCodeLine ("jsr ldaxysp");
-                   } else {
-                       AddCodeLine ("jsr ldax0sp");
-                   }
-               }
+               ldyconst (offs+1);
+               AddCodeLine ("jsr ldaxysp");
            }
            break;
 
        case CF_LONG:
-           if (offs) {
-               ldyconst (offs+3);
-               AddCodeLine ("jsr ldeaxysp");
-           } else {
-               AddCodeLine ("jsr ldeax0sp");
-           }
+           ldyconst (offs+3);
+           AddCodeLine ("jsr ldeaxysp");
                    break;
 
                default:
@@ -811,22 +883,14 @@ void g_getind (unsigned flags, unsigned offs)
                AddCodeLine ("iny");
                AddCodeLine ("ora (ptr1),y");
            } else {
-               if (offs == 0) {
-                   AddCodeLine ("jsr ldaxi");
-               } else {
-                   ldyconst (offs+1);
-                   AddCodeLine ("jsr ldaxidx");
-               }
+               ldyconst (offs+1);
+               AddCodeLine ("jsr ldaxidx");
            }
            break;
 
                case CF_LONG:
-           if (offs == 0) {
-               AddCodeLine ("jsr ldeaxi");
-           } else {
-               ldyconst (offs+3);
-               AddCodeLine ("jsr ldeaxidx");
-           }
+           ldyconst (offs+3);
+           AddCodeLine ("jsr ldeaxidx");
            if (flags & CF_TEST) {
                        AddCodeLine ("jsr tsteax");
            }
@@ -844,7 +908,7 @@ void g_leasp (int offs)
 /* Fetch the address of the specified symbol into the primary register */
 {
     /* Calculate the offset relative to sp */
-    offs -= oursp;
+    offs -= StackPtr;
 
     /* For value 0 we do direct code */
     if (offs == 0) {
@@ -856,7 +920,7 @@ void g_leasp (int offs)
                    AddCodeLine ("jsr leaasp"); /* Load effective address */
                } else {
            unsigned L = GetLocalLabel ();
-                   if (CPU == CPU_65C02 && offs == 1) {
+                   if ((CPUIsets[CPU] & CPU_ISET_65SC02) != 0 && offs == 1) {
                        AddCodeLine ("lda sp");
                        AddCodeLine ("ldx sp+1");
                        AddCodeLine ("ina");
@@ -885,22 +949,18 @@ void g_leavariadic (int Offs)
     unsigned ArgSizeOffs;
 
     /* Calculate the offset relative to sp */
-    Offs -= oursp;
+    Offs -= StackPtr;
 
     /* Get the offset of the parameter which is stored at sp+0 on function
      * entry and check if this offset is reachable with a byte offset.
      */
-    CHECK (oursp <= 0);
-    ArgSizeOffs = -oursp;
+    CHECK (StackPtr <= 0);
+    ArgSizeOffs = -StackPtr;
     CheckLocalOffs (ArgSizeOffs);
 
     /* Get the size of all parameters. */
-    if (ArgSizeOffs == 0 && CPU == CPU_65C02) {
-               AddCodeLine ("lda (sp)");
-    } else {
-               ldyconst (ArgSizeOffs);
-               AddCodeLine ("lda (sp),y");
-    }
+    ldyconst (ArgSizeOffs);
+    AddCodeLine ("lda (sp),y");
 
     /* Add the value of the stackpointer */
     if (CodeSizeFactor > 250) {
@@ -931,11 +991,11 @@ void g_leavariadic (int Offs)
 
 
 
-void g_putstatic (unsigned flags, unsigned long label, unsigned offs)
+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) {
@@ -969,7 +1029,7 @@ void g_putstatic (unsigned flags, unsigned long label, unsigned offs)
 void g_putlocal (unsigned Flags, int Offs, long Val)
 /* Put data into local object. */
 {
-    Offs -= oursp;
+    Offs -= StackPtr;
     CheckLocalOffs (Offs);
     switch (Flags & CF_TYPE) {
 
@@ -977,12 +1037,8 @@ void g_putlocal (unsigned Flags, int Offs, long Val)
            if (Flags & CF_CONST) {
                AddCodeLine ("lda #$%02X", (unsigned char) Val);
            }
-           if (CPU == CPU_65C02 && Offs == 0) {
-               AddCodeLine ("sta (sp)");
-           } else {
-               ldyconst (Offs);
-               AddCodeLine ("sta (sp),y");
-           }
+           ldyconst (Offs);
+           AddCodeLine ("sta (sp),y");
            break;
 
        case CF_INT:
@@ -994,41 +1050,25 @@ void g_putlocal (unsigned Flags, int Offs, long Val)
                    /* Place high byte into X */
                    AddCodeLine ("tax");
                }
-               if (CPU == CPU_65C02 && Offs == 0) {
-                   AddCodeLine ("lda #$%02X", (unsigned char) Val);
-                   AddCodeLine ("sta (sp)");
+               if ((Val & 0xFF) == Offs+1) {
+                   /* The value we need is already in Y */
+                   AddCodeLine ("tya");
+                   AddCodeLine ("dey");
                } else {
-                   if ((Val & 0xFF) == Offs+1) {
-                       /* The value we need is already in Y */
-                       AddCodeLine ("tya");
-                       AddCodeLine ("dey");
-                   } else {
-                       AddCodeLine ("dey");
-                       AddCodeLine ("lda #$%02X", (unsigned char) Val);
-                   }
-                   AddCodeLine ("sta (sp),y");
+                   AddCodeLine ("dey");
+                   AddCodeLine ("lda #$%02X", (unsigned char) Val);
                }
+               AddCodeLine ("sta (sp),y");
            } else {
                if ((Flags & CF_NOKEEP) == 0 || CodeSizeFactor < 160) {
-                   if (Offs) {
-                       ldyconst (Offs);
-                       AddCodeLine ("jsr staxysp");
-                   } else {
-                       AddCodeLine ("jsr stax0sp");
-                   }
+                   ldyconst (Offs);
+                   AddCodeLine ("jsr staxysp");
                } else {
-                   if (CPU == CPU_65C02 && Offs == 0) {
-                       AddCodeLine ("sta (sp)");
-                       ldyconst (1);
-                       AddCodeLine ("txa");
-                       AddCodeLine ("sta (sp),y");
-                   } else {
-                       ldyconst (Offs);
-                       AddCodeLine ("sta (sp),y");
-                       AddCodeLine ("iny");
-                       AddCodeLine ("txa");
-                       AddCodeLine ("sta (sp),y");
-                   }
+                   ldyconst (Offs);
+                   AddCodeLine ("sta (sp),y");
+                   AddCodeLine ("iny");
+                   AddCodeLine ("txa");
+                   AddCodeLine ("sta (sp),y");
                }
            }
            break;
@@ -1037,12 +1077,8 @@ void g_putlocal (unsigned Flags, int Offs, long Val)
            if (Flags & CF_CONST) {
                g_getimmed (Flags, Val, 0);
            }
-           if (Offs) {
-               ldyconst (Offs);
-               AddCodeLine ("jsr steaxysp");
-           } else {
-               AddCodeLine ("jsr steax0sp");
-           }
+           ldyconst (Offs);
+           AddCodeLine ("jsr steaxysp");
            break;
 
                default:
@@ -1177,18 +1213,81 @@ void g_tosint (unsigned flags)
 
 
 
-void g_reglong (unsigned flags)
+void g_regint (unsigned Flags)
+/* Make sure, the value in the primary register an int. Convert if necessary */
+{
+    unsigned L;
+
+    switch (Flags & CF_TYPE) {
+
+       case CF_CHAR:
+            if (Flags & CF_FORCECHAR) {
+                /* Conversion is from char */
+                if (Flags & CF_UNSIGNED) {
+                    AddCodeLine ("ldx #$00");
+                } else {
+                    L = GetLocalLabel();
+                    AddCodeLine ("ldx #$00");
+                    AddCodeLine ("cmp #$80");
+                    AddCodeLine ("bcc %s", LocalLabelName (L));
+                    AddCodeLine ("dex");
+                    g_defcodelabel (L);
+                }
+            }
+            /* FALLTHROUGH */
+
+       case CF_INT:
+       case CF_LONG:
+           break;
+
+       default:
+           typeerror (Flags);
+    }
+}
+
+
+
+void g_reglong (unsigned Flags)
 /* Make sure, the value in the primary register a long. Convert if necessary */
 {
-    switch (flags & CF_TYPE) {
+    unsigned L;
+
+    switch (Flags & CF_TYPE) {
 
        case CF_CHAR:
+            if (Flags & CF_FORCECHAR) {
+                /* Conversion is from char */
+                if (Flags & CF_UNSIGNED) {
+                    if (CodeSizeFactor >= 200) {
+                        AddCodeLine ("ldx #$00");
+                        AddCodeLine ("stx sreg");
+                        AddCodeLine ("stx sreg+1");
+                    } else {
+                        AddCodeLine ("jsr aulong");
+                    }
+                } else {
+                    if (CodeSizeFactor >= 366) {
+                        L = GetLocalLabel();
+                        AddCodeLine ("ldx #$00");
+                        AddCodeLine ("cmp #$80");
+                        AddCodeLine ("bcc %s", LocalLabelName (L));
+                        AddCodeLine ("dex");
+                        g_defcodelabel (L);
+                        AddCodeLine ("stx sreg");
+                        AddCodeLine ("stx sreg+1");
+                    } else {
+                        AddCodeLine ("jsr along");
+                    }
+                }
+            }
+            /* FALLTHROUGH */
+
        case CF_INT:
-           if (flags & CF_UNSIGNED) {
+           if (Flags & CF_UNSIGNED) {
                if (CodeSizeFactor >= 200) {
                    ldyconst (0);
                    AddCodeLine ("sty sreg");
-                   AddCodeLine ("sty sreg+1");
+                   AddCodeLine ("sty sreg+1");
                } else {
                    AddCodeLine ("jsr axulong");
                }
@@ -1201,7 +1300,7 @@ void g_reglong (unsigned flags)
            break;
 
        default:
-           typeerror (flags);
+           typeerror (Flags);
     }
 }
 
@@ -1269,9 +1368,14 @@ unsigned g_typecast (unsigned lhs, unsigned rhs)
     rtype = rhs & CF_TYPE;
 
     /* Check if a conversion is needed */
-    if (ltype == CF_LONG && rtype != CF_LONG && (rhs & CF_CONST) == 0) {
-       /* We must promote the primary register to long */
-       g_reglong (rhs);
+    if ((rhs & CF_CONST) == 0) {
+        if (ltype == CF_LONG && rtype != CF_LONG) {
+            /* We must promote the primary register to long */
+            g_reglong (rhs);
+        } else if (ltype == CF_INT && rtype != CF_INT) {
+            /* We must promote the primary register to int */
+            g_regint (rhs);
+        }
     }
 
     /* Do not need any other action. If the left type is int, and the primary
@@ -1444,7 +1548,7 @@ void g_addlocal (unsigned flags, int offs)
     unsigned L;
 
     /* Correct the offset and check it */
-    offs -= oursp;
+    offs -= StackPtr;
     CheckLocalOffs (offs);
 
     switch (flags & CF_TYPE) {
@@ -1486,13 +1590,13 @@ void g_addlocal (unsigned flags, int offs)
 
 
 
-void g_addstatic (unsigned flags, unsigned long label, unsigned offs)
+void g_addstatic (unsigned flags, unsigned long label, long offs)
 /* Add a static variable to ax */
 {
     unsigned L;
 
     /* Create the correct label name */
-    char* lbuf = GetLabelName (flags, label, offs);
+    const char* lbuf = GetLabelName (flags, label, offs);
 
     switch (flags & CF_TYPE) {
 
@@ -1530,40 +1634,18 @@ void g_addstatic (unsigned flags, unsigned long label, unsigned offs)
 
 
 
-/*****************************************************************************/
-/*            Compares of ax with a variable with fixed address             */
-/*****************************************************************************/
-
-
-
-void g_cmplocal (unsigned flags, int offs)
-/* Compare a local variable to ax */
-{
-    Internal ("g_cmplocal not implemented");
-}
-
-
-
-void g_cmpstatic (unsigned flags, unsigned label, unsigned offs)
-/* Compare a static variable to ax */
-{
-    Internal ("g_cmpstatic not implemented");
-}
-
-
-
 /*****************************************************************************/
 /*                          Special op= functions                           */
 /*****************************************************************************/
 
 
 
-void g_addeqstatic (unsigned flags, unsigned long label, unsigned offs,
+void g_addeqstatic (unsigned flags, unsigned long label, long offs,
                            unsigned long val)
 /* 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) {
@@ -1642,7 +1724,7 @@ void g_addeqstatic (unsigned flags, unsigned long label, unsigned 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 {
@@ -1657,7 +1739,7 @@ void g_addeqstatic (unsigned flags, unsigned long label, unsigned offs,
            } else {
                AddCodeLine ("ldy #<(%s)", lbuf);
                AddCodeLine ("sty ptr1");
-               AddCodeLine ("ldy #>(%s+1)", lbuf);
+               AddCodeLine ("ldy #>(%s)", lbuf);
                AddCodeLine ("jsr laddeq");
            }
                    break;
@@ -1673,7 +1755,7 @@ void g_addeqlocal (unsigned flags, int offs, unsigned long val)
 /* Emit += for a local variable */
 {
     /* Calculate the true offset, check it, load it into Y */
-    offs -= oursp;
+    offs -= StackPtr;
     CheckLocalOffs (offs);
 
     /* Check the size and determine operation */
@@ -1704,23 +1786,35 @@ void g_addeqlocal (unsigned flags, int offs, unsigned long val)
                    /* FALLTHROUGH */
 
                case CF_INT:
-           if (flags & CF_CONST) {
-               g_getimmed (flags, val, 0);
-           }
            ldyconst (offs);
-           AddCodeLine ("jsr addeqysp");
+           if (flags & CF_CONST) {
+               if (CodeSizeFactor >= 400) {
+                   AddCodeLine ("clc");
+                   AddCodeLine ("lda #$%02X", (int)(val & 0xFF));
+                   AddCodeLine ("adc (sp),y");
+                   AddCodeLine ("sta (sp),y");
+                   AddCodeLine ("iny");
+                   AddCodeLine ("lda #$%02X", (int) ((val >> 8) & 0xFF));
+                   AddCodeLine ("adc (sp),y");
+                   AddCodeLine ("sta (sp),y");
+                   AddCodeLine ("tax");
+                   AddCodeLine ("dey");
+                   AddCodeLine ("lda (sp),y");
+               } else {
+                   g_getimmed (flags, val, 0);
+                   AddCodeLine ("jsr addeqysp");
+               }
+           } else {
+               AddCodeLine ("jsr addeqysp");
+           }
                    break;
 
                case CF_LONG:
            if (flags & CF_CONST) {
                g_getimmed (flags, val, 0);
            }
-           if (offs == 0) {
-               AddCodeLine ("jsr laddeq0sp");
-           } else {
-               ldyconst (offs);
-               AddCodeLine ("jsr laddeqysp");
-           }
+           ldyconst (offs);
+           AddCodeLine ("jsr laddeqysp");
                    break;
 
                default:
@@ -1789,12 +1883,12 @@ void g_addeqind (unsigned flags, unsigned offs, unsigned long val)
 
 
 
-void g_subeqstatic (unsigned flags, unsigned long label, unsigned offs,
+void g_subeqstatic (unsigned flags, unsigned long label, long offs,
                            unsigned long val)
 /* 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) {
@@ -1813,10 +1907,9 @@ void g_subeqstatic (unsigned flags, unsigned long label, unsigned offs,
                                AddCodeLine ("sta %s", lbuf);
                            }
                        } else {
+                   AddCodeLine ("eor #$FF");
                            AddCodeLine ("sec");
-                           AddCodeLine ("sta tmp1");
-                           AddCodeLine ("lda %s", lbuf);
-                           AddCodeLine ("sbc tmp1");
+                           AddCodeLine ("adc %s", lbuf);
                            AddCodeLine ("sta %s", lbuf);
                        }
                        if ((flags & CF_UNSIGNED) == 0) {
@@ -1849,13 +1942,12 @@ void g_subeqstatic (unsigned flags, unsigned long label, unsigned offs,
                    AddCodeLine ("lda %s", lbuf);
                }
            } else {
-               AddCodeLine ("sta tmp1");
-               AddCodeLine ("lda %s", lbuf);
-               AddCodeLine ("sbc tmp1");
+               AddCodeLine ("eor #$FF");
+                       AddCodeLine ("adc %s", lbuf);
                AddCodeLine ("sta %s", lbuf);
-                       AddCodeLine ("stx tmp1");
-               AddCodeLine ("lda %s+1", lbuf);
-               AddCodeLine ("sbc tmp1");
+               AddCodeLine ("txa");
+               AddCodeLine ("eor #$FF");
+                       AddCodeLine ("adc %s+1", lbuf);
                AddCodeLine ("sta %s+1", lbuf);
                AddCodeLine ("tax");
                AddCodeLine ("lda %s", lbuf);
@@ -1867,13 +1959,9 @@ void g_subeqstatic (unsigned flags, unsigned long label, unsigned offs,
                if (val < 0x100) {
                    AddCodeLine ("ldy #<(%s)", lbuf);
                    AddCodeLine ("sty ptr1");
-                   AddCodeLine ("ldy #>(%s+1)", lbuf);
-                   if (val == 1) {
-                       AddCodeLine ("jsr lsubeq1");
-                   } else {
-                       AddCodeLine ("lda #$%02X", (unsigned char)val);
-                       AddCodeLine ("jsr lsubeqa");
-                   }
+                   AddCodeLine ("ldy #>(%s)", lbuf);
+                   AddCodeLine ("lda #$%02X", (unsigned char)val);
+                   AddCodeLine ("jsr lsubeqa");
                } else {
                    g_getstatic (flags, label, offs);
                    g_dec (flags, val);
@@ -1882,7 +1970,7 @@ void g_subeqstatic (unsigned flags, unsigned long label, unsigned offs,
            } else {
                AddCodeLine ("ldy #<(%s)", lbuf);
                AddCodeLine ("sty ptr1");
-               AddCodeLine ("ldy #>(%s+1)", lbuf);
+               AddCodeLine ("ldy #>(%s)", lbuf);
                AddCodeLine ("jsr lsubeq");
                    }
                    break;
@@ -1898,7 +1986,7 @@ void g_subeqlocal (unsigned flags, int offs, unsigned long val)
 /* Emit -= for a local variable */
 {
     /* Calculate the true offset, check it, load it into Y */
-    offs -= oursp;
+    offs -= StackPtr;
     CheckLocalOffs (offs);
 
     /* Check the size and determine operation */
@@ -1913,18 +2001,17 @@ void g_subeqlocal (unsigned flags, int offs, unsigned long val)
                    AddCodeLine ("lda (sp),y");
                    AddCodeLine ("sbc #$%02X", (unsigned char)val);
                } else {
-                   AddCodeLine ("sta tmp1");
-                   AddCodeLine ("lda (sp),y");
-                   AddCodeLine ("sbc tmp1");
+                   AddCodeLine ("eor #$FF");
+                   AddCodeLine ("adc (sp),y");
                }
                        AddCodeLine ("sta (sp),y");
                if ((flags & CF_UNSIGNED) == 0) {
-                   unsigned L = GetLocalLabel();
+                   unsigned L = GetLocalLabel();
                    AddCodeLine ("bpl %s", LocalLabelName (L));
-                   AddCodeLine ("dex");
-                   g_defcodelabel (L);
-               }
-                       break;
+                   AddCodeLine ("dex");
+                   g_defcodelabel (L);
+               }
+                       break;
                    }
                    /* FALLTHROUGH */
 
@@ -1932,24 +2019,16 @@ void g_subeqlocal (unsigned flags, int offs, unsigned long val)
            if (flags & CF_CONST) {
                g_getimmed (flags, val, 0);
            }
-           if (offs == 0) {
-               AddCodeLine ("jsr subeq0sp");
-           } else {
-               ldyconst (offs);
-               AddCodeLine ("jsr subeqysp");
-           }
+           ldyconst (offs);
+           AddCodeLine ("jsr subeqysp");
                    break;
 
                case CF_LONG:
            if (flags & CF_CONST) {
                g_getimmed (flags, val, 0);
            }
-           if (offs == 0) {
-               AddCodeLine ("jsr lsubeq0sp");
-           } else {
-               ldyconst (offs);
-               AddCodeLine ("jsr lsubeqysp");
-           }
+           ldyconst (offs);
+           AddCodeLine ("jsr lsubeqysp");
                    break;
 
                default:
@@ -2024,13 +2103,13 @@ void g_subeqind (unsigned flags, unsigned offs, unsigned long val)
 
 
 
-void g_addaddr_local (unsigned flags, int offs)
+void g_addaddr_local (unsigned flags attribute ((unused)), int offs)
 /* Add the address of a local variable to ax */
 {
     unsigned L = 0;
 
     /* Add the offset */
-    offs -= oursp;
+    offs -= StackPtr;
     if (offs != 0) {
        /* We cannot address more then 256 bytes of locals anyway */
        L = GetLocalLabel();
@@ -2058,11 +2137,11 @@ void g_addaddr_local (unsigned flags, int offs)
 
 
 
-void g_addaddr_static (unsigned flags, unsigned long label, unsigned offs)
+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");
@@ -2268,36 +2347,20 @@ void g_test (unsigned flags)
 void g_push (unsigned flags, unsigned long val)
 /* Push the primary register or a constant value onto the stack */
 {
-    unsigned char hi;
-
     if (flags & CF_CONST && (flags & CF_TYPE) != CF_LONG) {
 
        /* We have a constant 8 or 16 bit value */
        if ((flags & CF_TYPE) == CF_CHAR && (flags & CF_FORCECHAR)) {
 
            /* Handle as 8 bit value */
-           if (CodeSizeFactor >= 165 || val > 2) {
-               ldaconst (val);
-               AddCodeLine ("jsr pusha");
-           } else {
-               AddCodeLine ("jsr pushc%d", (int) val);
-           }
+           ldaconst (val);
+           AddCodeLine ("jsr pusha");
 
        } else {
 
            /* Handle as 16 bit value */
-           hi = (unsigned char) (val >> 8);
-           if (val <= 7) {
-               AddCodeLine ("jsr push%u", (unsigned) val);
-           } else if (hi == 0 || hi == 0xFF) {
-               /* Use special function */
-               ldaconst (val);
-                       AddCodeLine ("jsr %s", (hi == 0)? "pusha0" : "pushaFF");
-           } else {
-               /* Long way ... */
-               g_getimmed (flags, val, 0);
-               AddCodeLine ("jsr pushax");
-           }
+           g_getimmed (flags, val, 0);
+           AddCodeLine ("jsr pushax");
        }
 
     } else {
@@ -2371,20 +2434,38 @@ void g_call (unsigned Flags, const char* Label, unsigned ArgSize)
        ldyconst (ArgSize);
     }
     AddCodeLine ("jsr _%s", Label);
-    oursp += ArgSize;          /* callee pops args */
+    StackPtr += ArgSize;               /* callee pops args */
 }
 
 
 
-void g_callind (unsigned Flags, unsigned ArgSize)
-/* Call subroutine with address in AX */
+void g_callind (unsigned Flags, unsigned ArgSize, int Offs)
+/* Call subroutine indirect */
 {
-    if ((Flags & CF_FIXARGC) == 0) {
-       /* Pass arg count */
-       ldyconst (ArgSize);
+    if ((Flags & CF_LOCAL) == 0) {
+       /* Address is in a/x */
+       if ((Flags & CF_FIXARGC) == 0) {
+           /* Pass arg count */
+           ldyconst (ArgSize);
+       }
+       AddCodeLine ("jsr callax");
+    } else {
+       /* The address is on stack, offset is on Val */
+       Offs -= StackPtr;
+       CheckLocalOffs (Offs);
+       AddCodeLine ("pha");
+       AddCodeLine ("ldy #$%02X", Offs);
+       AddCodeLine ("lda (sp),y");
+       AddCodeLine ("sta jmpvec+1");
+       AddCodeLine ("iny");
+       AddCodeLine ("lda (sp),y");
+       AddCodeLine ("sta jmpvec+2");
+       AddCodeLine ("pla");
+       AddCodeLine ("jsr jmpvec");
     }
-    AddCodeLine ("jsr callax");        /* do the call */
-    oursp += ArgSize;                  /* callee pops args */
+
+    /* Callee pops args */
+    StackPtr += ArgSize;
 }
 
 
@@ -2397,54 +2478,7 @@ void g_jump (unsigned Label)
 
 
 
-void g_switch (unsigned Flags)
-/* Output switch statement preamble */
-{
-    switch (Flags & CF_TYPE) {
-
-       case CF_CHAR:
-       case CF_INT:
-           AddCodeLine ("jsr switch");
-           break;
-
-       case CF_LONG:
-           AddCodeLine ("jsr lswitch");
-           break;
-
-       default:
-           typeerror (Flags);
-
-    }
-}
-
-
-
-void g_case (unsigned flags, unsigned label, unsigned long val)
-/* Create table code for one case selector */
-{
-    switch (flags & CF_TYPE) {
-
-       case CF_CHAR:
-       case CF_INT:
-           AddCodeLine (".word $%04X, %s",
-                        (unsigned)(val & 0xFFFF),
-                        LocalLabelName (label));
-                   break;
-
-       case CF_LONG:
-           AddCodeLine (".dword $%08lX", val);
-           AddCodeLine (".word %s", LocalLabelName (label));
-           break;
-
-       default:
-           typeerror (flags);
-
-    }
-}
-
-
-
-void g_truejump (unsigned flags, unsigned label)
+void g_truejump (unsigned flags attribute ((unused)), unsigned label)
 /* Jump to label if zero flag clear */
 {
     AddCodeLine ("jne %s", LocalLabelName (label));
@@ -2452,7 +2486,7 @@ void g_truejump (unsigned flags, unsigned label)
 
 
 
-void g_falsejump (unsigned flags, unsigned label)
+void g_falsejump (unsigned flags attribute ((unused)), unsigned label)
 /* Jump to label if zero flag set */
 {
     AddCodeLine ("jeq %s", LocalLabelName (label));
@@ -2569,7 +2603,7 @@ void g_mul (unsigned flags, unsigned long val)
     if (flags & CF_CONST && (p2 = powerof2 (val)) >= 0) {
        /* Generate a shift instead */
        g_asl (flags, p2);
-       return;
+       return;
     }
 
     /* If the right hand side is const, the lhs is not on stack but still
@@ -2581,50 +2615,78 @@ void g_mul (unsigned flags, unsigned long val)
 
            case CF_CHAR:
                if (flags & CF_FORCECHAR) {
-                   /* Handle some special cases */
-                   switch (val) {
-
-                       case 3:
-                           AddCodeLine ("sta tmp1");
-                           AddCodeLine ("asl a");
-                           AddCodeLine ("clc");
-                           AddCodeLine ("adc tmp1");
-                           return;
-
-                       case 5:
-                           AddCodeLine ("sta tmp1");
-                           AddCodeLine ("asl a");
-                           AddCodeLine ("asl a");
-                           AddCodeLine ("clc");
-                           AddCodeLine ("adc tmp1");
-                           return;
-
-                       case 10:
-                           AddCodeLine ("sta tmp1");
-                           AddCodeLine ("asl a");
-                           AddCodeLine ("asl a");
-                           AddCodeLine ("clc");
-                           AddCodeLine ("adc tmp1");
-                           AddCodeLine ("asl a");
-                           return;
-                   }
-               }
-               /* FALLTHROUGH */
+                   /* Handle some special cases */
+                   switch (val) {
 
-           case CF_INT:
-               break;
+                       case 3:
+                           AddCodeLine ("sta tmp1");
+                           AddCodeLine ("asl a");
+                           AddCodeLine ("clc");
+                           AddCodeLine ("adc tmp1");
+                           return;
 
-           case CF_LONG:
-               break;
+                       case 5:
+                           AddCodeLine ("sta tmp1");
+                           AddCodeLine ("asl a");
+                           AddCodeLine ("asl a");
+                           AddCodeLine ("clc");
+                           AddCodeLine ("adc tmp1");
+                           return;
 
-           default:
-               typeerror (flags);
-       }
+                       case 6:
+                           AddCodeLine ("sta tmp1");
+                           AddCodeLine ("asl a");
+                           AddCodeLine ("clc");
+                           AddCodeLine ("adc tmp1");
+                           AddCodeLine ("asl a");
+                           return;
 
-       /* If we go here, we didn't emit code. Push the lhs on stack and fall
-        * into the normal, non-optimized stuff.
-        */
-       flags &= ~CF_FORCECHAR; /* Handle chars as ints */
+                       case 10:
+                           AddCodeLine ("sta tmp1");
+                           AddCodeLine ("asl a");
+                           AddCodeLine ("asl a");
+                           AddCodeLine ("clc");
+                           AddCodeLine ("adc tmp1");
+                           AddCodeLine ("asl a");
+                           return;
+                   }
+               }
+               /* FALLTHROUGH */
+
+           case CF_INT:
+               switch (val) {
+                   case 3:
+                       AddCodeLine ("jsr mulax3");
+                       return;
+                   case 5:
+                       AddCodeLine ("jsr mulax5");
+                       return;
+                   case 6:
+                       AddCodeLine ("jsr mulax6");
+                       return;
+                   case 7:
+                       AddCodeLine ("jsr mulax7");
+                       return;
+                   case 9:
+                       AddCodeLine ("jsr mulax9");
+                       return;
+                   case 10:
+                       AddCodeLine ("jsr mulax10");
+                       return;
+               }
+               break;
+
+           case CF_LONG:
+               break;
+
+           default:
+               typeerror (flags);
+       }
+
+       /* If we go here, we didn't emit code. Push the lhs on stack and fall
+        * into the normal, non-optimized stuff.
+        */
+       flags &= ~CF_FORCECHAR; /* Handle chars as ints */
        g_push (flags & ~CF_CONST, 0);
 
     }
@@ -2710,36 +2772,52 @@ void g_or (unsigned flags, unsigned long val)
 
            case CF_CHAR:
                if (flags & CF_FORCECHAR) {
-                   if ((val & 0xFF) != 0xFF) {
+                   if ((val & 0xFF) != 0) {
                                AddCodeLine ("ora #$%02X", (unsigned char)val);
                    }
                    return;
                }
                /* FALLTHROUGH */
 
-           case CF_INT:
-               if (val <= 0xFF) {
-                   AddCodeLine ("ora #$%02X", (unsigned char)val);
-                   return;
-               }
-               break;
-
-           case CF_LONG:
-               if (val <= 0xFF) {
-                   AddCodeLine ("ora #$%02X", (unsigned char)val);
-                   return;
-               }
-               break;
+           case CF_INT:
+               if (val <= 0xFF) {
+                    if ((val & 0xFF) != 0) {
+                       AddCodeLine ("ora #$%02X", (unsigned char)val);
+                    }
+               } else if ((val & 0xFF00) == 0xFF00) {
+                    if ((val & 0xFF) != 0) {
+                       AddCodeLine ("ora #$%02X", (unsigned char)val);
+                    }
+                    ldxconst (0xFF);
+                } else if (val != 0) {
+                    AddCodeLine ("ora #$%02X", (unsigned char)val);
+                    AddCodeLine ("pha");
+                    AddCodeLine ("txa");
+                    AddCodeLine ("ora #$%02X", (unsigned char)(val >> 8));
+                    AddCodeLine ("tax");
+                    AddCodeLine ("pla");
+                }
+               return;
 
-           default:
-               typeerror (flags);
-       }
+           case CF_LONG:
+               if (val <= 0xFF) {
+                    if ((val & 0xFF) != 0) {
+                        AddCodeLine ("ora #$%02X", (unsigned char)val);
+                    }
+                   return;
+               }
+               break;
 
-       /* 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);
+           default:
+               typeerror (flags);
+       }
 
+       /* If we go here, we didn't emit code. Push the lhs on stack and fall
+        * into the normal, non-optimized stuff. Note: The standard stuff will
+         * always work with ints.
+        */
+        flags &= ~CF_FORCECHAR;
+               g_push (flags & ~CF_CONST, 0);
     }
 
     /* Use long way over the stack */
@@ -2780,16 +2858,17 @@ void g_xor (unsigned flags, unsigned long val)
                    if (val != 0) {
                        AddCodeLine ("eor #$%02X", (unsigned char)val);
                    }
-                   return;
-               } else if ((val & 0xFF) == 0) {
+                       } else if (val != 0) {
+                    if ((val & 0xFF) != 0) {
+                        AddCodeLine ("eor #$%02X", (unsigned char)val);
+                    }
                    AddCodeLine ("pha");
                    AddCodeLine ("txa");
                    AddCodeLine ("eor #$%02X", (unsigned char)(val >> 8));
                    AddCodeLine ("tax");
                    AddCodeLine ("pla");
-                   return;
                }
-               break;
+               return;
 
            case CF_LONG:
                if (val <= 0xFF) {
@@ -2804,11 +2883,12 @@ void g_xor (unsigned flags, unsigned long val)
                typeerror (flags);
        }
 
-       /* 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);
-
+       /* If we go here, we didn't emit code. Push the lhs on stack and fall
+        * into the normal, non-optimized stuff. Note: The standard stuff will
+         * always work with ints.
+        */
+        flags &= ~CF_FORCECHAR;
+               g_push (flags & ~CF_CONST, 0);
     }
 
     /* Use long way over the stack */
@@ -2817,68 +2897,70 @@ void g_xor (unsigned flags, unsigned long val)
 
 
 
-void g_and (unsigned flags, unsigned long val)
+void g_and (unsigned Flags, unsigned long Val)
 /* Primary = TOS & Primary */
 {
     static char* ops [12] = {
-       0,              "tosanda0",     "tosandax",
-       0,              "tosanda0",     "tosandax",
-       0,              0,              "tosandeax",
-       0,              0,              "tosandeax",
+       0,              "tosanda0",     "tosandax",
+       0,              "tosanda0",     "tosandax",
+       0,              0,              "tosandeax",
+       0,              0,              "tosandeax",
     };
 
     /* If the right hand side is const, the lhs is not on stack but still
      * in the primary register.
      */
-    if (flags & CF_CONST) {
+    if (Flags & CF_CONST) {
 
-       switch (flags & CF_TYPE) {
+       switch (Flags & CF_TYPE) {
 
            case CF_CHAR:
-               if (flags & CF_FORCECHAR) {
-                   AddCodeLine ("and #$%02X", (unsigned char)val);
-                   return;
-               }
-               /* FALLTHROUGH */
+               if (Flags & CF_FORCECHAR) {
+                    if ((Val & 0xFF) != 0xFF) {
+                        AddCodeLine ("and #$%02X", (unsigned char)Val);
+                    }
+                   return;
+               }
+               /* FALLTHROUGH */
            case CF_INT:
-               if ((val & 0xFFFF) != 0xFFFF) {
-                           if (val <= 0xFF) {
-                       ldxconst (0);
-                       if (val == 0) {
-                           ldaconst (0);
-                       } else if (val != 0xFF) {
-                           AddCodeLine ("and #$%02X", (unsigned char)val);
-                       }
-                   } else if ((val & 0xFF00) == 0xFF00) {
-                       AddCodeLine ("and #$%02X", (unsigned char)val);
-                   } else if ((val & 0x00FF) == 0x0000) {
-                       AddCodeLine ("txa");
-                       AddCodeLine ("and #$%02X", (unsigned char)(val >> 8));
-                       AddCodeLine ("tax");
-                       ldaconst (0);
-                   } else {
-                       AddCodeLine ("tay");
-                       AddCodeLine ("txa");
-                       AddCodeLine ("and #$%02X", (unsigned char)(val >> 8));
-                       AddCodeLine ("tax");
-                       AddCodeLine ("tya");
-                       if ((val & 0x00FF) != 0x00FF) {
-                           AddCodeLine ("and #$%02X", (unsigned char)val);
-                       }
-                   }
-               }
+               if ((Val & 0xFFFF) != 0xFFFF) {
+                           if (Val <= 0xFF) {
+                       ldxconst (0);
+                       if (Val == 0) {
+                           ldaconst (0);
+                       } else if (Val != 0xFF) {
+                           AddCodeLine ("and #$%02X", (unsigned char)Val);
+                       }
+                   } else if ((Val & 0xFF00) == 0xFF00) {
+                       AddCodeLine ("and #$%02X", (unsigned char)Val);
+                   } else if ((Val & 0x00FF) == 0x0000) {
+                       AddCodeLine ("txa");
+                       AddCodeLine ("and #$%02X", (unsigned char)(Val >> 8));
+                       AddCodeLine ("tax");
+                       ldaconst (0);
+                   } else {
+                       AddCodeLine ("tay");
+                       AddCodeLine ("txa");
+                       AddCodeLine ("and #$%02X", (unsigned char)(Val >> 8));
+                       AddCodeLine ("tax");
+                       AddCodeLine ("tya");
+                       if ((Val & 0x00FF) != 0x00FF) {
+                           AddCodeLine ("and #$%02X", (unsigned char)Val);
+                       }
+                   }
+               }
                return;
 
            case CF_LONG:
-               if (val <= 0xFF) {
+               if (Val <= 0xFF) {
                    ldxconst (0);
                    AddCodeLine ("stx sreg+1");
                    AddCodeLine ("stx sreg");
-                   if ((val & 0xFF) != 0xFF) {
-                        AddCodeLine ("and #$%02X", (unsigned char)val);
+                   if ((Val & 0xFF) != 0xFF) {
+                        AddCodeLine ("and #$%02X", (unsigned char)Val);
                    }
                    return;
-               } else if (val == 0xFF00) {
+               } else if (Val == 0xFF00) {
                    ldaconst (0);
                    AddCodeLine ("sta sreg+1");
                    AddCodeLine ("sta sreg");
@@ -2887,18 +2969,19 @@ void g_and (unsigned flags, unsigned long val)
                break;
 
            default:
-               typeerror (flags);
+               typeerror (Flags);
        }
 
-       /* 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);
-
+       /* If we go here, we didn't emit code. Push the lhs on stack and fall
+        * into the normal, non-optimized stuff. Note: The standard stuff will
+         * always work with ints.
+        */
+        Flags &= ~CF_FORCECHAR;
+               g_push (Flags & ~CF_CONST, 0);
     }
 
     /* Use long way over the stack */
-    oper (flags, val, ops);
+    oper (Flags, Val, ops);
 }
 
 
@@ -2907,10 +2990,10 @@ void g_asr (unsigned flags, unsigned long val)
 /* Primary = TOS >> Primary */
 {
     static char* ops [12] = {
-       0,              "tosasra0",     "tosasrax",
-       0,              "tosshra0",     "tosshrax",
-       0,              0,              "tosasreax",
-       0,              0,              "tosshreax",
+       0,              "tosasra0",     "tosasrax",
+       0,              "tosshra0",     "tosshrax",
+       0,              0,              "tosasreax",
+       0,              0,              "tosshreax",
     };
 
     /* If the right hand side is const, the lhs is not on stack but still
@@ -2922,61 +3005,69 @@ void g_asr (unsigned flags, unsigned long val)
 
            case CF_CHAR:
            case CF_INT:
-               if (val >= 1 && val <= 4) {
-                   if (flags & CF_UNSIGNED) {
-                       AddCodeLine ("jsr shrax%ld", val);
-                   } else {
-                       AddCodeLine ("jsr asrax%ld", val);
-                   }
-                   return;
-               } else if (val == 8 && (flags & CF_UNSIGNED)) {
+                       if (val >= 8 && (flags & CF_UNSIGNED)) {
                    AddCodeLine ("txa");
                    ldxconst (0);
+                   val -= 8;
+               }
+               if (val == 0) {
+                   /* Done */
                    return;
-               }
-               break;
+               } else if (val >= 1 && val <= 4) {
+                   if (flags & CF_UNSIGNED) {
+                       AddCodeLine ("jsr shrax%ld", val);
+                   } else {
+                       AddCodeLine ("jsr asrax%ld", val);
+                   }
+                   return;
+                       }
+               break;
 
-           case CF_LONG:
-               if (val >= 1 && val <= 4) {
-                   if (flags & CF_UNSIGNED) {
-                       AddCodeLine ("jsr shreax%ld", val);
-                   } else {
-                       AddCodeLine ("jsr asreax%ld", val);
-                   }
+           case CF_LONG:
+               if (val == 0) {
+                   /* Nothing to do */
                    return;
-               } else if (val == 8 && (flags & CF_UNSIGNED)) {
-                   AddCodeLine ("txa");
-                   AddCodeLine ("ldx sreg");
-                   AddCodeLine ("ldy sreg+1");
-                   AddCodeLine ("sty sreg");
-                   AddCodeLine ("ldy #$00");
+               } else if (val >= 1 && val <= 4) {
+                   if (flags & CF_UNSIGNED) {
+                       AddCodeLine ("jsr shreax%ld", val);
+                   } else {
+                       AddCodeLine ("jsr asreax%ld", val);
+                   }
+                   return;
+               } else if (val == 8 && (flags & CF_UNSIGNED)) {
+                   AddCodeLine ("txa");
+                   AddCodeLine ("ldx sreg");
+                   AddCodeLine ("ldy sreg+1");
+                   AddCodeLine ("sty sreg");
+                   AddCodeLine ("ldy #$00");
                    AddCodeLine ("sty sreg+1");
-                   return;
+                   return;
                } else if (val == 16) {
-                   AddCodeLine ("ldy #$00");
-                   AddCodeLine ("ldx sreg+1");
-                   if ((flags & CF_UNSIGNED) == 0) {
-                       unsigned L = GetLocalLabel();
-                       AddCodeLine ("bpl %s", LocalLabelName (L));
-                       AddCodeLine ("dey");
-                       g_defcodelabel (L);
-                   }
+                   AddCodeLine ("ldy #$00");
+                   AddCodeLine ("ldx sreg+1");
+                   if ((flags & CF_UNSIGNED) == 0) {
+                       unsigned L = GetLocalLabel();
+                       AddCodeLine ("bpl %s", LocalLabelName (L));
+                       AddCodeLine ("dey");
+                       g_defcodelabel (L);
+                   }
                    AddCodeLine ("lda sreg");
-                   AddCodeLine ("sty sreg+1");
-                   AddCodeLine ("sty sreg");
-                   return;
-               }
-               break;
-
-           default:
-               typeerror (flags);
-       }
+                   AddCodeLine ("sty sreg+1");
+                   AddCodeLine ("sty sreg");
+                   return;
+               }
+               break;
 
-       /* 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);
+           default:
+               typeerror (flags);
+       }
 
+       /* If we go here, we didn't emit code. Push the lhs on stack and fall
+        * into the normal, non-optimized stuff. Note: The standard stuff will
+         * always work with ints.
+        */
+        flags &= ~CF_FORCECHAR;
+               g_push (flags & ~CF_CONST, 0);
     }
 
     /* Use long way over the stack */
@@ -2989,10 +3080,10 @@ void g_asl (unsigned flags, unsigned long val)
 /* Primary = TOS << Primary */
 {
     static char* ops [12] = {
-       0,              "tosasla0",     "tosaslax",
-       0,              "tosshla0",     "tosshlax",
-       0,              0,              "tosasleax",
-       0,              0,              "tosshleax",
+       0,              "tosasla0",     "tosaslax",
+       0,              "tosshla0",     "tosshlax",
+       0,              0,              "tosasleax",
+       0,              0,              "tosshleax",
     };
 
 
@@ -3005,22 +3096,29 @@ void g_asl (unsigned flags, unsigned long val)
 
            case CF_CHAR:
            case CF_INT:
-               if (val >= 1 && val <= 4) {
+               if (val >= 8) {
+                   AddCodeLine ("tax");
+                   AddCodeLine ("lda #$00");
+                   val -= 8;
+               }
+               if (val == 0) {
+                   /* Done */
+                   return;
+               } else if (val >= 1 && val <= 4) {
                    if (flags & CF_UNSIGNED) {
                        AddCodeLine ("jsr shlax%ld", val);
                    } else {
-                       AddCodeLine ("jsr aslax%ld", val);
+                       AddCodeLine ("jsr aslax%ld", val);
                    }
                    return;
-               } else if (val == 8) {
-                   AddCodeLine ("tax");
-                   AddCodeLine ("lda #$00");
-                   return;
-               }
+               }
                break;
 
            case CF_LONG:
-               if (val >= 1 && val <= 4) {
+               if (val == 0) {
+                   /* Nothing to do */
+                   return;
+               } else if (val >= 1 && val <= 4) {
                    if (flags & CF_UNSIGNED) {
                        AddCodeLine ("jsr shleax%ld", val);
                    } else {
@@ -3028,7 +3126,7 @@ void g_asl (unsigned flags, unsigned long val)
                    }
                    return;
                } else if (val == 8) {
-                   AddCodeLine ("ldy sreg");
+                   AddCodeLine ("ldy sreg");
                    AddCodeLine ("sty sreg+1");
                    AddCodeLine ("stx sreg");
                    AddCodeLine ("tax");
@@ -3047,11 +3145,12 @@ void g_asl (unsigned flags, unsigned long val)
                typeerror (flags);
        }
 
-       /* 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);
-
+       /* If we go here, we didn't emit code. Push the lhs on stack and fall
+        * into the normal, non-optimized stuff. Note: The standard stuff will
+         * always work with ints.
+        */
+        flags &= ~CF_FORCECHAR;
+               g_push (flags & ~CF_CONST, 0);
     }
 
     /* Use long way over the stack */
@@ -3060,22 +3159,30 @@ void g_asl (unsigned flags, unsigned long val)
 
 
 
-void g_neg (unsigned flags)
+void g_neg (unsigned Flags)
 /* Primary = -Primary */
 {
-    switch (flags & CF_TYPE) {
+    switch (Flags & CF_TYPE) {
 
        case CF_CHAR:
+            if (Flags & CF_FORCECHAR) {
+                AddCodeLine ("eor #$FF");
+                AddCodeLine ("clc");
+                AddCodeLine ("adc #$01");
+                return;
+            }
+            /* FALLTHROUGH */
+
        case CF_INT:
            AddCodeLine ("jsr negax");
            break;
 
        case CF_LONG:
-           AddCodeLine ("jsr negeax");
+           AddCodeLine ("jsr negeax");
            break;
 
        default:
-           typeerror (flags);
+           typeerror (Flags);
     }
 }
 
@@ -3105,12 +3212,18 @@ void g_bneg (unsigned flags)
 
 
 
-void g_com (unsigned flags)
+void g_com (unsigned Flags)
 /* Primary = ~Primary */
 {
-    switch (flags & CF_TYPE) {
+    switch (Flags & CF_TYPE) {
 
        case CF_CHAR:
+            if (Flags & CF_FORCECHAR) {
+                AddCodeLine ("eor #$FF");
+                return;
+            }
+            /* FALLTHROUGH */
+
        case CF_INT:
            AddCodeLine ("jsr complax");
            break;
@@ -3120,7 +3233,7 @@ void g_com (unsigned flags)
            break;
 
        default:
-           typeerror (flags);
+           typeerror (Flags);
     }
 }
 
@@ -3140,9 +3253,9 @@ void g_inc (unsigned flags, unsigned long val)
 
        case CF_CHAR:
            if (flags & CF_FORCECHAR) {
-               if (CPU == CPU_65C02 && val <= 2) {
+               if ((CPUIsets[CPU] & CPU_ISET_65SC02) != 0 && val <= 2) {
                    while (val--) {
-                       AddCodeLine ("ina");
+                       AddCodeLine ("ina");
                    }
                } else {
                    AddCodeLine ("clc");
@@ -3153,7 +3266,7 @@ void g_inc (unsigned flags, unsigned long val)
            /* FALLTHROUGH */
 
        case CF_INT:
-           if (CPU == CPU_65C02 && val == 1) {
+           if ((CPUIsets[CPU] & CPU_ISET_65SC02) != 0 && val == 1) {
                unsigned L = GetLocalLabel();
                AddCodeLine ("ina");
                AddCodeLine ("bne %s", LocalLabelName (L));
@@ -3171,14 +3284,14 @@ void g_inc (unsigned flags, unsigned long val)
                }
            } else {
                /* Inline the code */
-               if (val < 0x300) {
+               if (val <= 0x300) {
                    if ((val & 0xFF) != 0) {
-                       unsigned L = GetLocalLabel();
+                       unsigned L = GetLocalLabel();
                        AddCodeLine ("clc");
                        AddCodeLine ("adc #$%02X", (unsigned char) val);
                        AddCodeLine ("bcc %s", LocalLabelName (L));
                        AddCodeLine ("inx");
-                       g_defcodelabel (L);
+                       g_defcodelabel (L);
                    }
                    if (val >= 0x100) {
                        AddCodeLine ("inx");
@@ -3186,6 +3299,9 @@ void g_inc (unsigned flags, unsigned long val)
                    if (val >= 0x200) {
                        AddCodeLine ("inx");
                    }
+                   if (val >= 0x300) {
+                       AddCodeLine ("inx");
+                   }
                } else {
                    AddCodeLine ("clc");
                    if ((val & 0xFF) != 0) {
@@ -3231,7 +3347,7 @@ void g_dec (unsigned flags, unsigned long val)
 
        case CF_CHAR:
            if (flags & CF_FORCECHAR) {
-               if (CPU == CPU_65C02 && val <= 2) {
+               if ((CPUIsets[CPU] & CPU_ISET_65SC02) != 0 && val <= 2) {
                    while (val--) {
                        AddCodeLine ("dea");
                    }
@@ -3315,9 +3431,9 @@ void g_eq (unsigned flags, unsigned long val)
 {
     static char* ops [12] = {
        "toseq00",      "toseqa0",      "toseqax",
-       "toseq00",      "toseqa0",      "toseqax",
-       0,              0,              "toseqeax",
-       0,              0,              "toseqeax",
+       "toseq00",      "toseqa0",      "toseqax",
+       0,              0,              "toseqeax",
+       0,              0,              "toseqeax",
     };
 
     unsigned L;
@@ -3330,19 +3446,19 @@ void g_eq (unsigned flags, unsigned long val)
        switch (flags & CF_TYPE) {
 
            case CF_CHAR:
-               if (flags & CF_FORCECHAR) {
-                   AddCodeLine ("cmp #$%02X", (unsigned char)val);
-                   AddCodeLine ("jsr booleq");
-                   return;
-               }
+               if (flags & CF_FORCECHAR) {
+                   AddCodeLine ("cmp #$%02X", (unsigned char)val);
+                   AddCodeLine ("jsr booleq");
+                   return;
+               }
                /* FALLTHROUGH */
 
            case CF_INT:
-               L = GetLocalLabel();
+               L = GetLocalLabel();
                AddCodeLine ("cpx #$%02X", (unsigned char)(val >> 8));
                        AddCodeLine ("bne %s", LocalLabelName (L));
                AddCodeLine ("cmp #$%02X", (unsigned char)val);
-               g_defcodelabel (L);
+               g_defcodelabel (L);
                AddCodeLine ("jsr booleq");
                return;
 
@@ -3354,10 +3470,11 @@ void g_eq (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.
+        * into the normal, non-optimized stuff. Note: The standard stuff will
+         * always work with ints.
         */
-       g_push (flags & ~CF_CONST, 0);
-
+        flags &= ~CF_FORCECHAR;
+               g_push (flags & ~CF_CONST, 0);
     }
 
     /* Use long way over the stack */
@@ -3394,11 +3511,11 @@ void g_ne (unsigned flags, unsigned long val)
                /* FALLTHROUGH */
 
            case CF_INT:
-               L = GetLocalLabel();
+               L = GetLocalLabel();
                AddCodeLine ("cpx #$%02X", (unsigned char)(val >> 8));
                AddCodeLine ("bne %s", LocalLabelName (L));
                AddCodeLine ("cmp #$%02X", (unsigned char)val);
-               g_defcodelabel (L);
+               g_defcodelabel (L);
                AddCodeLine ("jsr boolne");
                return;
 
@@ -3410,10 +3527,11 @@ void g_ne (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.
+        * into the normal, non-optimized stuff. Note: The standard stuff will
+         * always work with ints.
         */
-       g_push (flags & ~CF_CONST, 0);
-
+        flags &= ~CF_FORCECHAR;
+               g_push (flags & ~CF_CONST, 0);
     }
 
     /* Use long way over the stack */
@@ -3428,7 +3546,7 @@ void g_lt (unsigned flags, unsigned long val)
     static char* ops [12] = {
        "toslt00",      "toslta0",      "tosltax",
        "tosult00",     "tosulta0",     "tosultax",
-       0,              0,              "toslteax",
+       0,              0,              "toslteax",
        0,              0,              "tosulteax",
     };
 
@@ -3437,67 +3555,94 @@ void g_lt (unsigned flags, unsigned long val)
      */
     if (flags & CF_CONST) {
 
-       /* Give a warning in some special cases */
-       if ((flags & CF_UNSIGNED) && val == 0) {
-           Warning ("Condition is never true");
-       }
-
-       /* Look at the type */
-       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 */
-
-           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) {
-                   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;
-               }
-               break;
-
-           case CF_LONG:
-               if ((flags & CF_UNSIGNED) == 0 && val == 0) {
-                   /* If we have a signed compare against zero, we only need to
-                    * test the high byte.
-                    */
-                   AddCodeLine ("lda sreg+1");
-                   AddCodeLine ("jsr boollt");
-                   return;
-               }
-               break;
-
-           default:
-               typeerror (flags);
-       }
-
-       /* 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);
+        /* Because the handling of the overflow flag is too complex for
+         * inlining, we can handle only unsigned compares, and signed
+         * compares against zero here.
+         */
+        if (flags & CF_UNSIGNED) {
+
+            /* Give a warning in some special cases */
+            if (val == 0) {
+                Warning ("Condition is never true");
+                AddCodeLine ("jsr return0");
+                return;
+            }
+
+            /* Look at the type */
+            switch (flags & CF_TYPE) {
+
+                case CF_CHAR:
+                    if (flags & CF_FORCECHAR) {
+                        AddCodeLine ("cmp #$%02X", (unsigned char)val);
+                        AddCodeLine ("jsr boolult");
+                        return;
+                    }
+                    /* FALLTHROUGH */
+
+                case CF_INT:
+                    /* If the low byte is zero, we must only test the high byte */
+                    AddCodeLine ("cpx #$%02X", (unsigned char)(val >> 8));
+                    if ((val & 0xFF) != 0) {
+                        unsigned L = GetLocalLabel();
+                        AddCodeLine ("bne %s", LocalLabelName (L));
+                        AddCodeLine ("cmp #$%02X", (unsigned char)val);
+                        g_defcodelabel (L);
+                    }
+                    AddCodeLine ("jsr boolult");
+                    return;
+
+                case CF_LONG:
+                    /* Do a subtraction */
+                    AddCodeLine ("cmp #$%02X", (unsigned char)val);
+                    AddCodeLine ("txa");
+                    AddCodeLine ("sbc #$%02X", (unsigned char)(val >> 8));
+                    AddCodeLine ("lda sreg");
+                    AddCodeLine ("sbc #$%02X", (unsigned char)(val >> 16));
+                    AddCodeLine ("lda sreg+1");
+                    AddCodeLine ("sbc #$%02X", (unsigned char)(val >> 24));
+                    AddCodeLine ("jsr boolult");
+                    return;
+
+                default:
+                    typeerror (flags);
+            }
+
+        } else if (val == 0) {
+
+            /* Look at the type */
+            switch (flags & CF_TYPE) {
+
+                case CF_CHAR:
+                    if (flags & CF_FORCECHAR) {
+                        AddCodeLine ("tax");
+                        AddCodeLine ("jsr boollt");
+                        return;
+                    }
+                    /* FALLTHROUGH */
+
+                case CF_INT:
+                    /* Just check the high byte */
+                    AddCodeLine ("txa");
+                    AddCodeLine ("jsr boollt");
+                    return;
+
+                case CF_LONG:
+                    /* Just check the high byte */
+                    AddCodeLine ("lda sreg+1");
+                    AddCodeLine ("jsr boollt");
+                    return;
+
+                default:
+                    typeerror (flags);
+            }
+        }
 
+       /* If we go here, we didn't emit code. Push the lhs on stack and fall
+        * into the normal, non-optimized stuff. Note: The standard stuff will
+         * always work with ints.
+        */
+        flags &= ~CF_FORCECHAR;
+               g_push (flags & ~CF_CONST, 0);
     }
 
     /* Use long way over the stack */
@@ -3513,7 +3658,7 @@ void g_le (unsigned flags, unsigned long val)
        "tosle00",      "toslea0",      "tosleax",
        "tosule00",     "tosulea0",     "tosuleax",
        0,              0,              "tosleeax",
-       0,              0,              "tosuleeax",
+       0,              0,              "tosuleeax",
     };
 
 
@@ -3522,65 +3667,100 @@ void g_le (unsigned flags, unsigned long val)
      */
     if (flags & CF_CONST) {
 
-       /* <= is not very effective on the 6502, so try to convert
-        * it into < if the value is in a valid range.
-        */
-
        /* Look at the type */
        switch (flags & CF_TYPE) {
 
            case CF_CHAR:
                if (flags & CF_FORCECHAR) {
                    if (flags & CF_UNSIGNED) {
-                       if (val < 255) {
-                           AddCodeLine ("cmp #$%02X", (unsigned char)val+1);
-                           AddCodeLine ("jsr boolult");
+                       /* Unsigned compare */
+                       if (val < 0xFF) {
+                           /* Use < instead of <= because the former gives
+                            * better code on the 6502 than the latter.
+                            */
+                           g_lt (flags, val+1);
                        } else {
-                           AddCodeLine ("cmp #$%02X", (unsigned char)val);
-                           AddCodeLine ("jsr boolule");
+                           /* Always true */
+                           Warning ("Condition is always true");
+                           AddCodeLine ("jsr return1");
                        }
                    } else {
-                       if (val < 127) {
-                           AddCodeLine ("cmp #$%02X", (unsigned char)val+1);
-                           AddCodeLine ("jsr boollt");
+                       /* Signed compare */
+                       if ((long) val < 0x7F) {
+                           /* Use < instead of <= because the former gives
+                            * better code on the 6502 than the latter.
+                            */
+                           g_lt (flags, val+1);
                        } else {
-                           AddCodeLine ("cmp #$%02X", (unsigned char)val);
-                           AddCodeLine ("jsr boolle");
+                           /* Always true */
+                           Warning ("Condition is always true");
+                           AddCodeLine ("jsr return1");
                        }
-                   }
-                   return;
-               }
-               /* FALLTHROUGH */
-
-           case CF_INT:
-               if (flags & CF_UNSIGNED) {
-                   unsigned L = GetLocalLabel();
-                   const char* Name = "boolule";
-                   if (val < 65535) {
-                       ++val;
-                       Name = "boolult";
-                   }
-                   AddCodeLine ("cpx #$%02X", (unsigned char)(val >> 8));
-                   AddCodeLine ("bne %s", LocalLabelName (L));
-                   AddCodeLine ("cmp #$%02X", (unsigned char)val);
-                   g_defcodelabel (L);
-                   AddCodeLine ("jsr %s", Name);
-                   return;
-               }
-               break;
+                   }
+                   return;
+               }
+               /* FALLTHROUGH */
 
-           case CF_LONG:
-               break;
+           case CF_INT:
+               if (flags & CF_UNSIGNED) {
+                   /* Unsigned compare */
+                   if (val < 0xFFFF) {
+                       /* Use < instead of <= because the former gives
+                        * better code on the 6502 than the latter.
+                        */
+                       g_lt (flags, val+1);
+                   } else {
+                       /* Always true */
+                       Warning ("Condition is always true");
+                       AddCodeLine ("jsr return1");
+                   }
+               } else {
+                   /* Signed compare */
+                   if ((long) val < 0x7FFF) {
+                       g_lt (flags, val+1);
+                   } else {
+                       /* Always true */
+                       Warning ("Condition is always true");
+                       AddCodeLine ("jsr return1");
+                   }
+               }
+               return;
 
-           default:
-               typeerror (flags);
-       }
+           case CF_LONG:
+               if (flags & CF_UNSIGNED) {
+                   /* Unsigned compare */
+                   if (val < 0xFFFFFFFF) {
+                       /* Use < instead of <= because the former gives
+                        * better code on the 6502 than the latter.
+                        */
+                       g_lt (flags, val+1);
+                   } else {
+                       /* Always true */
+                       Warning ("Condition is always true");
+                       AddCodeLine ("jsr return1");
+                   }
+               } else {
+                   /* Signed compare */
+                   if ((long) val < 0x7FFFFFFF) {
+                       g_lt (flags, val+1);
+                   } else {
+                       /* Always true */
+                       Warning ("Condition is always true");
+                       AddCodeLine ("jsr return1");
+                   }
+               }
+               return;
 
-       /* 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);
+           default:
+               typeerror (flags);
+       }
 
+       /* If we go here, we didn't emit code. Push the lhs on stack and fall
+        * into the normal, non-optimized stuff. Note: The standard stuff will
+         * always work with ints.
+        */
+        flags &= ~CF_FORCECHAR;
+               g_push (flags & ~CF_CONST, 0);
     }
 
     /* Use long way over the stack */
@@ -3593,10 +3773,10 @@ 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",
+       0,              0,              "tosgteax",
+       0,              0,              "tosugteax",
     };
 
 
@@ -3605,38 +3785,39 @@ void g_gt (unsigned flags, unsigned long val)
      */
     if (flags & CF_CONST) {
 
-               /* > is not very effective on the 6502, so try to convert
-        * it into >= if the value is in a valid range.
-        */
-
        /* Look at the type */
        switch (flags & CF_TYPE) {
 
            case CF_CHAR:
                if (flags & CF_FORCECHAR) {
                    if (flags & CF_UNSIGNED) {
-                       /* If we have a compare > 0, we will replace it by
-                        * != 0 here, since both are identical but the latter
-                        * is easier to optimize.
-                        */
                                if (val == 0) {
-                           AddCodeLine ("cmp #$%02X", (unsigned char)val);
-                           AddCodeLine ("jsr boolne");
-                       } else if (val < 255) {
-                           AddCodeLine ("cmp #$%02X", (unsigned char)val+1);
-                           AddCodeLine ("jsr booluge");
+                           /* If we have a compare > 0, we will replace it by
+                            * != 0 here, since both are identical but the
+                            * latter is easier to optimize.
+                            */
+                           g_ne (flags, val);
+                       } else if (val < 0xFF) {
+                           /* Use >= instead of > because the former gives
+                            * better code on the 6502 than the latter.
+                            */
+                           g_ge (flags, val+1);
                        } else {
-                           AddCodeLine ("cmp #$%02X", (unsigned char)val);
-                           AddCodeLine ("jsr boolugt");
-                       }
+                           /* Never true */
+                           Warning ("Condition is never true");
+                           AddCodeLine ("jsr return0");
+                       }
                    } else {
-                       if (val < 127) {
-                           AddCodeLine ("cmp #$%02X", (unsigned char)val+1);
-                           AddCodeLine ("jsr boolge");
-                       } else {
-                           AddCodeLine ("cmp #$%02X", (unsigned char)val);
-                           AddCodeLine ("jsr boolgt");
-                       }
+                       if ((long) val < 0x7F) {
+                           /* Use >= instead of > because the former gives
+                            * better code on the 6502 than the latter.
+                            */
+                           g_ge (flags, val+1);
+                       } else {
+                           /* Never true */
+                           Warning ("Condition is never true");
+                           AddCodeLine ("jsr return0");
+                       }
                    }
                    return;
                }
@@ -3644,43 +3825,76 @@ void g_gt (unsigned flags, unsigned long val)
 
            case CF_INT:
                if (flags & CF_UNSIGNED) {
-                   /* If we have a compare > 0, we will replace it by
-                    * != 0 here, since both are identical but the latter
-                    * is easier to optimize.
-                    */
-                   if (val == 0) {
-                       AddCodeLine ("stx tmp1");
-                       AddCodeLine ("ora tmp1");
-                       AddCodeLine ("jsr boolne");
-                   } else {
-                       unsigned L = GetLocalLabel();
-                       const char* Name = "boolugt";
-                       if (val < 65535) {
-                           ++val;
-                           Name = "booluge";
-                       }
-                               AddCodeLine ("cpx #$%02X", (unsigned char)(val >> 8));
-                       AddCodeLine ("bne %s", LocalLabelName (L));
-                       AddCodeLine ("cmp #$%02X", (unsigned char)val);
-                       g_defcodelabel (L);
-                               AddCodeLine ("jsr %s", Name);
-                   }
-                   return;
-                       }
-               break;
-
-           case CF_LONG:
-               break;
+                   /* Unsigned compare */
+                   if (val == 0) {
+                       /* If we have a compare > 0, we will replace it by
+                        * != 0 here, since both are identical but the latter
+                        * is easier to optimize.
+                        */
+                       g_ne (flags, val);
+                   } else if (val < 0xFFFF) {
+                       /* Use >= instead of > because the former gives better
+                        * code on the 6502 than the latter.
+                        */
+                       g_ge (flags, val+1);
+                   } else {
+                       /* Never true */
+                       Warning ("Condition is never true");
+                       AddCodeLine ("jsr return0");
+                   }
+                       } else {
+                   /* Signed compare */
+                   if ((long) val < 0x7FFF) {
+                       g_ge (flags, val+1);
+                   } else {
+                       /* Never true */
+                       Warning ("Condition is never true");
+                       AddCodeLine ("jsr return0");
+                   }
+               }
+               return;
 
-           default:
-               typeerror (flags);
-       }
+           case CF_LONG:
+               if (flags & CF_UNSIGNED) {
+                   /* Unsigned compare */
+                   if (val == 0) {
+                       /* If we have a compare > 0, we will replace it by
+                        * != 0 here, since both are identical but the latter
+                        * is easier to optimize.
+                        */
+                       g_ne (flags, val);
+                   } else if (val < 0xFFFFFFFF) {
+                       /* Use >= instead of > because the former gives better
+                        * code on the 6502 than the latter.
+                        */
+                       g_ge (flags, val+1);
+                   } else {
+                       /* Never true */
+                       Warning ("Condition is never true");
+                       AddCodeLine ("jsr return0");
+                   }
+                       } else {
+                   /* Signed compare */
+                   if ((long) val < 0x7FFFFFFF) {
+                       g_ge (flags, val+1);
+                   } else {
+                       /* Never true */
+                       Warning ("Condition is never true");
+                       AddCodeLine ("jsr return0");
+                   }
+               }
+               return;
 
-       /* 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);
+           default:
+               typeerror (flags);
+       }
 
+       /* If we go here, we didn't emit code. Push the lhs on stack and fall
+        * into the normal, non-optimized stuff. Note: The standard stuff will
+         * always work with ints.
+        */
+        flags &= ~CF_FORCECHAR;
+               g_push (flags & ~CF_CONST, 0);
     }
 
     /* Use long way over the stack */
@@ -3705,67 +3919,95 @@ void g_ge (unsigned flags, unsigned long val)
      */
     if (flags & CF_CONST) {
 
-       /* Give a warning in some special cases */
-       if ((flags & CF_UNSIGNED) && val == 0) {
-           Warning ("Condition is always true");
-       }
+        /* Because the handling of the overflow flag is too complex for
+         * inlining, we can handle only unsigned compares, and signed
+         * compares against zero here.
+         */
+        if (flags & CF_UNSIGNED) {
+
+            /* Give a warning in some special cases */
+            if (val == 0) {
+                Warning ("Condition is always true");
+                AddCodeLine ("jsr return1");
+                return;
+            }
+
+            /* Look at the type */
+            switch (flags & CF_TYPE) {
+
+                case CF_CHAR:
+                    if (flags & CF_FORCECHAR) {
+                        AddCodeLine ("cmp #$%02X", (unsigned char)val);
+                        AddCodeLine ("jsr booluge");
+                        return;
+                    }
+                    /* FALLTHROUGH */
+
+                case CF_INT:
+                    /* If the low byte is zero, we must only test the high byte */
+                    AddCodeLine ("cpx #$%02X", (unsigned char)(val >> 8));
+                    if ((val & 0xFF) != 0) {
+                        unsigned L = GetLocalLabel();
+                        AddCodeLine ("bne %s", LocalLabelName (L));
+                        AddCodeLine ("cmp #$%02X", (unsigned char)val);
+                        g_defcodelabel (L);
+                    }
+                    AddCodeLine ("jsr booluge");
+                    return;
+
+                case CF_LONG:
+                    /* Do a subtraction */
+                    AddCodeLine ("cmp #$%02X", (unsigned char)val);
+                    AddCodeLine ("txa");
+                    AddCodeLine ("sbc #$%02X", (unsigned char)(val >> 8));
+                    AddCodeLine ("lda sreg");
+                    AddCodeLine ("sbc #$%02X", (unsigned char)(val >> 16));
+                    AddCodeLine ("lda sreg+1");
+                    AddCodeLine ("sbc #$%02X", (unsigned char)(val >> 24));
+                    AddCodeLine ("jsr booluge");
+                    return;
+
+                default:
+                    typeerror (flags);
+            }
+
+        } else if (val == 0) {
+
+            /* Look at the type */
+            switch (flags & CF_TYPE) {
+
+                case CF_CHAR:
+                    if (flags & CF_FORCECHAR) {
+                        AddCodeLine ("tax");
+                        AddCodeLine ("jsr boolge");
+                        return;
+                    }
+                    /* FALLTHROUGH */
+
+                case CF_INT:
+                    /* Just test the high byte */
+                    AddCodeLine ("txa");
+                    AddCodeLine ("jsr boolge");
+                    return;
+
+                case CF_LONG:
+                    /* Just test the high byte */
+                    AddCodeLine ("lda sreg+1");
+                    AddCodeLine ("jsr boolge");
+                    return;
+
+                default:
+                    typeerror (flags);
+            }
+        }
 
-       /* Look at the type */
-       switch (flags & CF_TYPE) {
-
-           case CF_CHAR:
-               if (flags & CF_FORCECHAR) {
-                   AddCodeLine ("cmp #$%02X", (unsigned char)val);
-                   if (flags & CF_UNSIGNED) {
-                       AddCodeLine ("jsr booluge");
-                   } else {
-                       AddCodeLine ("jsr boolge");
-                   }
-                   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 boolge");
-                   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 booluge");
-                   return;
-               }
-               break;
-
-           case CF_LONG:
-               if ((flags & CF_UNSIGNED) == 0 && val == 0) {
-                   /* If we have a signed compare against zero, we only need to
-                    * test the high byte.
-                    */
-                   AddCodeLine ("lda sreg+1");
-                   AddCodeLine ("jsr boolge");
-                   return;
-               }
-               break;
-
-           default:
-               typeerror (flags);
-       }
-
-       /* 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);
 
+       /* If we go here, we didn't emit code. Push the lhs on stack and fall
+        * into the normal, non-optimized stuff. Note: The standard stuff will
+         * always work with ints.
+        */
+        flags &= ~CF_FORCECHAR;
+               g_push (flags & ~CF_CONST, 0);
     }
 
     /* Use long way over the stack */
@@ -3788,7 +4030,7 @@ void g_res (unsigned n)
 
 
 
-void g_defdata (unsigned flags, unsigned long val, unsigned offs)
+void g_defdata (unsigned flags, unsigned long val, long offs)
 /* Define data with the size given in flags */
 {
     if (flags & CF_CONST) {
@@ -3820,7 +4062,7 @@ void g_defdata (unsigned flags, unsigned long val, unsigned offs)
        const char* Label = GetLabelName (flags, val, offs);
 
        /* Labels are always 16 bit */
-       AddDataLine ("\t.word\t%s", Label);
+               AddDataLine ("\t.addr\t%s", Label);
 
     }
 }
@@ -3863,80 +4105,178 @@ void g_defbytes (const void* Bytes, unsigned Count)
 
 
 
-void g_zerobytes (unsigned n)
-/* Output n bytes of data initialized with zero */
+void g_zerobytes (unsigned Count)
+/* Output Count bytes of data initialized with zero */
 {
-    AddDataLine ("\t.res\t%u,$00", n);
+    if (Count > 0) {
+        AddDataLine ("\t.res\t%u,$00", Count);
+    }
 }
 
 
 
-/*****************************************************************************/
-/*                      User supplied assembler code                        */
-/*****************************************************************************/
+void g_initregister (unsigned Label, unsigned Reg, unsigned Size)
+/* Initialize a register variable from static initialization data */
+{
+    /* Register variables do always have less than 128 bytes */
+    unsigned CodeLabel = GetLocalLabel ();
+    ldxconst (Size-1);
+    g_defcodelabel (CodeLabel);
+    AddCodeLine ("lda %s,x", GetLabelName (CF_STATIC, Label, 0));
+    AddCodeLine ("sta %s,x", GetLabelName (CF_REGVAR, Reg, 0));
+    AddCodeLine ("dex");
+    AddCodeLine ("bpl %s", LocalLabelName (CodeLabel));
+}
 
 
 
-void g_asmcode (const char* Line, int Len)
-/* Output one line of assembler code. If Len is greater than zero, it is used
- * as the maximum number of characters to use from Line.
- */
+void g_initauto (unsigned Label, unsigned Size)
+/* Initialize a local variable at stack offset zero from static data */
 {
-    if (Len >= 0) {
-       AddCodeLine ("%.*s", Len, Line);
+    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 {
-       AddCodeLine ("%s", Line);
+        /* 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));
     }
 }
 
 
 
 /*****************************************************************************/
-/*                         Inlined known functions                          */
+/*                                    Switch statement                              */
 /*****************************************************************************/
 
 
 
-void g_strlen (unsigned flags, unsigned long val, unsigned offs)
-/* Inline the strlen() function */
+void g_switch (Collection* Nodes, unsigned DefaultLabel, unsigned Depth)
+/* Generate code for a switch statement */
 {
-    /* We need a label in both cases */
-    unsigned label = GetLocalLabel ();
+    unsigned NextLabel = 0;
+    unsigned I;
+
+    /* Setup registers and determine which compare insn to use */
+    const char* Compare;
+    switch (Depth) {
+       case 1:
+           Compare = "cmp #$%02X";
+           break;
+       case 2:
+           Compare = "cpx #$%02X";
+           break;
+       case 3:
+           AddCodeLine ("ldy sreg");
+           Compare = "cpy #$%02X";
+           break;
+       case 4:
+           AddCodeLine ("ldy sreg+1");
+           Compare = "cpy #$%02X";
+           break;
+       default:
+           Internal ("Invalid depth in g_switch: %u", Depth);
+    }
 
-    /* Two different encodings */
-    if (flags & CF_CONST) {
+    /* Walk over all nodes */
+    for (I = 0; I < CollCount (Nodes); ++I) {
 
-       /* The address of the string is constant. Create the correct label name */
-       char* lbuf = GetLabelName (flags, val, offs);
+       /* Get the next case node */
+       CaseNode* N = CollAtUnchecked (Nodes, I);
 
-       /* Generate the strlen code */
-       AddCodeLine ("ldy #$FF");
-       g_defcodelabel (label);
-       AddCodeLine ("iny");
-       AddCodeLine ("lda %s,y", lbuf);
-       AddCodeLine ("bne %s", LocalLabelName (label));
-               AddCodeLine ("tax");
-       AddCodeLine ("tya");
+       /* If we have a next label, define it */
+       if (NextLabel) {
+           g_defcodelabel (NextLabel);
+           NextLabel = 0;
+       }
 
-    } else {
+       /* Do the compare */
+       AddCodeLine (Compare, CN_GetValue (N));
 
-               /* Address not constant but in primary */
-       if (CodeSizeFactor < 400) {
-           /* This is too much code, so call strlen instead of inlining */
-           AddCodeLine ("jsr _strlen");
-       } else {
-           /* Inline the function */
-           AddCodeLine ("sta ptr1");
-           AddCodeLine ("stx ptr1+1");
-           AddCodeLine ("ldy #$FF");
-           g_defcodelabel (label);
-           AddCodeLine ("iny");
-           AddCodeLine ("lda (ptr1),y");
-           AddCodeLine ("bne %s", LocalLabelName (label));
-                   AddCodeLine ("tax");
-           AddCodeLine ("tya");
-       }
+       /* If this is the last level, jump directly to the case code if found */
+       if (Depth == 1) {
+
+           /* Branch if equal */
+           g_falsejump (0, CN_GetLabel (N));
+
+       } else {
+
+           /* Determine the next label */
+           if (I == CollCount (Nodes) - 1) {
+               /* Last node means not found */
+               g_truejump (0, DefaultLabel);
+           } else {
+               /* Jump to the next check */
+               NextLabel = GetLocalLabel ();
+               g_truejump (0, NextLabel);
+           }
+
+           /* Check the next level */
+           g_switch (N->Nodes, DefaultLabel, Depth-1);
+
+       }
     }
+
+    /* If we go here, we haven't found the label */
+    g_jump (DefaultLabel);
+}
+
+
+
+/*****************************************************************************/
+/*                      User supplied assembler code                        */
+/*****************************************************************************/
+
+
+
+void g_asmcode (struct StrBuf* B)
+/* Output one line of assembler code. */
+{
+    AddCodeLine ("%.*s", SB_GetLen (B), SB_GetConstBuf (B));
 }