]> git.sur5r.net Git - cc65/blobdiff - src/cc65/codegen.c
remove TABs
[cc65] / src / cc65 / codegen.c
index 7b436256a6314b50022cd040c47673588a7fd81b..a611f4f6a809ec0789c5c975bfc7876104e10b8e 100644 (file)
@@ -1,57 +1,70 @@
-/*
- * codegen.c
- *
- * Ullrich von Bassewitz, 08.06.1998
- */
+/*****************************************************************************/
+/*                                                                           */
+/*                                 codegen.c                                 */
+/*                                                                           */
+/*                            6502 code generator                            */
+/*                                                                           */
+/*                                                                           */
+/*                                                                           */
+/* (C) 1998-2013, Ullrich von Bassewitz                                      */
+/*                Roemerstrasse 52                                           */
+/*                D-70794 Filderstadt                                        */
+/* EMail:         uz@cc65.org                                                */
+/*                                                                           */
+/*                                                                           */
+/* This software is provided 'as-is', without any expressed or implied       */
+/* warranty.  In no event will the authors be held liable for any damages    */
+/* arising from the use of this software.                                    */
+/*                                                                           */
+/* Permission is granted to anyone to use this software for any purpose,     */
+/* including commercial applications, and to alter it and redistribute it    */
+/* freely, subject to the following restrictions:                            */
+/*                                                                           */
+/* 1. The origin of this software must not be misrepresented; you must not   */
+/*    claim that you wrote the original software. If you use this software   */
+/*    in a product, an acknowledgment in the product documentation would be  */
+/*    appreciated but is not required.                                       */
+/* 2. Altered source versions must be plainly marked as such, and must not   */
+/*    be misrepresented as being the original software.                      */
+/* 3. This notice may not be removed or altered from any source              */
+/*    distribution.                                                          */
+/*                                                                           */
+/*****************************************************************************/
 
 
 
 #include <stdio.h>
 #include <string.h>
+#include <stdarg.h>
 
-#include "../common/version.h"
-
+/* common */
+#include "check.h"
+#include "cpu.h"
+#include "inttypes.h"
+#include "strbuf.h"
+#include "xmalloc.h"
+#include "xsprintf.h"
+#include "version.h"
+
+/* cc65 */
 #include "asmcode.h"
 #include "asmlabel.h"
-#include "check.h"
+#include "casenode.h"
+#include "codeseg.h"
+#include "dataseg.h"
 #include "error.h"
 #include "global.h"
-#include "io.h"
-#include "litpool.h"
-#include "mem.h"
-#include "optimize.h"
+#include "segments.h"
+#include "stackptr.h"
+#include "stdfunc.h"
+#include "textseg.h"
 #include "util.h"
 #include "codegen.h"
 
 
 
 /*****************************************************************************/
-/*                                  Data                                    */
-/*****************************************************************************/
-
-
-
-/* Compiler relative stk ptr */
-int oursp      = 0;
-
-/* Current segment */
-static enum {
-    SEG_INV = -1,      /* Invalid segment */
-    SEG_CODE,
-    SEG_RODATA,
-    SEG_DATA,
-    SEG_BSS
-} CurSeg = SEG_CODE;
-
-/* Segment names */
-static char* SegmentNames [4];
-static char* SegmentHints [4] = {
-    "seg:code", "seg:rodata", "seg:data", "seg:bss"
-};
-
-
-/*****************************************************************************/
-/*                                 Helpers                                  */
+/*                                  Helpers                                  */
 /*****************************************************************************/
 
 
@@ -59,7 +72,12 @@ static char* SegmentHints [4] = {
 static void typeerror (unsigned type)
 /* Print an error message about an invalid operand type */
 {
-    Internal ("Invalid type in CF flags: %04X, type = %u", type, type & CF_TYPE);
+    /* Special handling for floats here: */
+    if ((type & CF_TYPEMASK) == CF_FLOAT) {
+        Fatal ("Floating point type is currently unsupported");
+    } else {
+        Internal ("Invalid type in CF flags: %04X, type = %u", type, type & CF_TYPEMASK);
+    }
 }
 
 
@@ -68,53 +86,60 @@ static void CheckLocalOffs (unsigned Offs)
 /* Check the offset into the stack for 8bit range */
 {
     if (Offs >= 256) {
-       /* Too many local vars */
-               AddCodeLine (";*** Too many locals");
-       Error (ERR_TOO_MANY_LOCALS);
+        /* Too many local vars */
+        Error ("Too many local variables");
     }
 }
 
 
 
-static char* GetLabelName (unsigned flags, unsigned long label, unsigned offs)
+static const char* GetLabelName (unsigned Flags, uintptr_t Label, long Offs)
 {
-    static char lbuf [128];            /* Label name */
+    static char Buf [256];              /* Label name */
 
     /* Create the correct label name */
-    switch (flags & CF_ADDRMASK) {
-
-       case CF_STATIC:
-           /* Static memory cell */
-           sprintf (lbuf, "L%04X+%u", (unsigned)(label & 0xFFFF), offs);
-           break;
-
-       case CF_EXTERNAL:
-           /* External label */
-           sprintf (lbuf, "_%s+%u", (char*) label, offs);
-           break;
-
-       case CF_ABSOLUTE:
-           /* Absolute address */
-           sprintf (lbuf, "$%04X", (unsigned)((label+offs) & 0xFFFF));
-           break;
-
-       case CF_REGVAR:
-           /* Variable in register bank */
-           sprintf (lbuf, "regbank+%u", (unsigned)((label+offs) & 0xFFFF));
-           break;
-
-       default:
-           Internal ("Invalid address flags");
+    switch (Flags & CF_ADDRMASK) {
+
+        case CF_STATIC:
+            /* Static memory cell */
+            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 */
+            if (Offs) {
+                xsprintf (Buf, sizeof (Buf), "_%s%+ld", (char*) Label, Offs);
+            } else {
+                xsprintf (Buf, sizeof (Buf), "_%s", (char*) Label);
+            }
+            break;
+
+        case CF_ABSOLUTE:
+            /* Absolute address */
+            xsprintf (Buf, sizeof (Buf), "$%04X", (unsigned)((Label+Offs) & 0xFFFF));
+            break;
+
+        case CF_REGVAR:
+            /* Variable in register bank */
+            xsprintf (Buf, sizeof (Buf), "regbank+%u", (unsigned)((Label+Offs) & 0xFFFF));
+            break;
+
+        default:
+            Internal ("Invalid address flags: %04X", Flags);
     }
 
     /* Return a pointer to the static buffer */
-    return lbuf;
+    return Buf;
 }
 
 
 
 /*****************************************************************************/
-/*                           Pre- and postamble                             */
+/*                            Pre- and postamble                             */
 /*****************************************************************************/
 
 
@@ -122,87 +147,71 @@ static char* GetLabelName (unsigned flags, unsigned long label, unsigned offs)
 void g_preamble (void)
 /* Generate the assembler code preamble */
 {
-    AddCodeLine ("; File generated by cc65 v %u.%u.%u", VER_MAJOR, VER_MINOR, VER_PATCH);
-    AddEmptyLine ();
+    /* Identify the compiler version */
+    AddTextLine (";");
+    AddTextLine ("; File generated by cc65 v %s", GetVersionAsString ());
+    AddTextLine (";");
 
     /* Insert some object file options */
-    AddCodeLine (".fopt\t\tcompiler,\"cc65 v %u.%u.%u\"", VER_MAJOR, VER_MINOR, VER_PATCH);
-    AddEmptyLine ();
+    AddTextLine ("\t.fopt\t\tcompiler,\"cc65 v %s\"",
+                 GetVersionAsString ());
+
+    /* If we're producing code for some other CPU, switch the command set */
+    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;
+        case CPU_HUC6280:   AddTextLine ("\t.setcpu\t\t\"HUC6280\"");   break;
+        default:            Internal ("Unknown CPU: %d", CPU);
+    }
+
+    /* Use smart mode */
+    AddTextLine ("\t.smart\t\ton");
 
     /* Allow auto import for runtime library routines */
-    AddCodeLine (".autoimport\ton");
+    AddTextLine ("\t.autoimport\ton");
 
-    /* Switch the assembler into case sensible mode */
-    AddCodeLine (".case\t\ton");
+    /* Switch the assembler into case sensitive mode */
+    AddTextLine ("\t.case\t\ton");
 
     /* Tell the assembler if we want to generate debug info */
-    AddCodeLine (".debuginfo\t%s", (DebugInfo != 0)? "on" : "off");
+    AddTextLine ("\t.debuginfo\t%s", (DebugInfo != 0)? "on" : "off");
 
-    /* Import the stack pointer for direct auto variable access */
-    AddCodeLine (".importzp\tsp, sreg, regsave, regbank, tmp1, ptr1");
+    /* Import zero page variables */
+    AddTextLine ("\t.importzp\tsp, sreg, regsave, regbank");
+    AddTextLine ("\t.importzp\ttmp1, tmp2, tmp3, tmp4, ptr1, ptr2, ptr3, ptr4");
 
     /* Define long branch macros */
-    AddCodeLine (".macpack\tlongbranch");
-    AddEmptyLine ();
-
-    /* Define the ldax macro */
-    AddCodeLine (".macro  ldax    Value");
-    AddCodeLine ("        lda     #<(Value)");
-    AddCodeLine ("        ldx     #>(Value)");
-    AddCodeLine (".endmacro");
-    AddEmptyLine ();
-
-    /* Define the default names for the segments */
-    SegmentNames [SEG_CODE]    = xstrdup ("CODE");
-    SegmentNames [SEG_RODATA]  = xstrdup ("RODATA");
-    SegmentNames [SEG_DATA]    = xstrdup ("DATA");
-    SegmentNames [SEG_BSS]     = xstrdup ("BSS");
-
-    /* Tell the optimizer that this is the end of the preamble */
-    AddCodeHint ("end_of_preamble");
+    AddTextLine ("\t.macpack\tlongbranch");
 }
 
 
 
-void g_postamble (void)
-/* Generate assembler code postamble */
+void g_fileinfo (const char* Name, unsigned long Size, unsigned long MTime)
+/* If debug info is enabled, place a file info into the source */
 {
-    /* Tell the optimizer that this is the start of the postamble */
-    AddCodeHint ("start_of_postamble");
+    if (DebugInfo) {
+        /* We have to place this into the global text segment, so it will
+        ** appear before all .dbg line statements.
+        */
+        TS_AddLine (GS->Text, "\t.dbg\t\tfile, \"%s\", %lu, %lu", Name, Size, MTime);
+    }
 }
 
 
 
 /*****************************************************************************/
-/*                             Segment support                              */
+/*                              Segment support                              */
 /*****************************************************************************/
 
 
 
-static void UseSeg (int NewSeg)
-/* Switch to a specific segment */
-{
-    if (CurSeg != NewSeg) {
-       CurSeg = NewSeg;
-       AddCodeLine (".segment\t\"%s\"", SegmentNames [CurSeg]);
-       AddCodeHint (SegmentHints [CurSeg]);
-    }
-}
-
-
-
-void g_usecode (void)
-/* Switch to the code segment */
-{
-    UseSeg (SEG_CODE);
-}
-
-
-
 void g_userodata (void)
 /* Switch to the read only data segment */
 {
-    UseSeg (SEG_RODATA);
+    UseDataSeg (SEG_RODATA);
 }
 
 
@@ -210,7 +219,7 @@ void g_userodata (void)
 void g_usedata (void)
 /* Switch to the data segment */
 {
-    UseSeg (SEG_DATA);
+    UseDataSeg (SEG_DATA);
 }
 
 
@@ -218,63 +227,31 @@ void g_usedata (void)
 void g_usebss (void)
 /* Switch to the bss segment */
 {
-    UseSeg (SEG_BSS);
+    UseDataSeg (SEG_BSS);
 }
 
 
 
-static void SegName (int Seg, const char* Name)
-/* Set the name of a segment */
+void g_segname (segment_t Seg)
+/* Emit the name of a segment if necessary */
 {
-    /* Free the old name and set a new one */
-    xfree (SegmentNames [Seg]);
-    SegmentNames [Seg] = xstrdup (Name);
-
-    /* If the new segment is the current segment, emit a segment directive
-     * with the new name.
-     */
-    if (Seg == CurSeg) {
-               CurSeg = SEG_INV;       /* Invalidate */
-       UseSeg (Seg);
+    /* 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;
+        case SEG_BSS:    S = CS->BSS;    break;
+        default:         S = 0;          break;
+    }
+    if (S) {
+        DS_AddLine (S, ".segment\t\"%s\"", GetSegName (Seg));
     }
-}
-
-
-
-void g_codename (const char* Name)
-/* Set the name of the CODE segment */
-{
-    SegName (SEG_CODE, Name);
-}
-
-
-
-void g_rodataname (const char* Name)
-/* Set the name of the RODATA segment */
-{
-    SegName (SEG_RODATA, Name);
-}
-
-
-
-void g_dataname (const char* Name)
-/* Set the name of the DATA segment */
-{
-    SegName (SEG_DATA, Name);
-}
-
-
-
-void g_bssname (const char* Name)
-/* Set the name of the BSS segment */
-{
-    SegName (SEG_BSS, Name);
 }
 
 
 
 /*****************************************************************************/
-/*                                  Code                                    */
+/*                                   Code                                    */
 /*****************************************************************************/
 
 
@@ -282,21 +259,24 @@ void g_bssname (const char* Name)
 unsigned sizeofarg (unsigned flags)
 /* Return the size of a function argument type that is encoded in flags */
 {
-    switch (flags & CF_TYPE) {
+    switch (flags & CF_TYPEMASK) {
 
-       case CF_CHAR:
-           return (flags & CF_FORCECHAR)? 1 : 2;
+        case CF_CHAR:
+            return (flags & CF_FORCECHAR)? 1 : 2;
 
-       case CF_INT:
-           return 2;
+        case CF_INT:
+            return 2;
 
-       case CF_LONG:
-           return 4;
+        case CF_LONG:
+            return 4;
+
+        case CF_FLOAT:
+            return 4;
 
-       default:
-           typeerror (flags);
-           /* NOTREACHED */
-           return 2;
+        default:
+            typeerror (flags);
+            /* NOTREACHED */
+            return 2;
     }
 }
 
@@ -305,7 +285,7 @@ unsigned sizeofarg (unsigned flags)
 int pop (unsigned flags)
 /* Pop an argument of the given size */
 {
-    return oursp += sizeofarg (flags);
+    return StackPtr += sizeofarg (flags);
 }
 
 
@@ -313,32 +293,32 @@ int pop (unsigned flags)
 int push (unsigned flags)
 /* Push an argument of the given size */
 {
-    return oursp -= sizeofarg (flags);
+    return StackPtr -= sizeofarg (flags);
 }
 
 
 
 static unsigned MakeByteOffs (unsigned Flags, unsigned Offs)
 /* The value in Offs is an offset to an address in a/x. Make sure, an object
- * of the type given in Flags can be loaded or stored into this address by
- * adding part of the offset to the address in ax, so that the remaining
- * offset fits into an index register. Return the remaining offset.
- */
+** of the type given in Flags can be loaded or stored into this address by
+** adding part of the offset to the address in ax, so that the remaining
+** offset fits into an index register. Return the remaining offset.
+*/
 {
     /* If the offset is too large for a byte register, add the high byte
-     * of the offset to the primary. Beware: We need a special correction
-     * if the offset in the low byte will overflow in the operation.
-     */
+    ** of the offset to the primary. Beware: We need a special correction
+    ** if the offset in the low byte will overflow in the operation.
+    */
     unsigned O = Offs & ~0xFFU;
     if ((Offs & 0xFF) > 256 - sizeofarg (Flags)) {
-       /* We need to add the low byte also */
-       O += Offs & 0xFF;
+        /* We need to add the low byte also */
+        O += Offs & 0xFF;
     }
 
     /* Do the correction if we need one */
     if (O != 0) {
-       g_inc (CF_INT | CF_CONST, O);
-       Offs -= O;
+        g_inc (CF_INT | CF_CONST, O);
+        Offs -= O;
     }
 
     /* Return the new offset */
@@ -348,21 +328,47 @@ static unsigned MakeByteOffs (unsigned Flags, unsigned Offs)
 
 
 /*****************************************************************************/
-/*                     Functions handling local labels                      */
+/*                      Functions handling local labels                      */
 /*****************************************************************************/
 
 
 
-void g_defloclabel (unsigned label)
-/* Define a local label */
+void g_defcodelabel (unsigned label)
+/* Define a local code label */
 {
-    AddCodeLine ("L%04X:", label & 0xFFFF);
+    CS_AddLabel (CS->Code, LocalLabelName (label));
+}
+
+
+
+void g_defdatalabel (unsigned label)
+/* Define a local data label */
+{
+    AddDataLine ("%s:", LocalLabelName (label));
+}
+
+
+
+void g_aliasdatalabel (unsigned label, unsigned baselabel, long offs)
+/* Define label as a local alias for baselabel+offs */
+{
+    /* We need an intermediate buffer here since LocalLabelName uses a
+    ** static buffer which changes with each call.
+    */
+    StrBuf L = AUTO_STRBUF_INITIALIZER;
+    SB_AppendStr (&L, LocalLabelName (label));
+    SB_Terminate (&L);
+    AddDataLine ("%s\t:=\t%s+%ld",
+                 SB_GetConstBuf (&L),
+                 LocalLabelName (baselabel),
+                 offs);
+    SB_Done (&L);
 }
 
 
 
 /*****************************************************************************/
-/*                    Functions handling global labels                      */
+/*                     Functions handling global labels                      */
 /*****************************************************************************/
 
 
@@ -370,7 +376,8 @@ void g_defloclabel (unsigned label)
 void g_defgloblabel (const char* Name)
 /* Define a global label with the given name */
 {
-    AddCodeLine ("_%s:", Name);
+    /* Global labels are always data labels */
+    AddDataLine ("_%s:", Name);
 }
 
 
@@ -379,9 +386,9 @@ void g_defexport (const char* Name, int ZP)
 /* Export the given label */
 {
     if (ZP) {
-       AddCodeLine ("\t.exportzp\t_%s", Name);
+        AddTextLine ("\t.exportzp\t_%s", Name);
     } else {
-       AddCodeLine ("\t.export\t\t_%s", Name);
+        AddTextLine ("\t.export\t\t_%s", Name);
     }
 }
 
@@ -391,55 +398,41 @@ void g_defimport (const char* Name, int ZP)
 /* Import the given label */
 {
     if (ZP) {
-               AddCodeLine ("\t.importzp\t_%s", Name);
+        AddTextLine ("\t.importzp\t_%s", Name);
     } else {
-       AddCodeLine ("\t.import\t\t_%s", Name);
+        AddTextLine ("\t.import\t\t_%s", Name);
     }
 }
 
 
 
-/*****************************************************************************/
-/*                          Load functions for various registers                    */
-/*****************************************************************************/
-
-
-
-static void ldaconst (unsigned val)
-/* Load a with a constant */
-{
-    AddCodeLine ("\tlda\t#$%02X", val & 0xFF);
-}
-
-
-
-static void ldxconst (unsigned val)
-/* Load x with a constant */
+void g_importstartup (void)
+/* Forced import of the startup module */
 {
-    AddCodeLine ("\tldx\t#$%02X", val & 0xFF);
+    AddTextLine ("\t.forceimport\t__STARTUP__");
 }
 
 
 
-static void ldyconst (unsigned val)
-/* Load y with a constant */
+void g_importmainargs (void)
+/* Forced import of a special symbol that handles arguments to main */
 {
-    AddCodeLine ("\tldy\t#$%02X", val & 0xFF);
+    AddTextLine ("\t.forceimport\tinitmainargs");
 }
 
 
 
 /*****************************************************************************/
-/*                                 Function entry and exit                          */
+/*                          Function entry and exit                          */
 /*****************************************************************************/
 
 
 
 /* Remember the argument size of a function. The variable is set by g_enter
- * and used by g_leave. If the functions gets its argument size by the caller
- * (variable param list or function without prototype), g_enter will set the
- * value to -1.
- */
+** and used by g_leave. If the function gets its argument size by the caller
+** (variable param list or function without prototype), g_enter will set the
+** value to -1.
+*/
 static int funcargs;
 
 
@@ -447,122 +440,128 @@ void g_enter (unsigned flags, unsigned argsize)
 /* Function prologue */
 {
     if ((flags & CF_FIXARGC) != 0) {
-       /* Just remember the argument size for the leave */
-       funcargs = argsize;
+        /* Just remember the argument size for the leave */
+        funcargs = argsize;
     } else {
-               funcargs = -1;
-               AddCodeLine ("\tjsr\tenter");
+        funcargs = -1;
+        AddCodeLine ("jsr enter");
     }
 }
 
 
 
-void g_leave (int flags, int val)
+void g_leave (void)
 /* Function epilogue */
 {
-    int k;
-    char buf [40];
-
     /* How many bytes of locals do we have to drop? */
-    k = -oursp;
+    unsigned ToDrop = (unsigned) -StackPtr;
 
     /* If we didn't have a variable argument list, don't call leave */
     if (funcargs >= 0) {
 
-       /* Load a function return code if needed */
-       if ((flags & CF_CONST) != 0) {
-           g_getimmed (flags, val, 0);
-       }
-
-       /* Drop stackframe or leave with rts */
-       k += funcargs;
-       if (k == 0) {
-           AddCodeLine ("\trts");
-       } else if (k <= 8) {
-           AddCodeLine ("\tjmp\tincsp%d", k);
-       } else {
-           CheckLocalOffs (k);
-           ldyconst (k);
-           AddCodeLine ("\tjmp\taddysp");
-       }
+        /* Drop stackframe if needed */
+        g_drop (ToDrop + funcargs);
+
+    } else if (StackPtr != 0) {
+
+        /* We've a stack frame to drop */
+        if (ToDrop > 255) {
+            g_drop (ToDrop);            /* Inlines the code */
+            AddCodeLine ("jsr leave");
+        } else {
+            AddCodeLine ("ldy #$%02X", ToDrop);
+            AddCodeLine ("jsr leavey");
+        }
 
     } else {
 
-       strcpy (buf, "\tjmp\tleave");
-       if (k) {
-           /* We've a stack frame to drop */
-           ldyconst (k);
-           strcat (buf, "y");
-       }
-       if (flags & CF_CONST) {
-           if ((flags & CF_TYPE) != CF_LONG) {
-               /* Constant int sized value given for return code */
-               if (val == 0) {
-                   /* Special case: return 0 */
-                   strcat (buf, "00");
-                       } else if (((val >> 8) & 0xFF) == 0) {
-                   /* Special case: constant with high byte zero */
-                   ldaconst (val);             /* Load low byte */
-                   strcat (buf, "0");
-               } else {
-                   /* Others: arbitrary constant value */
-                   g_getimmed (flags, val, 0); /* Load value */
-               }
-           } else {
-               /* Constant long value: No shortcut possible */
-               g_getimmed (flags, val, 0);
-           }
-       }
-
-       /* Output the jump */
-       AddCodeLine (buf);
-    }
-
-    /* Add an empty line  after a function to make the code more readable */
-    AddEmptyLine ();
+        /* Nothing to drop */
+        AddCodeLine ("jsr leave");
+
+    }
+
+    /* Add the final rts */
+    AddCodeLine ("rts");
 }
 
 
 
 /*****************************************************************************/
-/*                           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 */
+    AddCodeLine ("ldy #$%02X", StackOffs & 0xFF);
+    if (Bytes == 1) {
+
+        if (IS_Get (&CodeSizeFactor) < 165) {
+            AddCodeLine ("ldx #$%02X", RegOffs & 0xFF);
+            AddCodeLine ("jsr regswap1");
+        } else {
+            AddCodeLine ("lda (sp),y");
+            AddCodeLine ("ldx regbank%+d", RegOffs);
+            AddCodeLine ("sta regbank%+d", RegOffs);
+            AddCodeLine ("txa");
+            AddCodeLine ("sta (sp),y");
+        }
+
+    } else if (Bytes == 2) {
+
+        AddCodeLine ("ldx #$%02X", RegOffs & 0xFF);
+        AddCodeLine ("jsr regswap2");
+
+    } else {
+
+        AddCodeLine ("ldx #$%02X", RegOffs & 0xFF);
+        AddCodeLine ("lda #$%02X", Bytes & 0xFF);
+        AddCodeLine ("jsr regswap");
+    }
+}
+
+
+
 void g_save_regvars (int RegOffs, unsigned Bytes)
 /* Save register variables */
 {
     /* Don't loop for up to two bytes */
     if (Bytes == 1) {
 
-       AddCodeLine ("\tlda\tregbank%+d", RegOffs);
-               AddCodeLine ("\tjsr\tpusha");
+        AddCodeLine ("lda regbank%+d", RegOffs);
+        AddCodeLine ("jsr pusha");
 
     } else if (Bytes == 2) {
 
-               AddCodeLine ("\tlda\tregbank%+d", RegOffs);
-       AddCodeLine ("\tldx\tregbank%+d", RegOffs+1);
-               AddCodeLine ("\tjsr\tpushax");
+        AddCodeLine ("lda regbank%+d", RegOffs);
+        AddCodeLine ("ldx regbank%+d", RegOffs+1);
+        AddCodeLine ("jsr pushax");
 
     } else {
 
-       /* More than two bytes - loop */
-       unsigned Label = GetLabel ();
-       g_space (Bytes);
-       ldyconst (Bytes - 1);
-       ldxconst (Bytes);
-       g_defloclabel (Label);
-       AddCodeLine ("\tlda\tregbank%+d,x", RegOffs-1);
-       AddCodeLine ("\tsta\t(sp),y");
-       AddCodeLine ("\tdey");
-       AddCodeLine ("\tdex");
-       AddCodeLine ("\tbne\tL%04X", Label);
+        /* More than two bytes - loop */
+        unsigned Label = GetLocalLabel ();
+        g_space (Bytes);
+        AddCodeLine ("ldy #$%02X", (unsigned char) (Bytes - 1));
+        AddCodeLine ("ldx #$%02X", (unsigned char) Bytes);
+        g_defcodelabel (Label);
+        AddCodeLine ("lda regbank%+d,x", RegOffs-1);
+        AddCodeLine ("sta (sp),y");
+        AddCodeLine ("dey");
+        AddCodeLine ("dex");
+        AddCodeLine ("bne %s", LocalLabelName (Label));
 
     }
 
     /* We pushed stuff, correct the stack pointer */
-    oursp -= Bytes;
+    StackPtr -= Bytes;
 }
 
 
@@ -571,37 +570,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 ("\tlda\t(sp),y");
-       AddCodeLine ("\tsta\tregbank%+d", RegOffs);
+        AddCodeLine ("ldy #$%02X", StackOffs);
+        AddCodeLine ("lda (sp),y");
+        AddCodeLine ("sta regbank%+d", RegOffs);
 
     } else if (Bytes == 2) {
 
-       ldyconst (StackOffs);
-       AddCodeLine ("\tlda\t(sp),y");
-       AddCodeLine ("\tsta\tregbank%+d", RegOffs);
-       AddCodeLine ("\tiny");
-       AddCodeLine ("\tlda\t(sp),y");
-       AddCodeLine ("\tsta\tregbank%+d", RegOffs+1);
+        AddCodeLine ("ldy #$%02X", 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 && IS_Get (&CodeSizeFactor) >= 133) {
+
+        AddCodeLine ("ldy #$%02X", 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 ();
+        AddCodeLine ("ldy #$%02X", StackOffs);
+        g_defcodelabel (Label);
+        AddCodeLine ("lda (sp),y");
+        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 = GetLabel ();
-       ldyconst (StackOffs+Bytes-1);
-       ldxconst (Bytes);
-       g_defloclabel (Label);
-       AddCodeLine ("\tlda\t(sp),y");
-       AddCodeLine ("\tsta\tregbank%+d,x", RegOffs-1);
-       AddCodeLine ("\tdey");
-       AddCodeLine ("\tdex");
-       AddCodeLine ("\tbne\tL%04X", 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");
+        AddCodeLine ("ldy #$%02X", (unsigned char) (StackOffs + Bytes - 1));
+        AddCodeLine ("ldx #$%02X", (unsigned char) (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");
 
     }
 }
@@ -609,439 +639,534 @@ 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 */
 {
-    if ((flags & CF_CONST) != 0) {
-
-       /* Numeric constant */
-       switch (flags & CF_TYPE) {
-
-           case CF_CHAR:
-               if ((flags & CF_FORCECHAR) != 0) {
-                   ldaconst (val);
-                   break;
-               }
-               /* FALL THROUGH */
-           case CF_INT:
-               ldxconst ((val >> 8) & 0xFF);
-               ldaconst (val & 0xFF);
-               break;
-
-           case CF_LONG:
-               if (val < 0x100) {
-                   AddCodeLine ("\tldx\t#$00");
-                   AddCodeLine ("\tstx\tsreg+1");
-                   AddCodeLine ("\tstx\tsreg");
-                   AddCodeLine ("\tlda\t#$%02X", (unsigned char) val);
-               } else if ((val & 0xFFFF00FF) == 0) {
-                   AddCodeLine ("\tlda\t#$00");
-                   AddCodeLine ("\tsta\tsreg+1");
-                   AddCodeLine ("\tsta\tsreg");
-                   AddCodeLine ("\tldx\t#$%02X", (unsigned char) (val >> 8));
-               } else if ((val & 0xFFFF0000) == 0 && FavourSize == 0) {
-                   AddCodeLine ("\tlda\t#$00");
-                   AddCodeLine ("\tsta\tsreg+1");
-                   AddCodeLine ("\tsta\tsreg");
-                   AddCodeLine ("\tlda\t#$%02X", (unsigned char) val);
-                   AddCodeLine ("\tldx\t#$%02X", (unsigned char) (val >> 8));
-               } else if ((val & 0xFFFFFF00) == 0xFFFFFF00) {
-                   AddCodeLine ("\tldx\t#$FF");
-                   AddCodeLine ("\tstx\tsreg+1");
-                   AddCodeLine ("\tstx\tsreg");
-                   if ((val & 0xFF) == 0xFF) {
-                       AddCodeLine ("\ttxa");
-                   } else {
-                       AddCodeLine ("\tlda\t#$%02X", (unsigned char) val);
-                   }
-               } else if ((val & 0xFFFF00FF) == 0xFFFF00FF) {
-                   AddCodeLine ("\tlda\t#$FF");
-                   AddCodeLine ("\tsta\tsreg+1");
-                   AddCodeLine ("\tsta\tsreg");
-                   AddCodeLine ("\tldx\t#$%02X", (unsigned char) (val >> 8));
-               } else {
-                   /* Call a subroutine that will load following value */
-                   AddCodeLine ("\tjsr\tldeax");
-                   AddCodeLine ("\t.dword\t$%08lX", val & 0xFFFFFFFF);
-               }
-               break;
-
-           default:
-               typeerror (flags);
-               break;
-
-       }
+    unsigned char B1, B2, B3, B4;
+    unsigned      Done;
+
+
+    if ((Flags & CF_CONST) != 0) {
+
+        /* Numeric constant */
+        switch (Flags & CF_TYPEMASK) {
+
+            case CF_CHAR:
+                if ((Flags & CF_FORCECHAR) != 0) {
+                    AddCodeLine ("lda #$%02X", (unsigned char) Val);
+                    break;
+                }
+                /* FALL THROUGH */
+            case CF_INT:
+                AddCodeLine ("ldx #$%02X", (unsigned char) (Val >> 8));
+                AddCodeLine ("lda #$%02X", (unsigned char) Val);
+                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");
+                }
+                break;
+
+            default:
+                typeerror (Flags);
+                break;
+
+        }
 
     } 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 ("\tldax\t%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, uintptr_t 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) {
-
-       case CF_CHAR:
-           if ((flags & CF_FORCECHAR) || (flags & CF_TEST)) {
-               AddCodeLine ("\tlda\t%s", lbuf);        /* load A from the label */
-                   } else {
-               ldxconst (0);
-               AddCodeLine ("\tlda\t%s", lbuf);        /* load A from the label */
-               if (!(flags & CF_UNSIGNED)) {
-                   /* Must sign extend */
-                   AddCodeLine ("\tbpl\t*+3");
-                   AddCodeLine ("\tdex");
-                   AddCodeHint ("x:!");                /* X is invalid now */
-               }
-           }
-           break;
-
-       case CF_INT:
-           AddCodeLine ("\tlda\t%s", lbuf);
-           if (flags & CF_TEST) {
-               AddCodeLine ("\tora\t%s+1", lbuf);
-           } else {
-               AddCodeLine ("\tldx\t%s+1", lbuf);
-           }
-           break;
-
-       case CF_LONG:
-           if (flags & CF_TEST) {
-               AddCodeLine ("\tlda\t%s+3", lbuf);
-               AddCodeLine ("\tora\t%s+2", lbuf);
-               AddCodeLine ("\tora\t%s+1", lbuf);
-               AddCodeLine ("\tora\t%s+0", lbuf);
-           } else {
-               AddCodeLine ("\tlda\t%s+3", lbuf);
-               AddCodeLine ("\tsta\tsreg+1");
-               AddCodeLine ("\tlda\t%s+2", lbuf);
-               AddCodeLine ("\tsta\tsreg");
-               AddCodeLine ("\tldx\t%s+1", lbuf);
-               AddCodeLine ("\tlda\t%s", lbuf);
-           }
-           break;
-
-               default:
-                   typeerror (flags);
-
-    }
-}
-
-
-
-void g_getlocal (unsigned flags, int offs)
+    switch (flags & CF_TYPEMASK) {
+
+        case CF_CHAR:
+            if ((flags & CF_FORCECHAR) || (flags & CF_TEST)) {
+                AddCodeLine ("lda %s", lbuf);   /* load A from the label */
+            } else {
+                AddCodeLine ("ldx #$00");
+                AddCodeLine ("lda %s", lbuf);   /* load A from the label */
+                if (!(flags & CF_UNSIGNED)) {
+                    /* Must sign extend */
+                    unsigned L = GetLocalLabel ();
+                    AddCodeLine ("bpl %s", LocalLabelName (L));
+                    AddCodeLine ("dex");
+                    g_defcodelabel (L);
+                }
+            }
+            break;
+
+        case CF_INT:
+            AddCodeLine ("lda %s", lbuf);
+            if (flags & CF_TEST) {
+                AddCodeLine ("ora %s+1", lbuf);
+            } else {
+                AddCodeLine ("ldx %s+1", lbuf);
+            }
+            break;
+
+        case CF_LONG:
+            if (flags & CF_TEST) {
+                AddCodeLine ("lda %s+3", lbuf);
+                AddCodeLine ("ora %s+2", lbuf);
+                AddCodeLine ("ora %s+1", lbuf);
+                AddCodeLine ("ora %s+0", lbuf);
+            } else {
+                AddCodeLine ("lda %s+3", lbuf);
+                AddCodeLine ("sta sreg+1");
+                AddCodeLine ("lda %s+2", lbuf);
+                AddCodeLine ("sta sreg");
+                AddCodeLine ("ldx %s+1", lbuf);
+                AddCodeLine ("lda %s", lbuf);
+            }
+            break;
+
+        default:
+            typeerror (flags);
+
+    }
+}
+
+
+
+void g_getlocal (unsigned Flags, int Offs)
 /* Fetch specified local object (local var). */
 {
-    offs -= oursp;
-    CheckLocalOffs (offs);
-    switch (flags & CF_TYPE) {
-
-       case CF_CHAR:
-           if ((flags & CF_FORCECHAR) || (flags & CF_TEST)) {
-               ldyconst (offs);
-                       AddCodeLine ("\tlda\t(sp),y");
-           } else {
-               if (offs == 0) {
-                   AddCodeLine ("\tldx\t#$00");
-                   AddCodeLine ("\tlda\t(sp,x)");
-               } else {
-                   ldyconst (offs);
-                   AddCodeLine ("\tldx\t#$00");
-                   AddCodeLine ("\tlda\t(sp),y");
-               }
-               if ((flags & CF_UNSIGNED) == 0) {
-                   AddCodeLine ("\tbpl\t*+3");
-                   AddCodeLine ("\tdex");
-                   AddCodeHint ("x:!");        /* X is invalid now */
-               }
-           }
-           break;
-
-       case CF_INT:
-           CheckLocalOffs (offs + 1);
-                   if (flags & CF_TEST) {
-               ldyconst (offs + 1);
-               AddCodeLine ("\tlda\t(sp),y");
-               AddCodeLine ("\tdey");
-               AddCodeLine ("\tora\t(sp),y");
-           } else {
-               if (FavourSize) {
-                   if (offs) {
-                       ldyconst (offs+1);
-                               AddCodeLine ("\tjsr\tldaxysp");
-                   } else {
-                       AddCodeLine ("\tjsr\tldax0sp");
-                   }
-               } else {
-                   ldyconst (offs + 1);
-                   AddCodeLine ("\tlda\t(sp),y");
-                   AddCodeLine ("\ttax");
-                   AddCodeLine ("\tdey");
-                   AddCodeLine ("\tlda\t(sp),y");
-               }
-           }
-           break;
-
-       case CF_LONG:
-           if (offs) {
-               ldyconst (offs+3);
-               AddCodeLine ("\tjsr\tldeaxysp");
-           } else {
-               AddCodeLine ("\tjsr\tldeax0sp");
-           }
-           break;
-
-       default:
-           typeerror (flags);
-    }
-}
-
-
-
-void g_getind (unsigned flags, unsigned offs)
+    Offs -= StackPtr;
+    switch (Flags & CF_TYPEMASK) {
+
+        case CF_CHAR:
+            CheckLocalOffs (Offs);
+            if ((Flags & CF_FORCECHAR) || (Flags & CF_TEST)) {
+                AddCodeLine ("ldy #$%02X", Offs);
+                AddCodeLine ("lda (sp),y");
+            } else {
+                AddCodeLine ("ldy #$%02X", Offs);
+                AddCodeLine ("ldx #$00");
+                AddCodeLine ("lda (sp),y");
+                if ((Flags & CF_UNSIGNED) == 0) {
+                    unsigned L = GetLocalLabel();
+                    AddCodeLine ("bpl %s", LocalLabelName (L));
+                    AddCodeLine ("dex");
+                    g_defcodelabel (L);
+                }
+            }
+            break;
+
+        case CF_INT:
+            CheckLocalOffs (Offs + 1);
+            AddCodeLine ("ldy #$%02X", (unsigned char) (Offs+1));
+            if (Flags & CF_TEST) {
+                AddCodeLine ("lda (sp),y");
+                AddCodeLine ("dey");
+                AddCodeLine ("ora (sp),y");
+            } else {
+                AddCodeLine ("jsr ldaxysp");
+            }
+            break;
+
+        case CF_LONG:
+            CheckLocalOffs (Offs + 3);
+            AddCodeLine ("ldy #$%02X", (unsigned char) (Offs+3));
+            AddCodeLine ("jsr ldeaxysp");
+            if (Flags & CF_TEST) {
+                g_test (Flags);
+            }
+            break;
+
+        default:
+            typeerror (Flags);
+    }
+}
+
+
+
+void g_getind (unsigned Flags, unsigned Offs)
 /* Fetch the specified object type indirect through the primary register
- * into the primary register
- */
+** into the primary register
+*/
 {
     /* If the offset is greater than 255, add the part that is > 255 to
-     * the primary. This way we get an easy addition and use the low byte
-     * as the offset
-     */
-    offs = MakeByteOffs (flags, offs);
+    ** the primary. This way we get an easy addition and use the low byte
+    ** as the offset
+    */
+    Offs = MakeByteOffs (Flags, Offs);
 
     /* Handle the indirect fetch */
-    switch (flags & CF_TYPE) {
-
-       case CF_CHAR:
-                   /* Character sized */
-           if (offs) {
-               ldyconst (offs);
-               if (flags & CF_UNSIGNED) {
-                   AddCodeLine ("\tjsr\tldauidx");
-                       } else {
-                   AddCodeLine ("\tjsr\tldaidx");
-               }
-           } else {
-               if (flags & CF_UNSIGNED) {
-                   if (FavourSize) {
-                       AddCodeLine ("\tjsr\tldaui");
-                   } else {
-                       AddCodeLine ("\tsta\tptr1");
-                       AddCodeLine ("\tstx\tptr1+1");
-                       AddCodeLine ("\tldx\t#$00");
-                       AddCodeLine ("\tlda\t(ptr1,x)");
-                   }
-               } else {
-                   AddCodeLine ("\tjsr\tldai");
-               }
-           }
-           break;
-
-       case CF_INT:
-           if (flags & CF_TEST) {
-               ldyconst (offs);
-               AddCodeLine ("\tsta\tptr1");
-               AddCodeLine ("\tstx\tptr1+1");
-               AddCodeLine ("\tlda\t(ptr1),y");
-               AddCodeLine ("\tiny");
-               AddCodeLine ("\tora\t(ptr1),y");
-           } else {
-               if (offs == 0) {
-                   AddCodeLine ("\tjsr\tldaxi");
-               } else {
-                   ldyconst (offs+1);
-                   AddCodeLine ("\tjsr\tldaxidx");
-               }
-           }
-           break;
-
-               case CF_LONG:
-           if (offs == 0) {
-               AddCodeLine ("\tjsr\tldeaxi");
-           } else {
-               ldyconst (offs+3);
-               AddCodeLine ("\tjsr\tldeaxidx");
-           }
-           if (flags & CF_TEST) {
-                       AddCodeLine ("\tjsr\ttsteax");
-           }
-           break;
-
-       default:
-           typeerror (flags);
-
-    }
-}
-
-
-
-void g_leasp (int offs)
+    switch (Flags & CF_TYPEMASK) {
+
+        case CF_CHAR:
+            /* Character sized */
+            AddCodeLine ("ldy #$%02X", Offs);
+            if (Flags & CF_UNSIGNED) {
+                AddCodeLine ("jsr ldauidx");
+            } else {
+                AddCodeLine ("jsr ldaidx");
+            }
+            break;
+
+        case CF_INT:
+            if (Flags & CF_TEST) {
+                AddCodeLine ("ldy #$%02X", Offs);
+                AddCodeLine ("sta ptr1");
+                AddCodeLine ("stx ptr1+1");
+                AddCodeLine ("lda (ptr1),y");
+                AddCodeLine ("iny");
+                AddCodeLine ("ora (ptr1),y");
+            } else {
+                AddCodeLine ("ldy #$%02X", Offs+1);
+                AddCodeLine ("jsr ldaxidx");
+            }
+            break;
+
+        case CF_LONG:
+            AddCodeLine ("ldy #$%02X", Offs+3);
+            AddCodeLine ("jsr ldeaxidx");
+            if (Flags & CF_TEST) {
+                g_test (Flags);
+            }
+            break;
+
+        default:
+            typeerror (Flags);
+
+    }
+}
+
+
+
+void g_leasp (int Offs)
 /* Fetch the address of the specified symbol into the primary register */
 {
+    unsigned char Lo, Hi;
+
     /* Calculate the offset relative to sp */
-    offs -= oursp;
+    Offs -= StackPtr;
+
+    /* Get low and high byte */
+    Lo = (unsigned char) Offs;
+    Hi = (unsigned char) (Offs >> 8);
+
+    /* Generate code */
+    if (Lo == 0) {
+        if (Hi <= 3) {
+            AddCodeLine ("lda sp");
+            AddCodeLine ("ldx sp+1");
+            while (Hi--) {
+                AddCodeLine ("inx");
+            }
+        } else {
+            AddCodeLine ("lda sp+1");
+            AddCodeLine ("clc");
+            AddCodeLine ("adc #$%02X", Hi);
+            AddCodeLine ("tax");
+            AddCodeLine ("lda sp");
+        }
+    } else if (Hi == 0) {
+        /* 8 bit offset */
+        if (IS_Get (&CodeSizeFactor) < 200) {
+            /* 8 bit offset with subroutine call */
+            AddCodeLine ("lda #$%02X", Lo);
+            AddCodeLine ("jsr leaa0sp");
+        } else {
+            /* 8 bit offset inlined */
+            unsigned L = GetLocalLabel ();
+            AddCodeLine ("lda sp");
+            AddCodeLine ("ldx sp+1");
+            AddCodeLine ("clc");
+            AddCodeLine ("adc #$%02X", Lo);
+            AddCodeLine ("bcc %s", LocalLabelName (L));
+            AddCodeLine ("inx");
+            g_defcodelabel (L);
+        }
+    } else if (IS_Get (&CodeSizeFactor) < 170) {
+        /* Full 16 bit offset with subroutine call */
+        AddCodeLine ("lda #$%02X", Lo);
+        AddCodeLine ("ldx #$%02X", Hi);
+        AddCodeLine ("jsr leaaxsp");
+    } else {
+        /* Full 16 bit offset inlined */
+        AddCodeLine ("lda sp");
+        AddCodeLine ("clc");
+        AddCodeLine ("adc #$%02X", Lo);
+        AddCodeLine ("pha");
+        AddCodeLine ("lda sp+1");
+        AddCodeLine ("adc #$%02X", Hi);
+        AddCodeLine ("tax");
+        AddCodeLine ("pla");
+    }
+}
 
-    /* For value 0 we do direct code */
-    if (offs == 0) {
-       AddCodeLine ("\tlda\tsp");
-       AddCodeLine ("\tldx\tsp+1");
+
+
+void g_leavariadic (int Offs)
+/* Fetch the address of a parameter in a variadic function into the primary
+** register
+*/
+{
+    unsigned ArgSizeOffs;
+
+    /* Calculate the offset relative to sp */
+    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 (StackPtr <= 0);
+    ArgSizeOffs = -StackPtr;
+    CheckLocalOffs (ArgSizeOffs);
+
+    /* Get the size of all parameters. */
+    AddCodeLine ("ldy #$%02X", ArgSizeOffs);
+    AddCodeLine ("lda (sp),y");
+
+    /* Add the value of the stackpointer */
+    if (IS_Get (&CodeSizeFactor) > 250) {
+        unsigned L = GetLocalLabel();
+        AddCodeLine ("ldx sp+1");
+        AddCodeLine ("clc");
+        AddCodeLine ("adc sp");
+        AddCodeLine ("bcc %s", LocalLabelName (L));
+        AddCodeLine ("inx");
+        g_defcodelabel (L);
     } else {
-       if (FavourSize) {
-           ldyconst (offs);                    /* Load Y with offset value */
-           AddCodeLine ("\tjsr\tleaysp");      /* Load effective address */
-       } else {
-           ldaconst (offs);
-           AddCodeLine ("\tclc");
-           AddCodeLine ("\tldx\tsp+1");
-           AddCodeLine ("\tadc\tsp");
-           AddCodeLine ("\tbcc\t*+3");
-           AddCodeLine ("\tinx");
-           AddCodeHint ("x:!");                /* Invalidate X */
-       }
+        AddCodeLine ("ldx #$00");
+        AddCodeLine ("jsr leaaxsp");
+    }
+
+    /* Add the offset to the primary */
+    if (Offs > 0) {
+        g_inc (CF_INT | CF_CONST, Offs);
+    } else if (Offs < 0) {
+        g_dec (CF_INT | CF_CONST, -Offs);
     }
 }
 
 
 
 /*****************************************************************************/
-/*                                    Store into memory                             */
+/*                             Store into memory                             */
 /*****************************************************************************/
 
 
 
-void g_putstatic (unsigned flags, unsigned long label, unsigned offs)
+void g_putstatic (unsigned flags, uintptr_t 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) {
+    switch (flags & CF_TYPEMASK) {
 
-       case CF_CHAR:
-           AddCodeLine ("\tsta\t%s", lbuf);
-           break;
+        case CF_CHAR:
+            AddCodeLine ("sta %s", lbuf);
+            break;
 
-       case CF_INT:
-           AddCodeLine ("\tsta\t%s", lbuf);
-           AddCodeLine ("\tstx\t%s+1", lbuf);
-           break;
+        case CF_INT:
+            AddCodeLine ("sta %s", lbuf);
+            AddCodeLine ("stx %s+1", lbuf);
+            break;
 
-       case CF_LONG:
-           AddCodeLine ("\tsta\t%s", lbuf);
-           AddCodeLine ("\tstx\t%s+1", lbuf);
-           AddCodeLine ("\tldy\tsreg");
-           AddCodeLine ("\tsty\t%s+2", lbuf);
-           AddCodeLine ("\tldy\tsreg+1");
-           AddCodeLine ("\tsty\t%s+3", lbuf);
-           break;
+        case CF_LONG:
+            AddCodeLine ("sta %s", lbuf);
+            AddCodeLine ("stx %s+1", lbuf);
+            AddCodeLine ("ldy sreg");
+            AddCodeLine ("sty %s+2", lbuf);
+            AddCodeLine ("ldy sreg+1");
+            AddCodeLine ("sty %s+3", lbuf);
+            break;
 
-               default:
-                   typeerror (flags);
+        default:
+            typeerror (flags);
 
     }
 }
 
 
 
-void g_putlocal (unsigned flags, int offs)
+void g_putlocal (unsigned Flags, int Offs, long Val)
 /* Put data into local object. */
 {
-    offs -= oursp;
-    CheckLocalOffs (offs);
-    switch (flags & CF_TYPE) {
+    Offs -= StackPtr;
+    CheckLocalOffs (Offs);
+    switch (Flags & CF_TYPEMASK) {
+
+        case CF_CHAR:
+            if (Flags & CF_CONST) {
+                AddCodeLine ("lda #$%02X", (unsigned char) Val);
+            }
+            AddCodeLine ("ldy #$%02X", Offs);
+            AddCodeLine ("sta (sp),y");
+            break;
+
+        case CF_INT:
+            if (Flags & CF_CONST) {
+                AddCodeLine ("ldy #$%02X", Offs+1);
+                AddCodeLine ("lda #$%02X", (unsigned char) (Val >> 8));
+                AddCodeLine ("sta (sp),y");
+                if ((Flags & CF_NOKEEP) == 0) {
+                    /* Place high byte into X */
+                    AddCodeLine ("tax");
+                }
+                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");
+            } else {
+                AddCodeLine ("ldy #$%02X", Offs);
+                if ((Flags & CF_NOKEEP) == 0 || IS_Get (&CodeSizeFactor) < 160) {
+                    AddCodeLine ("jsr staxysp");
+                } else {
+                    AddCodeLine ("sta (sp),y");
+                    AddCodeLine ("iny");
+                    AddCodeLine ("txa");
+                    AddCodeLine ("sta (sp),y");
+                }
+            }
+            break;
 
-       case CF_CHAR:
-                   ldyconst (offs);
-           AddCodeLine ("\tsta\t(sp),y");
-           break;
-
-       case CF_INT:
-           if (offs) {
-               ldyconst (offs);
-               AddCodeLine ("\tjsr\tstaxysp");
-           } else {
-               AddCodeLine ("\tjsr\tstax0sp");
-           }
-           break;
-
-       case CF_LONG:
-           if (offs) {
-               ldyconst (offs);
-               AddCodeLine ("\tjsr\tsteaxysp");
-           } else {
-               AddCodeLine ("\tjsr\tsteax0sp");
-           }
-           break;
+        case CF_LONG:
+            if (Flags & CF_CONST) {
+                g_getimmed (Flags, Val, 0);
+            }
+            AddCodeLine ("ldy #$%02X", Offs);
+            AddCodeLine ("jsr steaxysp");
+            break;
 
-               default:
-           typeerror (flags);
+        default:
+            typeerror (Flags);
 
     }
 }
 
 
 
-void g_putind (unsigned flags, unsigned offs)
+void g_putind (unsigned Flags, unsigned Offs)
 /* Store the specified object type in the primary register at the address
- * on the top of the stack
- */
+** on the top of the stack
+*/
 {
-    /* We cannot currently handle more than byte sized offsets */
-    if (offs > 256 - sizeofarg (flags)) {
-       Internal ("g_putind: Large offsets not implemented");
+    /* We can handle offsets below $100 directly, larger offsets must be added
+    ** to the address. Since a/x is in use, best code is achieved by adding
+    ** just the high byte. Be sure to check if the low byte will overflow while
+    ** while storing.
+    */
+    if ((Offs & 0xFF) > 256 - sizeofarg (Flags | CF_FORCECHAR)) {
+
+        /* Overflow - we need to add the low byte also */
+        AddCodeLine ("ldy #$00");
+        AddCodeLine ("clc");
+        AddCodeLine ("pha");
+        AddCodeLine ("lda #$%02X", Offs & 0xFF);
+        AddCodeLine ("adc (sp),y");
+        AddCodeLine ("sta (sp),y");
+        AddCodeLine ("iny");
+        AddCodeLine ("lda #$%02X", (Offs >> 8) & 0xFF);
+        AddCodeLine ("adc (sp),y");
+        AddCodeLine ("sta (sp),y");
+        AddCodeLine ("pla");
+
+        /* Complete address is on stack, new offset is zero */
+        Offs = 0;
+
+    } else if ((Offs & 0xFF00) != 0) {
+
+        /* We can just add the high byte */
+        AddCodeLine ("ldy #$01");
+        AddCodeLine ("clc");
+        AddCodeLine ("pha");
+        AddCodeLine ("lda #$%02X", (Offs >> 8) & 0xFF);
+        AddCodeLine ("adc (sp),y");
+        AddCodeLine ("sta (sp),y");
+        AddCodeLine ("pla");
+
+        /* Offset is now just the low byte */
+        Offs &= 0x00FF;
     }
 
     /* Check the size and determine operation */
-    switch (flags & CF_TYPE) {
-
-       case CF_CHAR:
-           if (offs) {
-               ldyconst (offs);
-               AddCodeLine ("\tjsr\tstaspidx");
-           } else {
-               AddCodeLine ("\tjsr\tstaspp");
-           }
-           break;
-
-       case CF_INT:
-           if (offs) {
-               ldyconst (offs);
-               AddCodeLine ("\tjsr\tstaxspidx");
-           } else {
-               AddCodeLine ("\tjsr\tstaxspp");
-           }
-           break;
-
-       case CF_LONG:
-           if (offs) {
-               ldyconst (offs);
-               AddCodeLine ("\tjsr\tsteaxspidx");
-           } else {
-               AddCodeLine ("\tjsr\tsteaxspp");
-           }
-           break;
-
-       default:
-           typeerror (flags);
+    AddCodeLine ("ldy #$%02X", Offs);
+    switch (Flags & CF_TYPEMASK) {
+
+        case CF_CHAR:
+            AddCodeLine ("jsr staspidx");
+            break;
+
+        case CF_INT:
+            AddCodeLine ("jsr staxspidx");
+            break;
+
+        case CF_LONG:
+            AddCodeLine ("jsr steaxspidx");
+            break;
+
+        default:
+            typeerror (Flags);
 
     }
 
@@ -1052,7 +1177,7 @@ void g_putind (unsigned flags, unsigned offs)
 
 
 /*****************************************************************************/
-/*                   type conversion and similiar stuff                     */
+/*                    type conversion and similiar stuff                     */
 /*****************************************************************************/
 
 
@@ -1060,23 +1185,23 @@ void g_putind (unsigned flags, unsigned offs)
 void g_toslong (unsigned flags)
 /* Make sure, the value on TOS is a long. Convert if necessary */
 {
-    switch (flags & CF_TYPE) {
-
-       case CF_CHAR:
-       case CF_INT:
-           if (flags & CF_UNSIGNED) {
-               AddCodeLine ("\tjsr\ttosulong");
-           } else {
-               AddCodeLine ("\tjsr\ttoslong");
-           }
-           push (CF_INT);
-           break;
+    switch (flags & CF_TYPEMASK) {
+
+        case CF_CHAR:
+        case CF_INT:
+            if (flags & CF_UNSIGNED) {
+                AddCodeLine ("jsr tosulong");
+            } else {
+                AddCodeLine ("jsr toslong");
+            }
+            push (CF_INT);
+            break;
 
-       case CF_LONG:
-           break;
+        case CF_LONG:
+            break;
 
-       default:
-           typeerror (flags);
+        default:
+            typeerror (flags);
     }
 }
 
@@ -1085,49 +1210,113 @@ void g_toslong (unsigned flags)
 void g_tosint (unsigned flags)
 /* Make sure, the value on TOS is an int. Convert if necessary */
 {
-    switch (flags & CF_TYPE) {
+    switch (flags & CF_TYPEMASK) {
 
-       case CF_CHAR:
-       case CF_INT:
-           break;
+        case CF_CHAR:
+        case CF_INT:
+            break;
 
-       case CF_LONG:
-           AddCodeLine ("\tjsr\ttosint");
-           pop (CF_INT);
-           break;
+        case CF_LONG:
+            AddCodeLine ("jsr tosint");
+            pop (CF_INT);
+            break;
 
-       default:
-           typeerror (flags);
+        default:
+            typeerror (flags);
     }
 }
 
 
 
-void g_reglong (unsigned flags)
-/* Make sure, the value in the primary register a long. Convert if necessary */
+static void g_regchar (unsigned Flags)
+/* Make sure, the value in the primary register is in the range of char. Truncate if necessary */
 {
-    switch (flags & CF_TYPE) {
+    unsigned L;
 
-       case CF_CHAR:
-       case CF_INT:
-           if (flags & CF_UNSIGNED) {
-               if (FavourSize) {
-                   AddCodeLine ("\tjsr\taxulong");
-               } else {
-                   ldyconst (0);
-                   AddCodeLine ("\tsty\tsreg");
-                   AddCodeLine ("\tsty\tsreg+1");
-               }
-           } else {
-               AddCodeLine ("\tjsr\taxlong");
-           }
-           break;
+    AddCodeLine ("ldx #$00");
 
-       case CF_LONG:
-           break;
+    if ((Flags & CF_UNSIGNED) == 0) {
+        /* Sign extend */
+        L = GetLocalLabel();
+        AddCodeLine ("cmp #$80");
+        AddCodeLine ("bcc %s", LocalLabelName (L));
+        AddCodeLine ("dex");
+        g_defcodelabel (L);
+    }
+}
 
-       default:
-           typeerror (flags);
+
+
+void g_regint (unsigned Flags)
+/* Make sure, the value in the primary register an int. Convert if necessary */
+{
+    switch (Flags & CF_TYPEMASK) {
+
+        case CF_CHAR:
+            if (Flags & CF_FORCECHAR) {
+                /* Conversion is from char */
+                g_regchar (Flags);
+            }
+            /* 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_TYPEMASK) {
+
+        case CF_CHAR:
+            if (Flags & CF_FORCECHAR) {
+                /* Conversion is from char */
+                if (Flags & CF_UNSIGNED) {
+                    if (IS_Get (&CodeSizeFactor) >= 200) {
+                        AddCodeLine ("ldx #$00");
+                        AddCodeLine ("stx sreg");
+                        AddCodeLine ("stx sreg+1");
+                    } else {
+                        AddCodeLine ("jsr aulong");
+                    }
+                } else {
+                    if (IS_Get (&CodeSizeFactor) >= 366) {
+                        g_regchar (Flags);
+                        AddCodeLine ("stx sreg");
+                        AddCodeLine ("stx sreg+1");
+                    } else {
+                        AddCodeLine ("jsr along");
+                    }
+                }
+            }
+            /* FALLTHROUGH */
+
+        case CF_INT:
+            if (Flags & CF_UNSIGNED) {
+                if (IS_Get (&CodeSizeFactor) >= 200) {
+                    AddCodeLine ("ldy #$00");
+                    AddCodeLine ("sty sreg");
+                    AddCodeLine ("sty sreg+1");
+                } else {
+                    AddCodeLine ("jsr axulong");
+                }
+            } else {
+                AddCodeLine ("jsr axlong");
+            }
+            break;
+
+        case CF_LONG:
+            break;
+
+        default:
+            typeerror (Flags);
     }
 }
 
@@ -1135,48 +1324,48 @@ void g_reglong (unsigned flags)
 
 unsigned g_typeadjust (unsigned lhs, unsigned rhs)
 /* Adjust the integer operands before doing a binary operation. lhs is a flags
- * value, that corresponds to the value on TOS, rhs corresponds to the value
- * in (e)ax. The return value is the the flags value for the resulting type.
- */
+** value, that corresponds to the value on TOS, rhs corresponds to the value
+** in (e)ax. The return value is the the flags value for the resulting type.
+*/
 {
     unsigned ltype, rtype;
     unsigned result;
 
     /* Get the type spec from the flags */
-    ltype = lhs & CF_TYPE;
-    rtype = rhs & CF_TYPE;
+    ltype = lhs & CF_TYPEMASK;
+    rtype = rhs & CF_TYPEMASK;
 
     /* 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);
-       /* Get the new rhs type */
-       rhs = (rhs & ~CF_TYPE) | CF_LONG;
-       rtype = CF_LONG;
+        /* We must promote the primary register to long */
+        g_reglong (rhs);
+        /* Get the new rhs type */
+        rhs = (rhs & ~CF_TYPEMASK) | CF_LONG;
+        rtype = CF_LONG;
     } else if (ltype != CF_LONG && (lhs & CF_CONST) == 0 && rtype == CF_LONG) {
-       /* We must promote the lhs to long */
-       if (lhs & CF_REG) {
-           g_reglong (lhs);
-       } else {
-           g_toslong (lhs);
-       }
-       /* Get the new rhs type */
-       lhs = (lhs & ~CF_TYPE) | CF_LONG;
-       ltype = CF_LONG;
+        /* We must promote the lhs to long */
+        if (lhs & CF_REG) {
+            g_reglong (lhs);
+        } else {
+            g_toslong (lhs);
+        }
+        /* Get the new rhs type */
+        lhs = (lhs & ~CF_TYPEMASK) | CF_LONG;
+        ltype = CF_LONG;
     }
 
     /* Determine the result type for the operation:
-     * - The result is const if both operands are const.
-     * - The result is unsigned if one of the operands is unsigned.
-     * - The result is long if one of the operands is long.
-     * - Otherwise the result is int sized.
-     */
+    **  - The result is const if both operands are const.
+    **  - The result is unsigned if one of the operands is unsigned.
+    **  - The result is long if one of the operands is long.
+    **  - Otherwise the result is int sized.
+    */
     result = (lhs & CF_CONST) & (rhs & CF_CONST);
     result |= (lhs & CF_UNSIGNED) | (rhs & CF_UNSIGNED);
     if (rtype == CF_LONG || ltype == CF_LONG) {
-       result |= CF_LONG;
+        result |= CF_LONG;
     } else {
-       result |= CF_INT;
+        result |= CF_INT;
     }
     return result;
 }
@@ -1185,33 +1374,45 @@ unsigned g_typeadjust (unsigned lhs, unsigned rhs)
 
 unsigned g_typecast (unsigned lhs, unsigned rhs)
 /* Cast the value in the primary register to the operand size that is flagged
- * by the lhs value. Return the result value.
- */
+** by the lhs value. Return the result value.
+*/
 {
-    unsigned ltype, rtype;
-
-    /* Get the type spec from the flags */
-    ltype = lhs & CF_TYPE;
-    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) {
+        switch (lhs & CF_TYPEMASK) {
+
+            case CF_LONG:
+                /* We must promote the primary register to long */
+                g_reglong (rhs);
+                break;
+
+            case CF_INT:
+                /* We must promote the primary register to int */
+                g_regint (rhs);
+                break;
+
+            case CF_CHAR:
+                /* We must truncate the primary register to char */
+                g_regchar (lhs);
+                break;
+
+            default:
+                typeerror (lhs);
+        }
     }
 
     /* Do not need any other action. If the left type is int, and the primary
-     * register is long, it will be automagically truncated. If the right hand
-     * side is const, it is not located in the primary register and handled by
-     * the expression parser code.
-     */
+    ** register is long, it will be automagically truncated. If the right hand
+    ** side is const, it is not located in the primary register and handled by
+    ** the expression parser code.
+    */
 
     /* Result is const if the right hand side was const */
     lhs |= (rhs & CF_CONST);
 
     /* The resulting type is that of the left hand side (that's why you called
-     * this function :-)
-     */
+    ** this function :-)
+    */
     return lhs;
 }
 
@@ -1219,147 +1420,119 @@ unsigned g_typecast (unsigned lhs, unsigned rhs)
 
 void g_scale (unsigned flags, long val)
 /* Scale the value in the primary register by the given value. If val is positive,
- * scale up, is val is negative, scale down. This function is used to scale
- * the operands or results of pointer arithmetic by the size of the type, the
- * pointer points to.
- */
+** scale up, is val is negative, scale down. This function is used to scale
+** the operands or results of pointer arithmetic by the size of the type, the
+** pointer points to.
+*/
 {
     int p2;
 
     /* Value may not be zero */
     if (val == 0) {
-               Internal ("Data type has no size");
+        Internal ("Data type has no size");
     } else if (val > 0) {
 
-       /* Scale up */
-       if ((p2 = powerof2 (val)) > 0 && p2 <= 3) {
-
-           /* Factor is 2, 4 or 8, use special function */
-           switch (flags & CF_TYPE) {
-
-               case CF_CHAR:
-                   if (flags & CF_FORCECHAR) {
-                       while (p2--) {
-                           AddCodeLine ("\tasl\ta");
-                       }
-                       break;
-                   }
-                   /* FALLTHROUGH */
-
-               case CF_INT:
-                   if (FavourSize || p2 >= 3) {
-                       if (flags & CF_UNSIGNED) {
-                           AddCodeLine ("\tjsr\tshlax%d", p2);
-                       } else {
-                           AddCodeLine ("\tjsr\taslax%d", p2);
-                       }
-                   } else {
-                       AddCodeLine ("\tstx\ttmp1");
-                       while (p2--) {
-                           AddCodeLine ("\tasl\ta");
-                           AddCodeLine ("\trol\ttmp1");
-                       }
-                       AddCodeLine ("\tldx\ttmp1");
-                   }
-                   break;
-
-               case CF_LONG:
-                   if (flags & CF_UNSIGNED) {
-                       AddCodeLine ("\tjsr\tshleax%d", p2);
-                   } else {
-                       AddCodeLine ("\tjsr\tasleax%d", p2);
-                   }
-                   break;
-
-               default:
-                   typeerror (flags);
-
-           }
-
-       } else if (val != 1) {
-
-                   /* Use a multiplication instead */
-           g_mul (flags | CF_CONST, val);
-
-       }
+        /* Scale up */
+        if ((p2 = PowerOf2 (val)) > 0 && p2 <= 4) {
+
+            /* Factor is 2, 4, 8 and 16, use special function */
+            switch (flags & CF_TYPEMASK) {
+
+                case CF_CHAR:
+                    if (flags & CF_FORCECHAR) {
+                        while (p2--) {
+                            AddCodeLine ("asl a");
+                        }
+                        break;
+                    }
+                    /* FALLTHROUGH */
+
+                case CF_INT:
+                    if (flags & CF_UNSIGNED) {
+                        AddCodeLine ("jsr shlax%d", p2);
+                    } else {
+                        AddCodeLine ("jsr aslax%d", p2);
+                    }
+                    break;
+
+                case CF_LONG:
+                    if (flags & CF_UNSIGNED) {
+                        AddCodeLine ("jsr shleax%d", p2);
+                    } else {
+                        AddCodeLine ("jsr asleax%d", p2);
+                    }
+                    break;
+
+                default:
+                    typeerror (flags);
+
+            }
+
+        } else if (val != 1) {
+
+            /* Use a multiplication instead */
+            g_mul (flags | CF_CONST, val);
+
+        }
 
     } else {
 
-       /* Scale down */
-       val = -val;
-       if ((p2 = powerof2 (val)) > 0 && p2 <= 3) {
-
-           /* Factor is 2, 4 or 8, use special function */
-           switch (flags & CF_TYPE) {
-
-               case CF_CHAR:
-                   if (flags & CF_FORCECHAR) {
-                       if (flags & CF_UNSIGNED) {
-                           while (p2--) {
-                               AddCodeLine ("\tlsr\ta");
-                           }
-                           break;
-                       } else if (p2 <= 2) {
-                           AddCodeLine ("\tcmp\t#$80");
-                           AddCodeLine ("\tror\ta");
-                           break;
-                       }
-                   }
-                   /* FALLTHROUGH */
-
-               case CF_INT:
-                   if (flags & CF_UNSIGNED) {
-                       if (FavourSize || p2 >= 3) {
-                           AddCodeLine ("\tjsr\tlsrax%d", p2);
-                       } else {
-                           AddCodeLine ("\tstx\ttmp1");
-                           while (p2--) {
-                               AddCodeLine ("\tlsr\ttmp1");
-                               AddCodeLine ("\tror\ta");
-                           }
-                           AddCodeLine ("\tldx\ttmp1");
-                       }
-                   } else {
-                       if (FavourSize || p2 >= 3) {
-                           AddCodeLine ("\tjsr\tasrax%d", p2);
-                       } else {
-                           AddCodeLine ("\tstx\ttmp1");
-                           while (p2--) {
-                               AddCodeLine ("\tcpx\t#$80");
-                               AddCodeLine ("\tror\ttmp1");
-                               AddCodeLine ("\tror\ta");
-                           }
-                           AddCodeLine ("\tldx\ttmp1");
-                       }
-                   }
-                   break;
-
-               case CF_LONG:
-                   if (flags & CF_UNSIGNED) {
-                       AddCodeLine ("\tjsr\tlsreax%d", p2);
-                   } else {
-                       AddCodeLine ("\tjsr\tasreax%d", p2);
-                   }
-                   break;
-
-               default:
-                   typeerror (flags);
-
-           }
-
-       } else if (val != 1) {
-
-                   /* Use a division instead */
-           g_div (flags | CF_CONST, val);
-
-       }
+        /* Scale down */
+        val = -val;
+        if ((p2 = PowerOf2 (val)) > 0 && p2 <= 4) {
+
+            /* Factor is 2, 4, 8 and 16 use special function */
+            switch (flags & CF_TYPEMASK) {
+
+                case CF_CHAR:
+                    if (flags & CF_FORCECHAR) {
+                        if (flags & CF_UNSIGNED) {
+                            while (p2--) {
+                                AddCodeLine ("lsr a");
+                            }
+                            break;
+                        } else if (p2 <= 2) {
+                            AddCodeLine ("cmp #$80");
+                            AddCodeLine ("ror a");
+                            break;
+                        }
+                    }
+                    /* FALLTHROUGH */
+
+                case CF_INT:
+                    if (flags & CF_UNSIGNED) {
+                        AddCodeLine ("jsr lsrax%d", p2);
+                    } else {
+                        AddCodeLine ("jsr asrax%d", p2);
+                    }
+                    break;
+
+                case CF_LONG:
+                    if (flags & CF_UNSIGNED) {
+                        AddCodeLine ("jsr lsreax%d", p2);
+                    } else {
+                        AddCodeLine ("jsr asreax%d", p2);
+                    }
+                    break;
+
+                default:
+                    typeerror (flags);
+
+            }
+
+        } else if (val != 1) {
+
+            /* Use a division instead */
+            g_div (flags | CF_CONST, val);
+
+        }
     }
 }
 
 
 
 /*****************************************************************************/
-/*             Adds and subs of variables fix a fixed address               */
+/*              Adds and subs of variables fix a fixed address               */
 /*****************************************************************************/
 
 
@@ -1367,83 +1540,89 @@ void g_scale (unsigned flags, long val)
 void g_addlocal (unsigned flags, int offs)
 /* Add a local variable to ax */
 {
+    unsigned L;
+
     /* Correct the offset and check it */
-    offs -= oursp;
+    offs -= StackPtr;
     CheckLocalOffs (offs);
 
-    switch (flags & CF_TYPE) {
-
-       case CF_CHAR:
-           AddCodeLine ("\tldy\t#$%02X", offs & 0xFF);
-           AddCodeLine ("\tclc");
-           AddCodeLine ("\tadc\t(sp),y");
-           AddCodeLine ("\tbcc\t*+3");
-           AddCodeLine ("\tinx");
-           AddCodeHint ("x:!");
-           break;
-
-       case CF_INT:
-           AddCodeLine ("\tldy\t#$%02X", offs & 0xFF);
-           AddCodeLine ("\tclc");
-           AddCodeLine ("\tadc\t(sp),y");
-           AddCodeLine ("\tpha");
-           AddCodeLine ("\ttxa");
-           AddCodeLine ("\tiny");
-           AddCodeLine ("\tadc\t(sp),y");
-           AddCodeLine ("\ttax");
-           AddCodeLine ("\tpla");
-           break;
+    switch (flags & CF_TYPEMASK) {
+
+        case CF_CHAR:
+            L = GetLocalLabel();
+            AddCodeLine ("ldy #$%02X", offs & 0xFF);
+            AddCodeLine ("clc");
+            AddCodeLine ("adc (sp),y");
+            AddCodeLine ("bcc %s", LocalLabelName (L));
+            AddCodeLine ("inx");
+            g_defcodelabel (L);
+            break;
+
+        case CF_INT:
+            AddCodeLine ("ldy #$%02X", offs & 0xFF);
+            AddCodeLine ("clc");
+            AddCodeLine ("adc (sp),y");
+            AddCodeLine ("pha");
+            AddCodeLine ("txa");
+            AddCodeLine ("iny");
+            AddCodeLine ("adc (sp),y");
+            AddCodeLine ("tax");
+            AddCodeLine ("pla");
+            break;
 
-       case CF_LONG:
-           /* Do it the old way */
-                   g_push (flags, 0);
-           g_getlocal (flags, offs);
-           g_add (flags, 0);
-           break;
+        case CF_LONG:
+            /* Do it the old way */
+            g_push (flags, 0);
+            g_getlocal (flags, offs);
+            g_add (flags, 0);
+            break;
 
-       default:
-           typeerror (flags);
+        default:
+            typeerror (flags);
 
     }
 }
 
 
 
-void g_addstatic (unsigned flags, unsigned long label, unsigned offs)
+void g_addstatic (unsigned flags, uintptr_t label, long offs)
 /* Add a static variable to ax */
 {
-    /* Create the correct label name */
-    char* lbuf = GetLabelName (flags, label, offs);
-
-    switch (flags & CF_TYPE) {
+    unsigned L;
 
-       case CF_CHAR:
-           AddCodeLine ("\tclc");
-           AddCodeLine ("\tadc\t%s", lbuf);
-           AddCodeLine ("\tbcc\t*+3");
-           AddCodeLine ("\tinx");
-           AddCodeHint ("x:!");
-           break;
-
-       case CF_INT:
-           AddCodeLine ("\tclc");
-           AddCodeLine ("\tadc\t%s", lbuf);
-           AddCodeLine ("\ttay");
-           AddCodeLine ("\ttxa");
-           AddCodeLine ("\tadc\t%s+1", lbuf);
-           AddCodeLine ("\ttax");
-           AddCodeLine ("\ttya");
-           break;
+    /* Create the correct label name */
+    const char* lbuf = GetLabelName (flags, label, offs);
+
+    switch (flags & CF_TYPEMASK) {
+
+        case CF_CHAR:
+            L = GetLocalLabel();
+            AddCodeLine ("clc");
+            AddCodeLine ("adc %s", lbuf);
+            AddCodeLine ("bcc %s", LocalLabelName (L));
+            AddCodeLine ("inx");
+            g_defcodelabel (L);
+            break;
+
+        case CF_INT:
+            AddCodeLine ("clc");
+            AddCodeLine ("adc %s", lbuf);
+            AddCodeLine ("tay");
+            AddCodeLine ("txa");
+            AddCodeLine ("adc %s+1", lbuf);
+            AddCodeLine ("tax");
+            AddCodeLine ("tya");
+            break;
 
-       case CF_LONG:
-           /* Do it the old way */
-                   g_push (flags, 0);
-           g_getstatic (flags, label, offs);
-           g_add (flags, 0);
-           break;
+        case CF_LONG:
+            /* Do it the old way */
+            g_push (flags, 0);
+            g_getstatic (flags, label, offs);
+            g_add (flags, 0);
+            break;
 
-       default:
-           typeerror (flags);
+        default:
+            typeerror (flags);
 
     }
 }
@@ -1451,216 +1630,190 @@ void g_addstatic (unsigned flags, unsigned long label, unsigned offs)
 
 
 /*****************************************************************************/
-/*            Compares of ax with a variable with fixed address             */
+/*                           Special op= functions                           */
 /*****************************************************************************/
 
 
 
-void g_cmplocal (unsigned flags, int offs)
-/* Compare a local variable to ax */
+void g_addeqstatic (unsigned flags, uintptr_t label, long offs,
+                    unsigned long val)
+/* Emit += for a static variable */
 {
-    Internal ("g_cmplocal not implemented");
-}
-
+    /* Create the correct label name */
+    const char* lbuf = GetLabelName (flags, label, offs);
 
+    /* Check the size and determine operation */
+    switch (flags & CF_TYPEMASK) {
+
+        case CF_CHAR:
+            if (flags & CF_FORCECHAR) {
+                AddCodeLine ("ldx #$00");
+                if (flags & CF_CONST) {
+                    if (val == 1) {
+                        AddCodeLine ("inc %s", lbuf);
+                        AddCodeLine ("lda %s", lbuf);
+                    } else {
+                        AddCodeLine ("lda #$%02X", (int)(val & 0xFF));
+                        AddCodeLine ("clc");
+                        AddCodeLine ("adc %s", lbuf);
+                        AddCodeLine ("sta %s", lbuf);
+                    }
+                } else {
+                    AddCodeLine ("clc");
+                    AddCodeLine ("adc %s", lbuf);
+                    AddCodeLine ("sta %s", lbuf);
+                }
+                if ((flags & CF_UNSIGNED) == 0) {
+                    unsigned L = GetLocalLabel();
+                    AddCodeLine ("bpl %s", LocalLabelName (L));
+                    AddCodeLine ("dex");
+                    g_defcodelabel (L);
+                }
+                break;
+            }
+            /* FALLTHROUGH */
+
+        case CF_INT:
+            if (flags & CF_CONST) {
+                if (val == 1) {
+                    unsigned L = GetLocalLabel ();
+                    AddCodeLine ("inc %s", lbuf);
+                    AddCodeLine ("bne %s", LocalLabelName (L));
+                    AddCodeLine ("inc %s+1", lbuf);
+                    g_defcodelabel (L);
+                    AddCodeLine ("lda %s", lbuf);               /* Hmmm... */
+                    AddCodeLine ("ldx %s+1", lbuf);
+                } else {
+                    AddCodeLine ("lda #$%02X", (int)(val & 0xFF));
+                    AddCodeLine ("clc");
+                    AddCodeLine ("adc %s", lbuf);
+                    AddCodeLine ("sta %s", lbuf);
+                    if (val < 0x100) {
+                        unsigned L = GetLocalLabel ();
+                        AddCodeLine ("bcc %s", LocalLabelName (L));
+                        AddCodeLine ("inc %s+1", lbuf);
+                        g_defcodelabel (L);
+                        AddCodeLine ("ldx %s+1", lbuf);
+                    } else {
+                        AddCodeLine ("lda #$%02X", (unsigned char)(val >> 8));
+                        AddCodeLine ("adc %s+1", lbuf);
+                        AddCodeLine ("sta %s+1", lbuf);
+                        AddCodeLine ("tax");
+                        AddCodeLine ("lda %s", lbuf);
+                    }
+                }
+            } else {
+                AddCodeLine ("clc");
+                AddCodeLine ("adc %s", lbuf);
+                AddCodeLine ("sta %s", lbuf);
+                AddCodeLine ("txa");
+                AddCodeLine ("adc %s+1", lbuf);
+                AddCodeLine ("sta %s+1", lbuf);
+                AddCodeLine ("tax");
+                AddCodeLine ("lda %s", lbuf);
+            }
+            break;
 
-void g_cmpstatic (unsigned flags, unsigned label, unsigned offs)
-/* Compare a static variable to ax */
-{
-    Internal ("g_cmpstatic not implemented");
+        case CF_LONG:
+            if (flags & CF_CONST) {
+                if (val < 0x100) {
+                    AddCodeLine ("ldy #<(%s)", lbuf);
+                    AddCodeLine ("sty ptr1");
+                    AddCodeLine ("ldy #>(%s)", lbuf);
+                    if (val == 1) {
+                        AddCodeLine ("jsr laddeq1");
+                    } else {
+                        AddCodeLine ("lda #$%02X", (int)(val & 0xFF));
+                        AddCodeLine ("jsr laddeqa");
+                    }
+                } else {
+                    g_getstatic (flags, label, offs);
+                    g_inc (flags, val);
+                    g_putstatic (flags, label, offs);
+                }
+            } else {
+                AddCodeLine ("ldy #<(%s)", lbuf);
+                AddCodeLine ("sty ptr1");
+                AddCodeLine ("ldy #>(%s)", lbuf);
+                AddCodeLine ("jsr laddeq");
+            }
+            break;
+
+        default:
+            typeerror (flags);
+    }
 }
 
 
 
-/*****************************************************************************/
-/*                          Special op= functions                           */
-/*****************************************************************************/
-
-
-
-void g_addeqstatic (unsigned flags, unsigned long label, unsigned offs,
-                           unsigned long val)
-/* Emit += for a static variable */
-{
-    /* Create the correct label name */
-    char* lbuf = GetLabelName (flags, label, offs);
-
-    /* Check the size and determine operation */
-    switch (flags & CF_TYPE) {
-
-               case CF_CHAR:
-                   if (flags & CF_FORCECHAR) {
-               AddCodeLine ("\tldx\t#$00");
-                       if (flags & CF_CONST) {
-                   if (val == 1) {
-                       AddCodeLine ("\tinc\t%s", lbuf);
-                       AddCodeLine ("\tlda\t%s", lbuf);
-                   } else {
-                               AddCodeLine ("\tlda\t#$%02X", val & 0xFF);
-                       AddCodeLine ("\tclc");
-                       AddCodeLine ("\tadc\t%s", lbuf);
-                       AddCodeLine ("\tsta\t%s", lbuf);
-                   }
-                       } else {
-                   AddCodeLine ("\tclc");
-                           AddCodeLine ("\tadc\t%s", lbuf);
-                   AddCodeLine ("\tsta\t%s", lbuf);
-                       }
-               if ((flags & CF_UNSIGNED) == 0) {
-                   AddCodeLine ("\tbpl\t*+3");
-                   AddCodeLine ("\tdex");
-                   AddCodeHint ("x:!");                /* Invalidate X */
-               }
-                       break;
-                   }
-                   /* FALLTHROUGH */
-
-               case CF_INT:
-                   if (flags & CF_CONST) {
-               if (val == 1) {
-                   label = GetLabel ();
-                   AddCodeLine ("\tinc\t%s", lbuf);
-                   AddCodeLine ("\tbne\tL%04X", label);
-                   AddCodeLine ("\tinc\t%s+1", lbuf);
-                   g_defloclabel (label);
-                   AddCodeLine ("\tlda\t%s", lbuf);            /* Hmmm... */
-                   AddCodeLine ("\tldx\t%s+1", lbuf);
-               } else {
-                           AddCodeLine ("\tlda\t#$%02X", val & 0xFF);
-                   AddCodeLine ("\tclc");
-                   AddCodeLine ("\tadc\t%s", lbuf);
-                   AddCodeLine ("\tsta\t%s", lbuf);
-                   if (val < 0x100) {
-                       label = GetLabel ();
-                       AddCodeLine ("\tbcc\tL%04X", label);
-                       AddCodeLine ("\tinc\t%s+1", lbuf);
-                               g_defloclabel (label);
-                       AddCodeLine ("\tldx\t%s+1", lbuf);
-                   } else {
-                               AddCodeLine ("\tlda\t#$%02X", (val >> 8) & 0xFF);
-                       AddCodeLine ("\tadc\t%s+1", lbuf);
-                       AddCodeLine ("\tsta\t%s+1", lbuf);
-                       AddCodeLine ("\ttax");
-                       AddCodeLine ("\tlda\t%s", lbuf);
-                   }
-               }
-                   } else {
-               AddCodeLine ("\tclc");
-                       AddCodeLine ("\tadc\t%s", lbuf);
-                       AddCodeLine ("\tsta\t%s", lbuf);
-                       AddCodeLine ("\ttxa");
-                       AddCodeLine ("\tadc\t%s+1", lbuf);
-                       AddCodeLine ("\tsta\t%s+1", lbuf);
-                       AddCodeLine ("\ttax");
-               AddCodeLine ("\tlda\t%s", lbuf);
-           }
-                   break;
-
-               case CF_LONG:
-           if (flags & CF_CONST) {
-               if (val < 0x100) {
-                   AddCodeLine ("\tldy\t#<(%s)", lbuf);
-                   AddCodeLine ("\tsty\tptr1");
-                   AddCodeLine ("\tldy\t#>(%s+1)", lbuf);
-                   if (val == 1) {
-                       AddCodeLine ("\tjsr\tladdeq1");
-                   } else {
-                       AddCodeLine ("\tlda\t#$%02X", val & 0xFF);
-                       AddCodeLine ("\tjsr\tladdeqa");
-                   }
-               } else {
-                   g_getstatic (flags, label, offs);
-                   g_inc (flags, val);
-                   g_putstatic (flags, label, offs);
-               }
-           } else {
-               AddCodeLine ("\tldy\t#<(%s)", lbuf);
-               AddCodeLine ("\tsty\tptr1");
-               AddCodeLine ("\tldy\t#>(%s+1)", lbuf);
-               AddCodeLine ("\tjsr\tladdeq");
-           }
-                   break;
-
-               default:
-                   typeerror (flags);
-    }
-}
-
-
-
-void g_addeqlocal (unsigned flags, int offs, unsigned long val)
+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;
-    CheckLocalOffs (offs);
+    Offs -= StackPtr;
+    CheckLocalOffs (Offs);
 
     /* Check the size and determine operation */
-    switch (flags & CF_TYPE) {
-
-               case CF_CHAR:
-                   if (flags & CF_FORCECHAR) {
-                       if (offs == 0) {
-                           AddCodeLine ("\tldx\t#$00");
-                           if (flags & CF_CONST) {
-                               AddCodeLine ("\tclc");
-                               AddCodeLine ("\tlda\t#$%02X", val & 0xFF);
-                               AddCodeLine ("\tadc\t(sp,x)");
-                               AddCodeLine ("\tsta\t(sp,x)");
-                           } else {
-                               AddCodeLine ("\tclc");
-                               AddCodeLine ("\tadc\t(sp,x)");
-                               AddCodeLine ("\tsta\t(sp,x)");
-                           }
-                       } else {
-                           ldyconst (offs);
-                   AddCodeLine ("\tldx\t#$00");
-                   if (flags & CF_CONST) {
-                       AddCodeLine ("\tclc");
-                               AddCodeLine ("\tlda\t#$%02X", val & 0xFF);
-                       AddCodeLine ("\tadc\t(sp),y");
-                       AddCodeLine ("\tsta\t(sp),y");
-                   } else {
-                       AddCodeLine ("\tclc");
-                       AddCodeLine ("\tadc\t(sp),y");
-                       AddCodeLine ("\tsta\t(sp),y");
-                   }
-               }
-               if ((flags & CF_UNSIGNED) == 0) {
-                   AddCodeLine ("\tbpl\t*+3");
-                   AddCodeLine ("\tdex");
-                   AddCodeHint ("x:!");        /* Invalidate X */
-               }
-                       break;
-                   }
-                   /* FALLTHROUGH */
-
-               case CF_INT:
-           if (flags & CF_CONST) {
-               g_getimmed (flags, val, 0);
-           }
-           if (offs == 0) {
-               AddCodeLine ("\tjsr\taddeq0sp");
-           } else {
-               ldyconst (offs);
-               AddCodeLine ("\tjsr\taddeqysp");
-           }
-                   break;
-
-               case CF_LONG:
-           if (flags & CF_CONST) {
-               g_getimmed (flags, val, 0);
-           }
-           if (offs == 0) {
-               AddCodeLine ("\tjsr\tladdeq0sp");
-           } else {
-               ldyconst (offs);
-               AddCodeLine ("\tjsr\tladdeqysp");
-           }
-                   break;
-
-               default:
-                   typeerror (flags);
+    switch (flags & CF_TYPEMASK) {
+
+        case CF_CHAR:
+            if (flags & CF_FORCECHAR) {
+                AddCodeLine ("ldy #$%02X", Offs);
+                AddCodeLine ("ldx #$00");
+                if (flags & CF_CONST) {
+                    AddCodeLine ("clc");
+                    AddCodeLine ("lda #$%02X", (int)(val & 0xFF));
+                    AddCodeLine ("adc (sp),y");
+                    AddCodeLine ("sta (sp),y");
+                } else {
+                    AddCodeLine ("clc");
+                    AddCodeLine ("adc (sp),y");
+                    AddCodeLine ("sta (sp),y");
+                }
+                if ((flags & CF_UNSIGNED) == 0) {
+                    unsigned L = GetLocalLabel();
+                    AddCodeLine ("bpl %s", LocalLabelName (L));
+                    AddCodeLine ("dex");
+                    g_defcodelabel (L);
+                }
+                break;
+            }
+            /* FALLTHROUGH */
+
+        case CF_INT:
+            AddCodeLine ("ldy #$%02X", Offs);
+            if (flags & CF_CONST) {
+                if (IS_Get (&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);
+            }
+            AddCodeLine ("ldy #$%02X", Offs);
+            AddCodeLine ("jsr laddeqysp");
+            break;
+
+        default:
+            typeerror (flags);
     }
 }
 
@@ -1670,232 +1823,193 @@ void g_addeqind (unsigned flags, unsigned offs, unsigned long val)
 /* Emit += for the location with address in ax */
 {
     /* If the offset is too large for a byte register, add the high byte
-     * of the offset to the primary. Beware: We need a special correction
-     * if the offset in the low byte will overflow in the operation.
-     */
+    ** of the offset to the primary. Beware: We need a special correction
+    ** if the offset in the low byte will overflow in the operation.
+    */
     offs = MakeByteOffs (flags, offs);
 
     /* Check the size and determine operation */
-    switch (flags & CF_TYPE) {
-
-               case CF_CHAR:
-           AddCodeLine ("\tsta\tptr1");
-           AddCodeLine ("\tstx\tptr1+1");
-           if (offs == 0) {
-               AddCodeLine ("\tldx\t#$00");
-               AddCodeLine ("\tlda\t#$%02X", val & 0xFF);
-               AddCodeLine ("\tclc");
-               AddCodeLine ("\tadc\t(ptr1,x)");
-               AddCodeLine ("\tsta\t(ptr1,x)");
-           } else {
-               AddCodeLine ("\tldy\t#$%02X", offs);
-                       AddCodeLine ("\tldx\t#$00");
-                       AddCodeLine ("\tlda\t#$%02X", val & 0xFF);
-                       AddCodeLine ("\tclc");
-                       AddCodeLine ("\tadc\t(ptr1),y");
-                       AddCodeLine ("\tsta\t(ptr1),y");
-           }
-           break;
-
-               case CF_INT:
-           if (!FavourSize) {
-               /* Lots of code, use only if size is not important */
-                       AddCodeLine ("\tsta\tptr1");
-               AddCodeLine ("\tstx\tptr1+1");
-               AddCodeLine ("\tldy\t#$%02X", offs);
-               AddCodeLine ("\tlda\t#$%02X", val & 0xFF);
-               AddCodeLine ("\tclc");
-               AddCodeLine ("\tadc\t(ptr1),y");
-               AddCodeLine ("\tsta\t(ptr1),y");
-               AddCodeLine ("\tpha");
-               AddCodeLine ("\tiny");
-               AddCodeLine ("\tlda\t#$%02X", (val >> 8) & 0xFF);
-               AddCodeLine ("\tadc\t(ptr1),y");
-               AddCodeLine ("\tsta\t(ptr1),y");
-               AddCodeLine ("\ttax");
-               AddCodeLine ("\tpla");
-               break;
-           }
-           /* FALL THROUGH */
-
-               case CF_LONG:
-                   AddCodeLine ("\tjsr\tpushax");      /* Push the address */
-           push (flags);                       /* Correct the internal sp */
-           g_getind (flags, offs);             /* Fetch the value */
-           g_inc (flags, val);                 /* Increment value in primary */
-           g_putind (flags, offs);             /* Store the value back */
-                   break;
-
-               default:
-                   typeerror (flags);
-    }
-}
-
-
-
-void g_subeqstatic (unsigned flags, unsigned long label, unsigned offs,
-                           unsigned long val)
+    switch (flags & CF_TYPEMASK) {
+
+        case CF_CHAR:
+            AddCodeLine ("sta ptr1");
+            AddCodeLine ("stx ptr1+1");
+            AddCodeLine ("ldy #$%02X", offs);
+            AddCodeLine ("ldx #$00");
+            AddCodeLine ("lda #$%02X", (int)(val & 0xFF));
+            AddCodeLine ("clc");
+            AddCodeLine ("adc (ptr1),y");
+            AddCodeLine ("sta (ptr1),y");
+            break;
+
+        case CF_INT:
+        case CF_LONG:
+            AddCodeLine ("jsr pushax");         /* Push the address */
+            push (CF_PTR);                      /* Correct the internal sp */
+            g_getind (flags, offs);             /* Fetch the value */
+            g_inc (flags, val);                 /* Increment value in primary */
+            g_putind (flags, offs);             /* Store the value back */
+            break;
+
+        default:
+            typeerror (flags);
+    }
+}
+
+
+
+void g_subeqstatic (unsigned flags, uintptr_t 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) {
-
-               case CF_CHAR:
-                   if (flags & CF_FORCECHAR) {
-                       AddCodeLine ("\tldx\t#$00");
-                       if (flags & CF_CONST) {
-                           if (val == 1) {
-                               AddCodeLine ("\tdec\t%s", lbuf);
-                               AddCodeLine ("\tlda\t%s", lbuf);
-                           } else {
-                               AddCodeLine ("\tsec");
-                               AddCodeLine ("\tlda\t%s", lbuf);
-                               AddCodeLine ("\tsbc\t#$%02X", val & 0xFF);
-                               AddCodeLine ("\tsta\t%s", lbuf);
-                           }
-                       } else {
-                           AddCodeLine ("\tsec");
-                           AddCodeLine ("\tsta\ttmp1");
-                           AddCodeLine ("\tlda\t%s", lbuf);
-                           AddCodeLine ("\tsbc\ttmp1");
-                           AddCodeLine ("\tsta\t%s", lbuf);
-                       }
-                       if ((flags & CF_UNSIGNED) == 0) {
-                           AddCodeLine ("\tbpl\t*+3");
-                           AddCodeLine ("\tdex");
-                           AddCodeHint ("x:!");                /* Invalidate X */
-                       }
-                       break;
-                   }
-                   /* FALLTHROUGH */
-
-               case CF_INT:
-           AddCodeLine ("\tsec");
-           if (flags & CF_CONST) {
-               AddCodeLine ("\tlda\t%s", lbuf);
-               AddCodeLine ("\tsbc\t#$%02X", val & 0xFF);
-               AddCodeLine ("\tsta\t%s", lbuf);
-               if (val < 0x100) {
-                   label = GetLabel ();
-                   AddCodeLine ("\tbcs\tL%04X", label);
-                   AddCodeLine ("\tdec\t%s+1", lbuf);
-                   g_defloclabel (label);
-                   AddCodeLine ("\tldx\t%s+1", lbuf);
-               } else {
-                   AddCodeLine ("\tlda\t%s+1", lbuf);
-                   AddCodeLine ("\tsbc\t#$%02X", (val >> 8) & 0xFF);
-                   AddCodeLine ("\tsta\t%s+1", lbuf);
-                   AddCodeLine ("\ttax");
-                   AddCodeLine ("\tlda\t%s", lbuf);
-               }
-           } else {
-               AddCodeLine ("\tsta\ttmp1");
-               AddCodeLine ("\tlda\t%s", lbuf);
-               AddCodeLine ("\tsbc\ttmp1");
-               AddCodeLine ("\tsta\t%s", lbuf);
-                       AddCodeLine ("\tstx\ttmp1");
-               AddCodeLine ("\tlda\t%s+1", lbuf);
-               AddCodeLine ("\tsbc\ttmp1");
-               AddCodeLine ("\tsta\t%s+1", lbuf);
-               AddCodeLine ("\ttax");
-               AddCodeLine ("\tlda\t%s", lbuf);
-           }
-                   break;
-
-               case CF_LONG:
-           if (flags & CF_CONST) {
-               if (val < 0x100) {
-                   AddCodeLine ("\tldy\t#<(%s)", lbuf);
-                   AddCodeLine ("\tsty\tptr1");
-                   AddCodeLine ("\tldy\t#>(%s+1)", lbuf);
-                   if (val == 1) {
-                       AddCodeLine ("\tjsr\tlsubeq1");
-                   } else {
-                       AddCodeLine ("\tlda\t#$%02X", val & 0xFF);
-                       AddCodeLine ("\tjsr\tlsubeqa");
-                   }
-               } else {
-                   g_getstatic (flags, label, offs);
-                   g_dec (flags, val);
-                   g_putstatic (flags, label, offs);
-               }
-           } else {
-               AddCodeLine ("\tldy\t#<(%s)", lbuf);
-               AddCodeLine ("\tsty\tptr1");
-               AddCodeLine ("\tldy\t#>(%s+1)", lbuf);
-               AddCodeLine ("\tjsr\tlsubeq");
-                   }
-                   break;
-
-               default:
-                   typeerror (flags);
-    }
-}
-
-
-
-void g_subeqlocal (unsigned flags, int offs, unsigned long val)
+    switch (flags & CF_TYPEMASK) {
+
+        case CF_CHAR:
+            if (flags & CF_FORCECHAR) {
+                AddCodeLine ("ldx #$00");
+                if (flags & CF_CONST) {
+                    if (val == 1) {
+                        AddCodeLine ("dec %s", lbuf);
+                        AddCodeLine ("lda %s", lbuf);
+                    } else {
+                        AddCodeLine ("lda %s", lbuf);
+                        AddCodeLine ("sec");
+                        AddCodeLine ("sbc #$%02X", (int)(val & 0xFF));
+                        AddCodeLine ("sta %s", lbuf);
+                    }
+                } else {
+                    AddCodeLine ("eor #$FF");
+                    AddCodeLine ("sec");
+                    AddCodeLine ("adc %s", lbuf);
+                    AddCodeLine ("sta %s", lbuf);
+                }
+                if ((flags & CF_UNSIGNED) == 0) {
+                    unsigned L = GetLocalLabel();
+                    AddCodeLine ("bpl %s", LocalLabelName (L));
+                    AddCodeLine ("dex");
+                    g_defcodelabel (L);
+                }
+                break;
+            }
+            /* FALLTHROUGH */
+
+        case CF_INT:
+            if (flags & CF_CONST) {
+                AddCodeLine ("lda %s", lbuf);
+                AddCodeLine ("sec");
+                AddCodeLine ("sbc #$%02X", (unsigned char)val);
+                AddCodeLine ("sta %s", lbuf);
+                if (val < 0x100) {
+                    unsigned L = GetLocalLabel ();
+                    AddCodeLine ("bcs %s", LocalLabelName (L));
+                    AddCodeLine ("dec %s+1", lbuf);
+                    g_defcodelabel (L);
+                    AddCodeLine ("ldx %s+1", lbuf);
+                } else {
+                    AddCodeLine ("lda %s+1", lbuf);
+                    AddCodeLine ("sbc #$%02X", (unsigned char)(val >> 8));
+                    AddCodeLine ("sta %s+1", lbuf);
+                    AddCodeLine ("tax");
+                    AddCodeLine ("lda %s", lbuf);
+                }
+            } else {
+                AddCodeLine ("eor #$FF");
+                AddCodeLine ("sec");
+                AddCodeLine ("adc %s", lbuf);
+                AddCodeLine ("sta %s", lbuf);
+                AddCodeLine ("txa");
+                AddCodeLine ("eor #$FF");
+                AddCodeLine ("adc %s+1", lbuf);
+                AddCodeLine ("sta %s+1", lbuf);
+                AddCodeLine ("tax");
+                AddCodeLine ("lda %s", lbuf);
+            }
+            break;
+
+        case CF_LONG:
+            if (flags & CF_CONST) {
+                if (val < 0x100) {
+                    AddCodeLine ("ldy #<(%s)", lbuf);
+                    AddCodeLine ("sty ptr1");
+                    AddCodeLine ("ldy #>(%s)", lbuf);
+                    AddCodeLine ("lda #$%02X", (unsigned char)val);
+                    AddCodeLine ("jsr lsubeqa");
+                } else {
+                    g_getstatic (flags, label, offs);
+                    g_dec (flags, val);
+                    g_putstatic (flags, label, offs);
+                }
+            } else {
+                AddCodeLine ("ldy #<(%s)", lbuf);
+                AddCodeLine ("sty ptr1");
+                AddCodeLine ("ldy #>(%s)", lbuf);
+                AddCodeLine ("jsr lsubeq");
+            }
+            break;
+
+        default:
+            typeerror (flags);
+    }
+}
+
+
+
+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;
-    CheckLocalOffs (offs);
+    Offs -= StackPtr;
+    CheckLocalOffs (Offs);
 
     /* Check the size and determine operation */
-    switch (flags & CF_TYPE) {
-
-               case CF_CHAR:
-                   if (flags & CF_FORCECHAR) {
-               ldyconst (offs);
-               AddCodeLine ("\tldx\t#$00");
-                       AddCodeLine ("\tsec");
-               if (flags & CF_CONST) {
-                   AddCodeLine ("\tlda\t(sp),y");
-                   AddCodeLine ("\tsbc\t#$%02X", val & 0xFF);
-               } else {
-                   AddCodeLine ("\tsta\ttmp1");
-                   AddCodeLine ("\tlda\t(sp),y");
-                   AddCodeLine ("\tsbc\ttmp1");
-               }
-                       AddCodeLine ("\tsta\t(sp),y");
-               if ((flags & CF_UNSIGNED) == 0) {
-                   AddCodeLine ("\tbpl\t*+3");
-                   AddCodeLine ("\tdex");
-                   AddCodeHint ("x:!");                /* Invalidate X */
-               }
-                       break;
-                   }
-                   /* FALLTHROUGH */
-
-               case CF_INT:
-           if (flags & CF_CONST) {
-               g_getimmed (flags, val, 0);
-           }
-           if (offs == 0) {
-               AddCodeLine ("\tjsr\tsubeq0sp");
-           } else {
-               ldyconst (offs);
-               AddCodeLine ("\tjsr\tsubeqysp");
-           }
-                   break;
-
-               case CF_LONG:
-           if (flags & CF_CONST) {
-               g_getimmed (flags, val, 0);
-           }
-           if (offs == 0) {
-               AddCodeLine ("\tjsr\tlsubeq0sp");
-           } else {
-               ldyconst (offs);
-               AddCodeLine ("\tjsr\tlsubeqysp");
-           }
-                   break;
-
-               default:
-                   typeerror (flags);
+    switch (flags & CF_TYPEMASK) {
+
+        case CF_CHAR:
+            if (flags & CF_FORCECHAR) {
+                AddCodeLine ("ldy #$%02X", Offs);
+                AddCodeLine ("ldx #$00");
+                if (flags & CF_CONST) {
+                    AddCodeLine ("lda (sp),y");
+                    AddCodeLine ("sec");
+                    AddCodeLine ("sbc #$%02X", (unsigned char)val);
+                } else {
+                    AddCodeLine ("eor #$FF");
+                    AddCodeLine ("sec");
+                    AddCodeLine ("adc (sp),y");
+                }
+                AddCodeLine ("sta (sp),y");
+                if ((flags & CF_UNSIGNED) == 0) {
+                    unsigned L = GetLocalLabel();
+                    AddCodeLine ("bpl %s", LocalLabelName (L));
+                    AddCodeLine ("dex");
+                    g_defcodelabel (L);
+                }
+                break;
+            }
+            /* FALLTHROUGH */
+
+        case CF_INT:
+            if (flags & CF_CONST) {
+                g_getimmed (flags, val, 0);
+            }
+            AddCodeLine ("ldy #$%02X", Offs);
+            AddCodeLine ("jsr subeqysp");
+            break;
+
+        case CF_LONG:
+            if (flags & CF_CONST) {
+                g_getimmed (flags, val, 0);
+            }
+            AddCodeLine ("ldy #$%02X", Offs);
+            AddCodeLine ("jsr lsubeqysp");
+            break;
+
+        default:
+            typeerror (flags);
     }
 }
 
@@ -1905,122 +2019,101 @@ void g_subeqind (unsigned flags, unsigned offs, unsigned long val)
 /* Emit -= for the location with address in ax */
 {
     /* If the offset is too large for a byte register, add the high byte
-     * of the offset to the primary. Beware: We need a special correction
-     * if the offset in the low byte will overflow in the operation.
-     */
+    ** of the offset to the primary. Beware: We need a special correction
+    ** if the offset in the low byte will overflow in the operation.
+    */
     offs = MakeByteOffs (flags, offs);
 
     /* Check the size and determine operation */
-    switch (flags & CF_TYPE) {
-
-               case CF_CHAR:
-           AddCodeLine ("\tsta\tptr1");
-           AddCodeLine ("\tstx\tptr1+1");
-           if (offs == 0) {
-               AddCodeLine ("\tldx\t#$00");
-               AddCodeLine ("\tlda\t(ptr1,x)");
-                       AddCodeLine ("\tsec");
-               AddCodeLine ("\tsbc\t#$%02X", val & 0xFF);
-               AddCodeLine ("\tsta\t(ptr1,x)");
-           } else {
-                       AddCodeLine ("\tldy\t#$%02X", offs);
-               AddCodeLine ("\tldx\t#$00");
-               AddCodeLine ("\tlda\t(ptr1),y");
-               AddCodeLine ("\tsec");
-               AddCodeLine ("\tsbc\t#$%02X", val & 0xFF);
-               AddCodeLine ("\tsta\t(ptr1),y");
-           }
-           break;
-
-               case CF_INT:
-           if (!FavourSize) {
-               /* Lots of code, use only if size is not important */
-               AddCodeLine ("\tsta\tptr1");
-                       AddCodeLine ("\tstx\tptr1+1");
-               AddCodeLine ("\tldy\t#$%02X", offs);
-               AddCodeLine ("\tlda\t(ptr1),y");
-               AddCodeLine ("\tsec");
-               AddCodeLine ("\tsbc\t#$%02X", val & 0xFF);
-               AddCodeLine ("\tsta\t(ptr1),y");
-               AddCodeLine ("\tpha");
-               AddCodeLine ("\tiny");
-               AddCodeLine ("\tlda\t(ptr1),y");
-               AddCodeLine ("\tsbc\t#$%02X", (val >> 8) & 0xFF);
-               AddCodeLine ("\tsta\t(ptr1),y");
-               AddCodeLine ("\ttax");
-               AddCodeLine ("\tpla");
-               break;
-           }
-           /* FALL THROUGH */
-
-               case CF_LONG:
-                   AddCodeLine ("\tjsr\tpushax");      /* Push the address */
-           push (flags);                       /* Correct the internal sp */
-           g_getind (flags, offs);             /* Fetch the value */
-           g_dec (flags, val);                 /* Increment value in primary */
-           g_putind (flags, offs);             /* Store the value back */
-                   break;
-
-               default:
-                   typeerror (flags);
+    switch (flags & CF_TYPEMASK) {
+
+        case CF_CHAR:
+            AddCodeLine ("sta ptr1");
+            AddCodeLine ("stx ptr1+1");
+            AddCodeLine ("ldy #$%02X", offs);
+            AddCodeLine ("ldx #$00");
+            AddCodeLine ("lda (ptr1),y");
+            AddCodeLine ("sec");
+            AddCodeLine ("sbc #$%02X", (unsigned char)val);
+            AddCodeLine ("sta (ptr1),y");
+            break;
+
+        case CF_INT:
+        case CF_LONG:
+            AddCodeLine ("jsr pushax");         /* Push the address */
+            push (CF_PTR);                      /* Correct the internal sp */
+            g_getind (flags, offs);             /* Fetch the value */
+            g_dec (flags, val);                 /* Increment value in primary */
+            g_putind (flags, offs);             /* Store the value back */
+            break;
+
+        default:
+            typeerror (flags);
     }
 }
 
 
 
 /*****************************************************************************/
-/*                Add a variable address to the value in ax                 */
+/*                 Add a variable address to the value in ax                 */
 /*****************************************************************************/
 
 
 
-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 */
-       CheckLocalOffs (offs);
-       AddCodeLine ("\tclc");
-       AddCodeLine ("\tadc\t#$%02X", offs & 0xFF);
-               AddCodeLine ("\tbcc\t*+4");     /* Do also skip the CLC insn below */
-       AddCodeLine ("\tinx");
-       AddCodeHint ("x:!");                    /* Invalidate X */
+        /* We cannot address more then 256 bytes of locals anyway */
+        L = GetLocalLabel();
+        CheckLocalOffs (offs);
+        AddCodeLine ("clc");
+        AddCodeLine ("adc #$%02X", offs & 0xFF);
+        /* Do also skip the CLC insn below */
+        AddCodeLine ("bcc %s", LocalLabelName (L));
+        AddCodeLine ("inx");
     }
 
     /* Add the current stackpointer value */
-    AddCodeLine ("\tclc");
-    AddCodeLine ("\tadc\tsp");
-    AddCodeLine ("\ttay");
-    AddCodeLine ("\ttxa");
-    AddCodeLine ("\tadc\tsp+1");
-    AddCodeLine ("\ttax");
-    AddCodeLine ("\ttya");
+    AddCodeLine ("clc");
+    if (L != 0) {
+        /* Label was used above */
+        g_defcodelabel (L);
+    }
+    AddCodeLine ("adc sp");
+    AddCodeLine ("tay");
+    AddCodeLine ("txa");
+    AddCodeLine ("adc sp+1");
+    AddCodeLine ("tax");
+    AddCodeLine ("tya");
 }
 
 
 
-void g_addaddr_static (unsigned flags, unsigned long label, unsigned offs)
+void g_addaddr_static (unsigned flags, uintptr_t 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 ("\tclc");
-    AddCodeLine ("\tadc\t#<(%s)", lbuf);
-    AddCodeLine ("\ttay");
-    AddCodeLine ("\ttxa");
-    AddCodeLine ("\tadc\t#>(%s)", lbuf);
-    AddCodeLine ("\ttax");
-    AddCodeLine ("\ttya");
+    AddCodeLine ("clc");
+    AddCodeLine ("adc #<(%s)", lbuf);
+    AddCodeLine ("tay");
+    AddCodeLine ("txa");
+    AddCodeLine ("adc #>(%s)", lbuf);
+    AddCodeLine ("tax");
+    AddCodeLine ("tya");
 }
 
 
 
 /*****************************************************************************/
-/*                                                                          */
+/*                                                                           */
 /*****************************************************************************/
 
 
@@ -2029,55 +2122,55 @@ void g_save (unsigned flags)
 /* Copy primary register to hold register. */
 {
     /* Check the size and determine operation */
-    switch (flags & CF_TYPE) {
+    switch (flags & CF_TYPEMASK) {
 
-       case CF_CHAR:
-           if (flags & CF_FORCECHAR) {
-               AddCodeLine ("\tpha");
-               break;
-           }
-           /* FALLTHROUGH */
+        case CF_CHAR:
+            if (flags & CF_FORCECHAR) {
+                AddCodeLine ("pha");
+                break;
+            }
+            /* FALLTHROUGH */
 
-       case CF_INT:
-           AddCodeLine ("\tsta\tregsave");
-           AddCodeLine ("\tstx\tregsave+1");
-           break;
+        case CF_INT:
+            AddCodeLine ("sta regsave");
+            AddCodeLine ("stx regsave+1");
+            break;
 
-       case CF_LONG:
-           AddCodeLine ("\tjsr\tsaveeax");
-           break;
+        case CF_LONG:
+            AddCodeLine ("jsr saveeax");
+            break;
 
-       default:
-           typeerror (flags);
+        default:
+            typeerror (flags);
     }
 }
 
 
 
 void g_restore (unsigned flags)
-/* Copy hold register to P. */
+/* Copy hold register to primary. */
 {
     /* Check the size and determine operation */
-    switch (flags & CF_TYPE) {
+    switch (flags & CF_TYPEMASK) {
 
-       case CF_CHAR:
-           if (flags & CF_FORCECHAR) {
-               AddCodeLine ("\tpla");
-               break;
-           }
-           /* FALLTHROUGH */
+        case CF_CHAR:
+            if (flags & CF_FORCECHAR) {
+                AddCodeLine ("pla");
+                break;
+            }
+            /* FALLTHROUGH */
 
-       case CF_INT:
-           AddCodeLine ("\tlda\tregsave");
-           AddCodeLine ("\tldx\tregsave+1");
-           break;
+        case CF_INT:
+            AddCodeLine ("lda regsave");
+            AddCodeLine ("ldx regsave+1");
+            break;
 
-       case CF_LONG:
-           AddCodeLine ("\tjsr\tresteax");
-           break;
+        case CF_LONG:
+            AddCodeLine ("jsr resteax");
+            break;
 
-       default:
-           typeerror (flags);
+        default:
+            typeerror (flags);
     }
 }
 
@@ -2085,119 +2178,98 @@ void g_restore (unsigned flags)
 
 void g_cmp (unsigned flags, unsigned long val)
 /* Immidiate compare. The primary register will not be changed, Z flag
- * will be set.
- */
+** will be set.
+*/
 {
-    /* Check the size and determine operation */
-    switch (flags & CF_TYPE) {
+    unsigned L;
 
-       case CF_CHAR:
-           if (flags & CF_FORCECHAR) {
-               AddCodeLine ("\tcmp\t#$%02X", val & 0xFF);
-               break;
-           }
-           /* FALLTHROUGH */
-
-       case CF_INT:
-           AddCodeLine ("\tcmp\t#$%02X", val & 0xFF);
-                   AddCodeLine ("\tbne\t*+4");
-           AddCodeLine ("\tcpx\t#$%02X", (val >> 8) & 0xFF);
-           break;
+    /* Check the size and determine operation */
+    switch (flags & CF_TYPEMASK) {
+
+        case CF_CHAR:
+            if (flags & CF_FORCECHAR) {
+                AddCodeLine ("cmp #$%02X", (unsigned char)val);
+                break;
+            }
+            /* FALLTHROUGH */
+
+        case CF_INT:
+            L = GetLocalLabel();
+            AddCodeLine ("cmp #$%02X", (unsigned char)val);
+            AddCodeLine ("bne %s", LocalLabelName (L));
+            AddCodeLine ("cpx #$%02X", (unsigned char)(val >> 8));
+            g_defcodelabel (L);
+            break;
 
         case CF_LONG:
-           Internal ("g_cmp: Long compares not implemented");
-           break;
+            Internal ("g_cmp: Long compares not implemented");
+            break;
 
-       default:
-           typeerror (flags);
+        default:
+            typeerror (flags);
     }
 }
 
 
 
-static void oper (unsigned flags, unsigned long val, char** subs)
-/* Encode a binary operation. subs is a pointer to four groups of three
- * strings:
- *     0-2     --> Operate on ints
- *     3-5     --> Operate on unsigneds
- *     6-8     --> Operate on longs
- *     9-11    --> Operate on unsigned longs
- *
- * The first subroutine names in each string group is used to encode an
- * operation with a zero constant, the second to encode an operation with
- * a 8 bit constant, and the third is used in all other cases.
- */
+static void oper (unsigned Flags, unsigned long Val, const char* const* Subs)
+/* Encode a binary operation. subs is a pointer to four strings:
+**      0       --> Operate on ints
+**      1       --> Operate on unsigneds
+**      2       --> Operate on longs
+**      3       --> Operate on unsigned longs
+*/
 {
-    unsigned offs;
-
     /* Determine the offset into the array */
-    offs = (flags & CF_UNSIGNED)? 3 : 0;
-    switch (flags & CF_TYPE) {
-       case CF_CHAR:
-       case CF_INT:
-           break;
-
-       case CF_LONG:
-           offs += 6;
-           break;
-
-       default:
-           typeerror (flags);
+    if (Flags & CF_UNSIGNED) {
+        ++Subs;
+    }
+    if ((Flags & CF_TYPEMASK) == CF_LONG) {
+        Subs += 2;
     }
 
-    /* Encode the operation */
-    if (flags & CF_CONST) {
-       /* Constant value given */
-       if (val == 0 && subs [offs+0]) {
-           /* Special case: constant with value zero */
-           AddCodeLine ("\tjsr\t%s", subs [offs+0]);
-       } else if (val < 0x100 && subs [offs+1]) {
-           /* Special case: constant with high byte zero */
-           ldaconst (val);             /* Load low byte */
-           AddCodeLine ("\tjsr\t%s", subs [offs+1]);
-       } else {
-           /* Others: arbitrary constant value */
-           g_getimmed (flags, val, 0);                 /* Load value */
-           AddCodeLine ("\tjsr\t%s", subs [offs+2]);
-       }
-    } else {
-       /* Value not constant (is already in (e)ax) */
-       AddCodeLine ("\tjsr\t%s", subs [offs+2]);
+    /* Load the value if it is not already in the primary */
+    if (Flags & CF_CONST) {
+        /* Load value */
+        g_getimmed (Flags, Val, 0);
     }
 
+    /* Output the operation */
+    AddCodeLine ("jsr %s", *Subs);
+
     /* The operation will pop it's argument */
-    pop (flags);
+    pop (Flags);
 }
 
 
 
 void g_test (unsigned flags)
-/* Force a test to set cond codes right */
+/* Test the value in the primary and set the condition codes */
 {
-    switch (flags & CF_TYPE) {
+    switch (flags & CF_TYPEMASK) {
 
-       case CF_CHAR:
-           if (flags & CF_FORCECHAR) {
-               AddCodeLine ("\ttax");
-               break;
-           }
-           /* FALLTHROUGH */
+        case CF_CHAR:
+            if (flags & CF_FORCECHAR) {
+                AddCodeLine ("tax");
+                break;
+            }
+            /* FALLTHROUGH */
 
-       case CF_INT:
-           AddCodeLine ("\tstx\ttmp1");
-           AddCodeLine ("\tora\ttmp1");
-           break;
+        case CF_INT:
+            AddCodeLine ("stx tmp1");
+            AddCodeLine ("ora tmp1");
+            break;
 
-       case CF_LONG:
-           if (flags & CF_UNSIGNED) {
-               AddCodeLine ("\tjsr\tutsteax");
-           } else {
-               AddCodeLine ("\tjsr\ttsteax");
-           }
-           break;
+        case CF_LONG:
+            if (flags & CF_UNSIGNED) {
+                AddCodeLine ("jsr utsteax");
+            } else {
+                AddCodeLine ("jsr tsteax");
+            }
+            break;
 
-       default:
-           typeerror (flags);
+        default:
+            typeerror (flags);
 
     }
 }
@@ -2207,68 +2279,52 @@ 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 (FavourSize && val <= 2) {
-               AddCodeLine ("\tjsr\tpushc%d", (int) val);
-           } else {
-               ldaconst (val);
-               AddCodeLine ("\tjsr\tpusha");
-           }
-
-       } else {
-
-           /* Handle as 16 bit value */
-           hi = (unsigned char) (val >> 8);
-           if (val <= 7) {
-               AddCodeLine ("\tjsr\tpush%u", (unsigned) val);
-           } else if (hi == 0 || hi == 0xFF) {
-               /* Use special function */
-               ldaconst (val);
-                       AddCodeLine ("\tjsr\t%s", (hi == 0)? "pusha0" : "pushaFF");
-           } else {
-               /* Long way ... */
-               g_getimmed (flags, val, 0);
-               AddCodeLine ("\tjsr\tpushax");
-           }
-       }
+    if (flags & CF_CONST && (flags & CF_TYPEMASK) != CF_LONG) {
+
+        /* We have a constant 8 or 16 bit value */
+        if ((flags & CF_TYPEMASK) == CF_CHAR && (flags & CF_FORCECHAR)) {
+
+            /* Handle as 8 bit value */
+            AddCodeLine ("lda #$%02X", (unsigned char) val);
+            AddCodeLine ("jsr pusha");
+
+        } else {
+
+            /* Handle as 16 bit value */
+            g_getimmed (flags, val, 0);
+            AddCodeLine ("jsr pushax");
+        }
 
     } else {
 
-       /* Value is not 16 bit or not constant */
-       if (flags & CF_CONST) {
-           /* Constant 32 bit value, load into eax */
-           g_getimmed (flags, val, 0);
-       }
+        /* Value is not 16 bit or not constant */
+        if (flags & CF_CONST) {
+            /* Constant 32 bit value, load into eax */
+            g_getimmed (flags, val, 0);
+        }
 
-       /* Push the primary register */
-       switch (flags & CF_TYPE) {
+        /* Push the primary register */
+        switch (flags & CF_TYPEMASK) {
 
-           case CF_CHAR:
-               if (flags & CF_FORCECHAR) {
-                   /* Handle as char */
-                   AddCodeLine ("\tjsr\tpusha");
-                   break;
-               }
-               /* FALL THROUGH */
-           case CF_INT:
-               AddCodeLine ("\tjsr\tpushax");
-               break;
+            case CF_CHAR:
+                if (flags & CF_FORCECHAR) {
+                    /* Handle as char */
+                    AddCodeLine ("jsr pusha");
+                    break;
+                }
+                /* FALL THROUGH */
+            case CF_INT:
+                AddCodeLine ("jsr pushax");
+                break;
 
-           case CF_LONG:
-               AddCodeLine ("\tjsr\tpusheax");
-               break;
+            case CF_LONG:
+                AddCodeLine ("jsr pusheax");
+                break;
 
-           default:
-               typeerror (flags);
+            default:
+                typeerror (flags);
 
-       }
+        }
 
     }
 
@@ -2280,152 +2336,176 @@ void g_push (unsigned flags, unsigned long val)
 
 void g_swap (unsigned flags)
 /* Swap the primary register and the top of the stack. flags give the type
- * of *both* values (must have same size).
- */
+** of *both* values (must have same size).
+*/
 {
-    switch (flags & CF_TYPE) {
+    switch (flags & CF_TYPEMASK) {
 
-       case CF_CHAR:
-       case CF_INT:
-           AddCodeLine ("\tjsr\tswapstk");
-           break;
+        case CF_CHAR:
+        case CF_INT:
+            AddCodeLine ("jsr swapstk");
+            break;
 
-       case CF_LONG:
-           AddCodeLine ("\tjsr\tswapestk");
-           break;
+        case CF_LONG:
+            AddCodeLine ("jsr swapestk");
+            break;
 
-       default:
-           typeerror (flags);
+        default:
+            typeerror (flags);
 
     }
 }
 
 
 
-void g_call (unsigned flags, char* lbl, unsigned argsize)
+void g_call (unsigned Flags, const char* Label, unsigned ArgSize)
 /* Call the specified subroutine name */
 {
-    if ((flags & CF_FIXARGC) == 0) {
-       /* Pass arg count */
-       ldyconst (argsize);
+    if ((Flags & CF_FIXARGC) == 0) {
+        /* Pass the argument count */
+        AddCodeLine ("ldy #$%02X", ArgSize);
     }
-    AddCodeLine ("\tjsr\t_%s", lbl);
-    oursp += argsize;                  /* callee pops args */
+    AddCodeLine ("jsr _%s", Label);
+    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 */
+            AddCodeLine ("ldy #$%02X", 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 ("\tjsr\tcallax");     /* do the call */
-    oursp += argsize;                  /* callee pops args */
+
+    /* Callee pops args */
+    StackPtr += ArgSize;
 }
 
 
 
-void g_jump (unsigned label)
+void g_jump (unsigned Label)
 /* Jump to specified internal label number */
 {
-    AddCodeLine ("\tjmp\tL%04X", label);
+    AddCodeLine ("jmp %s", LocalLabelName (Label));
 }
 
 
 
-void g_switch (unsigned flags)
-/* Output switch statement preample */
+void g_truejump (unsigned flags attribute ((unused)), unsigned label)
+/* Jump to label if zero flag clear */
 {
-    switch (flags & CF_TYPE) {
-
-       case CF_CHAR:
-       case CF_INT:
-           AddCodeLine ("\tjsr\tswitch");
-           break;
-
-       case CF_LONG:
-           AddCodeLine ("\tjsr\tlswitch");
-           break;
-
-       default:
-           typeerror (flags);
-
-    }
+    AddCodeLine ("jne %s", LocalLabelName (label));
 }
 
 
 
-void g_case (unsigned flags, unsigned label, unsigned long val)
-/* Create table code for one case selector */
+void g_falsejump (unsigned flags attribute ((unused)), unsigned label)
+/* Jump to label if zero flag set */
 {
-    switch (flags & CF_TYPE) {
-
-       case CF_CHAR:
-       case CF_INT:
-           AddCodeLine ("\t.word\t$%04X, L%04X", val & 0xFFFF, label & 0xFFFF);
-                   break;
-
-       case CF_LONG:
-           AddCodeLine ("\t.dword\t$%08X", val);
-           AddCodeLine ("\t.word\tL%04X", label & 0xFFFF);
-           break;
-
-       default:
-           typeerror (flags);
-
-    }
+    AddCodeLine ("jeq %s", LocalLabelName (label));
 }
 
 
+void g_lateadjustSP (unsigned label)
+/* Adjust stack based on non-immediate data */
+{
+    AddCodeLine ("pha");
+    AddCodeLine ("lda %s", LocalLabelName (label));
+    AddCodeLine ("clc");
+    AddCodeLine ("adc sp");
+    AddCodeLine ("sta sp");
+    AddCodeLine ("lda %s+1", LocalLabelName (label));
+    AddCodeLine ("adc sp+1");
+    AddCodeLine ("sta sp+1");
+    AddCodeLine ("pla");
+}
 
-void g_truejump (unsigned flags, unsigned label)
-/* Jump to label if zero flag clear */
+void g_drop (unsigned Space)
+/* Drop space allocated on the stack */
 {
-    if (flags & CF_SHORT) {
-       AddCodeLine ("\tbne\tL%04X", label);
-    } else {
-        AddCodeLine ("\tjne\tL%04X", label);
+    if (Space > 255) {
+        /* Inline the code since calling addysp repeatedly is quite some
+        ** overhead.
+        */
+        AddCodeLine ("pha");
+        AddCodeLine ("lda #$%02X", (unsigned char) Space);
+        AddCodeLine ("clc");
+        AddCodeLine ("adc sp");
+        AddCodeLine ("sta sp");
+        AddCodeLine ("lda #$%02X", (unsigned char) (Space >> 8));
+        AddCodeLine ("adc sp+1");
+        AddCodeLine ("sta sp+1");
+        AddCodeLine ("pla");
+    } else if (Space > 8) {
+        AddCodeLine ("ldy #$%02X", Space);
+        AddCodeLine ("jsr addysp");
+    } else if (Space != 0) {
+        AddCodeLine ("jsr incsp%u", Space);
     }
 }
 
 
 
-void g_falsejump (unsigned flags, unsigned label)
-/* Jump to label if zero flag set */
+void g_space (int Space)
+/* Create or drop space on the stack */
 {
-    if (flags & CF_SHORT) {
-       AddCodeLine ("\tbeq\tL%04X", label);
-    } else {
-               AddCodeLine ("\tjeq\tL%04X", label);
+    if (Space < 0) {
+        /* This is actually a drop operation */
+        g_drop (-Space);
+    } else if (Space > 255) {
+        /* Inline the code since calling subysp repeatedly is quite some
+        ** overhead.
+        */
+        AddCodeLine ("pha");
+        AddCodeLine ("lda sp");
+        AddCodeLine ("sec");
+        AddCodeLine ("sbc #$%02X", (unsigned char) Space);
+        AddCodeLine ("sta sp");
+        AddCodeLine ("lda sp+1");
+        AddCodeLine ("sbc #$%02X", (unsigned char) (Space >> 8));
+        AddCodeLine ("sta sp+1");
+        AddCodeLine ("pla");
+    } else if (Space > 8) {
+        AddCodeLine ("ldy #$%02X", Space);
+        AddCodeLine ("jsr subysp");
+    } else if (Space != 0) {
+        AddCodeLine ("jsr decsp%u", Space);
     }
 }
 
 
 
-static void mod_internal (int k, char* verb1, char* verb2)
+void g_cstackcheck (void)
+/* Check for a C stack overflow */
 {
-    if (k <= 8) {
-       AddCodeLine ("\tjsr\t%ssp%c", verb1, k + '0');
-    } else {
-       CheckLocalOffs (k);
-       ldyconst (k);
-       AddCodeLine ("\tjsr\t%ssp", verb2);
-    }
+    AddCodeLine ("jsr cstkchk");
 }
 
 
 
-void g_space (int space)
-/* Create or drop space on the stack */
+void g_stackcheck (void)
+/* Check for a stack overflow */
 {
-    if (space < 0) {
-       mod_internal (-space, "inc", "addy");
-    } else if (space > 0) {
-       mod_internal (space, "dec", "suby");
-    }
+    AddCodeLine ("jsr stkchk");
 }
 
 
@@ -2433,16 +2513,13 @@ void g_space (int space)
 void g_add (unsigned flags, unsigned long val)
 /* Primary = TOS + Primary */
 {
-    static char* ops [12] = {
-       0,              "tosadda0",     "tosaddax",
-       0,              "tosadda0",     "tosaddax",
-       0,              0,              "tosaddeax",
-       0,              0,              "tosaddeax",
+    static const char* const ops[4] = {
+        "tosaddax", "tosaddax", "tosaddeax", "tosaddeax"
     };
 
     if (flags & CF_CONST) {
-       flags &= ~CF_FORCECHAR; // Handle chars as ints
-       g_push (flags & ~CF_CONST, 0);
+        flags &= ~CF_FORCECHAR; /* Handle chars as ints */
+        g_push (flags & ~CF_CONST, 0);
     }
     oper (flags, val, ops);
 }
@@ -2452,16 +2529,13 @@ void g_add (unsigned flags, unsigned long val)
 void g_sub (unsigned flags, unsigned long val)
 /* Primary = TOS - Primary */
 {
-    static char* ops [12] = {
-       0,              "tossuba0",     "tossubax",
-       0,              "tossuba0",     "tossubax",
-       0,              0,              "tossubeax",
-       0,              0,              "tossubeax",
+    static const char* const ops[4] = {
+        "tossubax", "tossubax", "tossubeax", "tossubeax"
     };
 
     if (flags & CF_CONST) {
-       flags &= ~CF_FORCECHAR; // Handle chars as ints
-       g_push (flags & ~CF_CONST, 0);
+        flags &= ~CF_FORCECHAR; /* Handle chars as ints */
+        g_push (flags & ~CF_CONST, 0);
     }
     oper (flags, val, ops);
 }
@@ -2471,11 +2545,8 @@ void g_sub (unsigned flags, unsigned long val)
 void g_rsub (unsigned flags, unsigned long val)
 /* Primary = Primary - TOS */
 {
-    static char* ops [12] = {
-       0,              "tosrsuba0",    "tosrsubax",
-       0,              "tosrsuba0",    "tosrsubax",
-       0,              0,              "tosrsubeax",
-       0,              0,              "tosrsubeax",
+    static const char* const ops[4] = {
+        "tosrsubax", "tosrsubax", "tosrsubeax", "tosrsubeax"
     };
     oper (flags, val, ops);
 }
@@ -2485,76 +2556,101 @@ void g_rsub (unsigned flags, unsigned long val)
 void g_mul (unsigned flags, unsigned long val)
 /* Primary = TOS * Primary */
 {
-    static char* ops [12] = {
-       0,              "tosmula0",     "tosmulax",
-       0,              "tosumula0",    "tosumulax",
-       0,              0,              "tosmuleax",
-       0,              0,              "tosumuleax",
+    static const char* const ops[4] = {
+        "tosmulax", "tosumulax", "tosmuleax", "tosumuleax"
     };
 
     int p2;
 
     /* Do strength reduction if the value is constant and a power of two */
-    if (flags & CF_CONST && (p2 = powerof2 (val)) >= 0) {
-       /* Generate a shift instead */
-       g_asl (flags, p2);
-       return;
+    if (flags & CF_CONST && (p2 = PowerOf2 (val)) >= 0) {
+        /* Generate a shift instead */
+        g_asl (flags, p2);
+        return;
     }
 
     /* If the right hand side is const, the lhs is not on stack but still
-     * in the primary register.
-     */
+    ** in the primary register.
+    */
     if (flags & CF_CONST) {
 
-       switch (flags & CF_TYPE) {
-
-           case CF_CHAR:
-               if (flags & CF_FORCECHAR) {
-                   /* Handle some special cases */
-                   switch (val) {
-
-                       case 3:
-                           AddCodeLine ("\tsta\ttmp1");
-                           AddCodeLine ("\tasl\ta");
-                           AddCodeLine ("\tclc");
-                           AddCodeLine ("\tadc\ttmp1");
-                           return;
-
-                       case 5:
-                           AddCodeLine ("\tsta\ttmp1");
-                           AddCodeLine ("\tasl\ta");
-                           AddCodeLine ("\tasl\ta");
-                           AddCodeLine ("\tclc");
-                           AddCodeLine ("\tadc\ttmp1");
-                           return;
-
-                       case 10:
-                           AddCodeLine ("\tsta\ttmp1");
-                           AddCodeLine ("\tasl\ta");
-                           AddCodeLine ("\tasl\ta");
-                           AddCodeLine ("\tclc");
-                           AddCodeLine ("\tadc\ttmp1");
-                           AddCodeLine ("\tasl\ta");
-                           return;
-                   }
-               }
-               /* FALLTHROUGH */
-
-           case CF_INT:
-               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);
+        switch (flags & CF_TYPEMASK) {
+
+            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 6:
+                            AddCodeLine ("sta tmp1");
+                            AddCodeLine ("asl a");
+                            AddCodeLine ("clc");
+                            AddCodeLine ("adc tmp1");
+                            AddCodeLine ("asl a");
+                            return;
+
+                        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);
 
     }
 
@@ -2567,26 +2663,23 @@ void g_mul (unsigned flags, unsigned long val)
 void g_div (unsigned flags, unsigned long val)
 /* Primary = TOS / Primary */
 {
-    static char* ops [12] = {
-       0,              "tosdiva0",     "tosdivax",
-       0,              "tosudiva0",    "tosudivax",
-       0,              0,              "tosdiveax",
-       0,              0,              "tosudiveax",
+    static const char* const ops[4] = {
+        "tosdivax", "tosudivax", "tosdiveax", "tosudiveax"
     };
 
     /* Do strength reduction if the value is constant and a power of two */
     int p2;
-    if ((flags & CF_CONST) && (p2 = powerof2 (val)) >= 0) {
-       /* Generate a shift instead */
-       g_asr (flags, p2);
+    if ((flags & CF_CONST) && (p2 = PowerOf2 (val)) >= 0) {
+        /* Generate a shift instead */
+        g_asr (flags, p2);
     } else {
-       /* Generate a division */
-       if (flags & CF_CONST) {
-           /* lhs is not on stack */
-           flags &= ~CF_FORCECHAR;     // Handle chars as ints
-           g_push (flags & ~CF_CONST, 0);
-       }
-       oper (flags, val, ops);
+        /* Generate a division */
+        if (flags & CF_CONST) {
+            /* lhs is not on stack */
+            flags &= ~CF_FORCECHAR;     /* Handle chars as ints */
+            g_push (flags & ~CF_CONST, 0);
+        }
+        oper (flags, val, ops);
     }
 }
 
@@ -2595,26 +2688,23 @@ void g_div (unsigned flags, unsigned long val)
 void g_mod (unsigned flags, unsigned long val)
 /* Primary = TOS % Primary */
 {
-    static char* ops [12] = {
-       0,              "tosmoda0",     "tosmodax",
-       0,              "tosumoda0",    "tosumodax",
-       0,              0,              "tosmodeax",
-       0,              0,              "tosumodeax",
+    static const char* const ops[4] = {
+        "tosmodax", "tosumodax", "tosmodeax", "tosumodeax"
     };
     int p2;
 
     /* Check if we can do some cost reduction */
-    if ((flags & CF_CONST) && (flags & CF_UNSIGNED) && val != 0xFFFFFFFF && (p2 = powerof2 (val)) >= 0) {
-       /* We can do that with an AND operation */
-       g_and (flags, val - 1);
+    if ((flags & CF_CONST) && (flags & CF_UNSIGNED) && val != 0xFFFFFFFF && (p2 = PowerOf2 (val)) >= 0) {
+        /* We can do that with an AND operation */
+        g_and (flags, val - 1);
     } else {
-       /* Do it the hard way... */
-       if (flags & CF_CONST) {
-           /* lhs is not on stack */
-           flags &= ~CF_FORCECHAR;     // Handle chars as ints
-           g_push (flags & ~CF_CONST, 0);
-       }
-       oper (flags, val, ops);
+        /* Do it the hard way... */
+        if (flags & CF_CONST) {
+            /* lhs is not on stack */
+            flags &= ~CF_FORCECHAR;     /* Handle chars as ints */
+            g_push (flags & ~CF_CONST, 0);
+        }
+        oper (flags, val, ops);
     }
 }
 
@@ -2623,52 +2713,65 @@ void g_mod (unsigned flags, unsigned long val)
 void g_or (unsigned flags, unsigned long val)
 /* Primary = TOS | Primary */
 {
-    static char* ops [12] = {
-       0,              "tosora0",      "tosorax",
-       0,              "tosora0",      "tosorax",
-       0,              0,              "tosoreax",
-       0,              0,              "tosoreax",
+    static const char* const ops[4] = {
+        "tosorax", "tosorax", "tosoreax", "tosoreax"
     };
 
     /* If the right hand side is const, the lhs is not on stack but still
-     * in the primary register.
-     */
+    ** in the primary register.
+    */
     if (flags & CF_CONST) {
 
-       switch (flags & CF_TYPE) {
-
-           case CF_CHAR:
-               if (flags & CF_FORCECHAR) {
-                   if ((val & 0xFF) != 0xFF) {
-                               AddCodeLine ("\tora\t#$%02X", val & 0xFF);
-                   }
-                   return;
-               }
-               /* FALLTHROUGH */
-
-           case CF_INT:
-               if (val <= 0xFF) {
-                   AddCodeLine ("\tora\t#$%02X", val & 0xFF);
-                   return;
-               }
-               break;
-
-           case CF_LONG:
-               if (val <= 0xFF) {
-                   AddCodeLine ("\tora\t#$%02X", val & 0xFF);
-                   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);
-
+        switch (flags & CF_TYPEMASK) {
+
+            case CF_CHAR:
+                if (flags & CF_FORCECHAR) {
+                    if ((val & 0xFF) != 0) {
+                        AddCodeLine ("ora #$%02X", (unsigned char)val);
+                    }
+                    return;
+                }
+                /* FALLTHROUGH */
+
+            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);
+                    }
+                    AddCodeLine ("ldx #$FF");
+                } 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;
+
+            case CF_LONG:
+                if (val <= 0xFF) {
+                    if ((val & 0xFF) != 0) {
+                        AddCodeLine ("ora #$%02X", (unsigned char)val);
+                    }
+                    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. Note: The standard stuff will
+        ** always work with ints.
+        */
+        flags &= ~CF_FORCECHAR;
+        g_push (flags & ~CF_CONST, 0);
     }
 
     /* Use long way over the stack */
@@ -2680,64 +2783,63 @@ void g_or (unsigned flags, unsigned long val)
 void g_xor (unsigned flags, unsigned long val)
 /* Primary = TOS ^ Primary */
 {
-    static char* ops [12] = {
-       0,              "tosxora0",     "tosxorax",
-       0,              "tosxora0",     "tosxorax",
-       0,              0,              "tosxoreax",
-       0,              0,              "tosxoreax",
+    static const char* const ops[4] = {
+        "tosxorax", "tosxorax", "tosxoreax", "tosxoreax"
     };
 
 
     /* If the right hand side is const, the lhs is not on stack but still
-     * in the primary register.
-     */
+    ** in the primary register.
+    */
     if (flags & CF_CONST) {
 
-       switch (flags & CF_TYPE) {
-
-           case CF_CHAR:
-               if (flags & CF_FORCECHAR) {
-                   if ((val & 0xFF) != 0) {
-                               AddCodeLine ("\teor\t#$%02X", val & 0xFF);
-                   }
-                   return;
-               }
-               /* FALLTHROUGH */
-
-           case CF_INT:
-               if (val <= 0xFF) {
-                   if (val != 0) {
-                       AddCodeLine ("\teor\t#$%02X", val);
-                   }
-                   return;
-               } else if ((val & 0xFF) == 0) {
-                   AddCodeLine ("\tpha");
-                   AddCodeLine ("\ttxa");
-                   AddCodeLine ("\teor\t#$%02X", (val >> 8) & 0xFF);
-                   AddCodeLine ("\ttax");
-                   AddCodeLine ("\tpla");
-                   return;
-               }
-               break;
-
-           case CF_LONG:
-               if (val <= 0xFF) {
-                   if (val != 0) {
-                               AddCodeLine ("\teor\t#$%02X", val & 0xFF);
-                   }
-                   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);
-
+        switch (flags & CF_TYPEMASK) {
+
+            case CF_CHAR:
+                if (flags & CF_FORCECHAR) {
+                    if ((val & 0xFF) != 0) {
+                        AddCodeLine ("eor #$%02X", (unsigned char)val);
+                    }
+                    return;
+                }
+                /* FALLTHROUGH */
+
+            case CF_INT:
+                if (val <= 0xFF) {
+                    if (val != 0) {
+                        AddCodeLine ("eor #$%02X", (unsigned char)val);
+                    }
+                } 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;
+
+            case CF_LONG:
+                if (val <= 0xFF) {
+                    if (val != 0) {
+                        AddCodeLine ("eor #$%02X", (unsigned char)val);
+                    }
+                    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. Note: The standard stuff will
+        ** always work with ints.
+        */
+        flags &= ~CF_FORCECHAR;
+        g_push (flags & ~CF_CONST, 0);
     }
 
     /* Use long way over the stack */
@@ -2746,88 +2848,94 @@ 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",
+    static const char* const ops[4] = {
+        "tosandax", "tosandax", "tosandeax", "tosandeax"
     };
 
     /* If the right hand side is const, the lhs is not on stack but still
-     * in the primary register.
-     */
-    if (flags & CF_CONST) {
-
-       switch (flags & CF_TYPE) {
-
-           case CF_CHAR:
-               if (flags & CF_FORCECHAR) {
-                   AddCodeLine ("\tand\t#$%02X", val & 0xFF);
-                   return;
-               }
-               /* FALLTHROUGH */
-           case CF_INT:
-               if ((val & 0xFFFF) != 0xFFFF) {
-                           if (val <= 0xFF) {
-                       ldxconst (0);
-                       if (val == 0) {
-                           ldaconst (0);
-                       } else if (val != 0xFF) {
-                           AddCodeLine ("\tand\t#$%02X", val & 0xFF);
-                       }
-                   } else if ((val & 0xFF00) == 0xFF00) {
-                       AddCodeLine ("\tand\t#$%02X", val & 0xFF);
-                   } else if ((val & 0x00FF) == 0x0000) {
-                       AddCodeLine ("\ttxa");
-                       AddCodeLine ("\tand\t#$%02X", (val >> 8) & 0xFF);
-                       AddCodeLine ("\ttax");
-                       ldaconst (0);
-                   } else {
-                       AddCodeLine ("\ttay");
-                       AddCodeLine ("\ttxa");
-                       AddCodeLine ("\tand\t#$%02X", (val >> 8) & 0xFF);
-                       AddCodeLine ("\ttax");
-                       AddCodeLine ("\ttya");
-                       if ((val & 0x00FF) != 0x00FF) {
-                           AddCodeLine ("\tand\t#$%02X", val & 0xFF);
-                       }
-                   }
-               }
-               return;
-
-           case CF_LONG:
-               if (val <= 0xFF) {
-                   ldxconst (0);
-                   AddCodeLine ("\tstx\tsreg+1");
-                   AddCodeLine ("\tstx\tsreg");
-                   if ((val & 0xFF) != 0xFF) {
-                        AddCodeLine ("\tand\t#$%02X", val & 0xFF);
-                   }
-                   return;
-               } else if (val == 0xFF00) {
-                   ldaconst (0);
-                   AddCodeLine ("\tsta\tsreg+1");
-                   AddCodeLine ("\tsta\tsreg");
-                   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);
-
+    ** in the primary register.
+    */
+    if (Flags & CF_CONST) {
+
+        switch (Flags & CF_TYPEMASK) {
+
+            case CF_CHAR:
+                if (Flags & CF_FORCECHAR) {
+                    if ((Val & 0xFF) == 0x00) {
+                        AddCodeLine ("lda #$00");
+                    } else if ((Val & 0xFF) != 0xFF) {
+                        AddCodeLine ("and #$%02X", (unsigned char)Val);
+                    }
+                    return;
+                }
+                /* FALLTHROUGH */
+            case CF_INT:
+                if ((Val & 0xFFFF) != 0xFFFF) {
+                    if (Val <= 0xFF) {
+                        AddCodeLine ("ldx #$00");
+                        if (Val == 0) {
+                            AddCodeLine ("lda #$00");
+                        } else if (Val != 0xFF) {
+                            AddCodeLine ("and #$%02X", (unsigned char)Val);
+                        }
+                    } else if ((Val & 0xFFFF) == 0xFF00) {
+                        AddCodeLine ("lda #$00");
+                    } 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");
+                        AddCodeLine ("lda #$00");
+                    } else {
+                        AddCodeLine ("tay");
+                        AddCodeLine ("txa");
+                        AddCodeLine ("and #$%02X", (unsigned char)(Val >> 8));
+                        AddCodeLine ("tax");
+                        AddCodeLine ("tya");
+                        if ((Val & 0x00FF) == 0x0000) {
+                            AddCodeLine ("lda #$00");
+                        } else if ((Val & 0x00FF) != 0x00FF) {
+                            AddCodeLine ("and #$%02X", (unsigned char)Val);
+                        }
+                    }
+                }
+                return;
+
+            case CF_LONG:
+                if (Val <= 0xFF) {
+                    AddCodeLine ("ldx #$00");
+                    AddCodeLine ("stx sreg+1");
+                    AddCodeLine ("stx sreg");
+                    if ((Val & 0xFF) != 0xFF) {
+                         AddCodeLine ("and #$%02X", (unsigned char)Val);
+                    }
+                    return;
+                } else if (Val == 0xFF00) {
+                    AddCodeLine ("lda #$00");
+                    AddCodeLine ("sta sreg+1");
+                    AddCodeLine ("sta sreg");
+                    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. 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);
 }
 
 
@@ -2835,76 +2943,126 @@ void g_and (unsigned flags, unsigned long val)
 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",
+    static const char* const ops[4] = {
+        "tosasrax", "tosshrax", "tosasreax", "tosshreax"
     };
 
     /* If the right hand side is const, the lhs is not on stack but still
-     * in the primary register.
-     */
+    ** in the primary register.
+    */
     if (flags & CF_CONST) {
 
-       switch (flags & CF_TYPE) {
-
-           case CF_CHAR:
-           case CF_INT:
-               if (val >= 1 && val <= 3) {
-                   if (flags & CF_UNSIGNED) {
-                       AddCodeLine ("\tjsr\tshrax%ld", val);
-                   } else {
-                       AddCodeLine ("\tjsr\tasrax%ld", val);
-                   }
-                   return;
-               } else if (val == 8 && (flags & CF_UNSIGNED)) {
-                   AddCodeLine ("\ttxa");
-                   ldxconst (0);
-                   return;
-               }
-               break;
-
-           case CF_LONG:
-               if (val >= 1 && val <= 3) {
-                   if (flags & CF_UNSIGNED) {
-                       AddCodeLine ("\tjsr\tshreax%ld", val);
-                   } else {
-                       AddCodeLine ("\tjsr\tasreax%ld", val);
-                   }
-                   return;
-               } else if (val == 8 && (flags & CF_UNSIGNED)) {
-                   AddCodeLine ("\ttxa");
-                   AddCodeLine ("\tldx\tsreg");
-                   AddCodeLine ("\tldy\tsreg+1");
-                   AddCodeLine ("\tsty\tsreg");
-                   AddCodeLine ("\tldy\t#$00");
-                   AddCodeLine ("\tsty\tsreg+1");
-                   return;
-               } else if (val == 16) {
-                   AddCodeLine ("\tldy\t#$00");
-                   AddCodeLine ("\tldx\tsreg+1");
-                   if ((flags & CF_UNSIGNED) == 0) {
-                       AddCodeLine ("\tbpl\t*+3");
-                       AddCodeLine ("\tdey");
-                       AddCodeHint ("y:!");
-                   }
-                   AddCodeLine ("\tlda\tsreg");
-                   AddCodeLine ("\tsty\tsreg+1");
-                   AddCodeLine ("\tsty\tsreg");
-                   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);
-
+        switch (flags & CF_TYPEMASK) {
+
+            case CF_CHAR:
+            case CF_INT:
+                val &= 0x0F;
+                if (val >= 8) {
+                    if (flags & CF_UNSIGNED) {
+                        AddCodeLine ("txa");
+                        AddCodeLine ("ldx #$00");
+                    } else {
+                        unsigned L = GetLocalLabel();
+                        AddCodeLine ("cpx #$80");   /* Sign bit into carry */
+                        AddCodeLine ("txa");
+                        AddCodeLine ("ldx #$00");
+                        AddCodeLine ("bcc %s", LocalLabelName (L));
+                        AddCodeLine ("dex");        /* Make $FF */
+                        g_defcodelabel (L);
+                    }
+                    val -= 8;
+                }
+                if (val >= 4) {
+                    if (flags & CF_UNSIGNED) {
+                        AddCodeLine ("jsr shrax4");
+                    } else {
+                        AddCodeLine ("jsr asrax4");
+                    }
+                    val -= 4;
+                }
+                if (val > 0) {
+                    if (flags & CF_UNSIGNED) {
+                        AddCodeLine ("jsr shrax%ld", val);
+                    } else {
+                        AddCodeLine ("jsr asrax%ld", val);
+                    }
+                }
+                return;
+
+            case CF_LONG:
+                val &= 0x1F;
+                if (val >= 24) {
+                    AddCodeLine ("ldx #$00");
+                    AddCodeLine ("lda sreg+1");
+                    if ((flags & CF_UNSIGNED) == 0) {
+                        unsigned L = GetLocalLabel();
+                        AddCodeLine ("bpl %s", LocalLabelName (L));
+                        AddCodeLine ("dex");
+                        g_defcodelabel (L);
+                    }
+                    AddCodeLine ("stx sreg");
+                    AddCodeLine ("stx sreg+1");
+                    val -= 24;
+                }
+                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 ("lda sreg");
+                    AddCodeLine ("sty sreg+1");
+                    AddCodeLine ("sty sreg");
+                    val -= 16;
+                }
+                if (val >= 8) {
+                    AddCodeLine ("txa");
+                    AddCodeLine ("ldx sreg");
+                    AddCodeLine ("ldy sreg+1");
+                    AddCodeLine ("sty sreg");
+                    if ((flags & CF_UNSIGNED) == 0) {
+                        unsigned L = GetLocalLabel();
+                        AddCodeLine ("cpy #$80");
+                        AddCodeLine ("ldy #$00");
+                        AddCodeLine ("bcc %s", LocalLabelName (L));
+                        AddCodeLine ("dey");
+                        g_defcodelabel (L);
+                    } else {
+                        AddCodeLine ("ldy #$00");
+                    }
+                    AddCodeLine ("sty sreg+1");
+                    val -= 8;
+                }
+                if (val >= 4) {
+                    if (flags & CF_UNSIGNED) {
+                        AddCodeLine ("jsr shreax4");
+                    } else {
+                        AddCodeLine ("jsr asreax4");
+                    }
+                    val -= 4;
+                }
+                if (val > 0) {
+                    if (flags & CF_UNSIGNED) {
+                        AddCodeLine ("jsr shreax%ld", val);
+                    } else {
+                        AddCodeLine ("jsr asreax%ld", val);
+                    }
+                }
+                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 */
@@ -2916,70 +3074,94 @@ void g_asr (unsigned flags, unsigned long val)
 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",
+    static const char* const ops[4] = {
+        "tosaslax", "tosshlax", "tosasleax", "tosshleax"
     };
 
 
     /* If the right hand side is const, the lhs is not on stack but still
-     * in the primary register.
-     */
+    ** in the primary register.
+    */
     if (flags & CF_CONST) {
 
-       switch (flags & CF_TYPE) {
-
-           case CF_CHAR:
-           case CF_INT:
-               if (val >= 1 && val <= 3) {
-                   if (flags & CF_UNSIGNED) {
-                       AddCodeLine ("\tjsr\tshlax%ld", val);
-                   } else {
-                       AddCodeLine ("\tjsr\taslax%ld", val);
-                   }
-                   return;
-               } else if (val == 8) {
-                   AddCodeLine ("\ttax");
-                   AddCodeLine ("\tlda\t#$00");
-                   return;
-               }
-               break;
-
-           case CF_LONG:
-               if (val >= 1 && val <= 3) {
-                   if (flags & CF_UNSIGNED) {
-                       AddCodeLine ("\tjsr\tshleax%ld", val);
-                   } else {
-                       AddCodeLine ("\tjsr\tasleax%ld", val);
-                   }
-                   return;
-               } else if (val == 8) {
-                   AddCodeLine ("\tldy\tsreg");
-                   AddCodeLine ("\tsty\tsreg+1");
-                   AddCodeLine ("\tstx\tsreg");
-                   AddCodeLine ("\ttax");
-                   AddCodeLine ("\tlda\t#$00");
-                   return;
-               } else if (val == 16) {
-                   AddCodeLine ("\tstx\tsreg+1");
-                   AddCodeLine ("\tsta\tsreg");
-                   AddCodeLine ("\tlda\t#$00");
-                   AddCodeLine ("\ttax");
-                   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);
-
+        switch (flags & CF_TYPEMASK) {
+
+            case CF_CHAR:
+            case CF_INT:
+                val &= 0x0F;
+                if (val >= 8) {
+                    AddCodeLine ("tax");
+                    AddCodeLine ("lda #$00");
+                    val -= 8;
+                }
+                if (val >= 4) {
+                    if (flags & CF_UNSIGNED) {
+                        AddCodeLine ("jsr shlax4");
+                    } else {
+                        AddCodeLine ("jsr aslax4");
+                    }
+                    val -= 4;
+                }
+                if (val > 0) {
+                    if (flags & CF_UNSIGNED) {
+                        AddCodeLine ("jsr shlax%ld", val);
+                    } else {
+                        AddCodeLine ("jsr aslax%ld", val);
+                    }
+                }
+                return;
+
+            case CF_LONG:
+                val &= 0x1F;
+                if (val >= 24) {
+                    AddCodeLine ("sta sreg+1");
+                    AddCodeLine ("lda #$00");
+                    AddCodeLine ("tax");
+                    AddCodeLine ("sta sreg");
+                    val -= 24;
+                }
+                if (val >= 16) {
+                    AddCodeLine ("stx sreg+1");
+                    AddCodeLine ("sta sreg");
+                    AddCodeLine ("lda #$00");
+                    AddCodeLine ("tax");
+                    val -= 16;
+                }
+                if (val >= 8) {
+                    AddCodeLine ("ldy sreg");
+                    AddCodeLine ("sty sreg+1");
+                    AddCodeLine ("stx sreg");
+                    AddCodeLine ("tax");
+                    AddCodeLine ("lda #$00");
+                    val -= 8;
+                }
+                if (val > 4) {
+                    if (flags & CF_UNSIGNED) {
+                        AddCodeLine ("jsr shleax4");
+                    } else {
+                        AddCodeLine ("jsr asleax4");
+                    }
+                    val -= 4;
+                }
+                if (val > 0) {
+                    if (flags & CF_UNSIGNED) {
+                        AddCodeLine ("jsr shleax%ld", val);
+                    } else {
+                        AddCodeLine ("jsr asleax%ld", val);
+                    }
+                }
+                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 */
@@ -2988,22 +3170,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_TYPEMASK) {
 
-       case CF_CHAR:
-       case CF_INT:
-           AddCodeLine ("\tjsr\tnegax");
-           break;
+        case CF_CHAR:
+            if (Flags & CF_FORCECHAR) {
+                AddCodeLine ("eor #$FF");
+                AddCodeLine ("clc");
+                AddCodeLine ("adc #$01");
+                return;
+            }
+            /* FALLTHROUGH */
 
-       case CF_LONG:
-           AddCodeLine ("\tjsr\tnegeax");
-           break;
+        case CF_INT:
+            AddCodeLine ("jsr negax");
+            break;
 
-       default:
-           typeerror (flags);
+        case CF_LONG:
+            AddCodeLine ("jsr negeax");
+            break;
+
+        default:
+            typeerror (Flags);
     }
 }
 
@@ -3012,43 +3202,49 @@ void g_neg (unsigned flags)
 void g_bneg (unsigned flags)
 /* Primary = !Primary */
 {
-    switch (flags & CF_TYPE) {
+    switch (flags & CF_TYPEMASK) {
 
-       case CF_CHAR:
-           AddCodeLine ("\tjsr\tbnega");
-           break;
+        case CF_CHAR:
+            AddCodeLine ("jsr bnega");
+            break;
 
-       case CF_INT:
-           AddCodeLine ("\tjsr\tbnegax");
-           break;
+        case CF_INT:
+            AddCodeLine ("jsr bnegax");
+            break;
 
-       case CF_LONG:
-           AddCodeLine ("\tjsr\tbnegeax");
-           break;
+        case CF_LONG:
+            AddCodeLine ("jsr bnegeax");
+            break;
 
-       default:
-           typeerror (flags);
+        default:
+            typeerror (flags);
     }
 }
 
 
 
-void g_com (unsigned flags)
+void g_com (unsigned Flags)
 /* Primary = ~Primary */
 {
-    switch (flags & CF_TYPE) {
+    switch (Flags & CF_TYPEMASK) {
 
-       case CF_CHAR:
-       case CF_INT:
-           AddCodeLine ("\tjsr\tcomplax");
-           break;
+        case CF_CHAR:
+            if (Flags & CF_FORCECHAR) {
+                AddCodeLine ("eor #$FF");
+                return;
+            }
+            /* FALLTHROUGH */
 
-       case CF_LONG:
-           AddCodeLine ("\tjsr\tcompleax");
-           break;
+        case CF_INT:
+            AddCodeLine ("jsr complax");
+            break;
 
-       default:
-           typeerror (flags);
+        case CF_LONG:
+            AddCodeLine ("jsr compleax");
+            break;
+
+        default:
+            typeerror (Flags);
     }
 }
 
@@ -3059,76 +3255,94 @@ void g_inc (unsigned flags, unsigned long val)
 {
     /* Don't inc by zero */
     if (val == 0) {
-       return;
+        return;
     }
 
     /* Generate code for the supported types */
     flags &= ~CF_CONST;
-    switch (flags & CF_TYPE) {
-
-       case CF_CHAR:
-           if (flags & CF_FORCECHAR) {
-               AddCodeLine ("\tclc");
-               AddCodeLine ("\tadc\t#$%02X", val & 0xFF);
-               break;
-           }
-           /* FALLTHROUGH */
-
-       case CF_INT:
-           if (FavourSize) {
-               /* Use jsr calls */
-               if (val <= 8) {
-                   AddCodeLine ("\tjsr\tincax%u", val);
-               } else if (val <= 255) {
-                   ldyconst (val);
-                   AddCodeLine ("\tjsr\tincaxy");
-               } else {
-                   g_add (flags | CF_CONST, val);
-               }
-           } else {
-               /* Inline the code */
-               if (val < 0x300) {
-                   if ((val & 0xFF) != 0) {
-                       AddCodeLine ("\tclc");
-                       AddCodeLine ("\tadc\t#$%02X", (unsigned char) val);
-                       AddCodeLine ("\tbcc\t*+3");
-                       AddCodeLine ("\tinx");
-                       /* Tell the optimizer that the X register may be invalid */
-                               AddCodeHint ("x:!");
-                   }
-                   if (val >= 0x100) {
-                       AddCodeLine ("\tinx");
-                   }
-                   if (val >= 0x200) {
-                       AddCodeLine ("\tinx");
-                   }
-               } else {
-                   AddCodeLine ("\tclc");
-                   if ((val & 0xFF) != 0) {
-                       AddCodeLine ("\tadc\t#$%02X", (unsigned char) val);
-                       /* Tell the optimizer that the X register may be invalid */
-                       AddCodeHint ("x:!");
-                   }
-                   AddCodeLine ("\tpha");
-                   AddCodeLine ("\ttxa");
-                   AddCodeLine ("\tadc\t#$%02X", (unsigned char) (val >> 8));
-                   AddCodeLine ("\ttax");
-                   AddCodeLine ("\tpla");
-               }
-           }
-           break;
-
-               case CF_LONG:
-           if (val <= 255) {
-               ldyconst (val);
-               AddCodeLine ("\tjsr\tinceaxy");
-           } else {
-               g_add (flags | CF_CONST, val);
-           }
-           break;
-
-       default:
-           typeerror (flags);
+    switch (flags & CF_TYPEMASK) {
+
+        case CF_CHAR:
+            if (flags & CF_FORCECHAR) {
+                if ((CPUIsets[CPU] & CPU_ISET_65SC02) != 0 && val <= 2) {
+                    while (val--) {
+                        AddCodeLine ("ina");
+                    }
+                } else {
+                    AddCodeLine ("clc");
+                    AddCodeLine ("adc #$%02X", (unsigned char)val);
+                }
+                break;
+            }
+            /* FALLTHROUGH */
+
+        case CF_INT:
+            if ((CPUIsets[CPU] & CPU_ISET_65SC02) != 0 && val == 1) {
+                unsigned L = GetLocalLabel();
+                AddCodeLine ("ina");
+                AddCodeLine ("bne %s", LocalLabelName (L));
+                AddCodeLine ("inx");
+                g_defcodelabel (L);
+            } else if (IS_Get (&CodeSizeFactor) < 200) {
+                /* Use jsr calls */
+                if (val <= 8) {
+                    AddCodeLine ("jsr incax%lu", val);
+                } else if (val <= 255) {
+                    AddCodeLine ("ldy #$%02X", (unsigned char) val);
+                    AddCodeLine ("jsr incaxy");
+                } else {
+                    g_add (flags | CF_CONST, val);
+                }
+            } else {
+                /* Inline the code */
+                if (val <= 0x300) {
+                    if ((val & 0xFF) != 0) {
+                        unsigned L = GetLocalLabel();
+                        AddCodeLine ("clc");
+                        AddCodeLine ("adc #$%02X", (unsigned char) val);
+                        AddCodeLine ("bcc %s", LocalLabelName (L));
+                        AddCodeLine ("inx");
+                        g_defcodelabel (L);
+                    }
+                    if (val >= 0x100) {
+                        AddCodeLine ("inx");
+                    }
+                    if (val >= 0x200) {
+                        AddCodeLine ("inx");
+                    }
+                    if (val >= 0x300) {
+                        AddCodeLine ("inx");
+                    }
+                } else if ((val & 0xFF) != 0) {
+                    AddCodeLine ("clc");
+                    AddCodeLine ("adc #$%02X", (unsigned char) val);
+                    AddCodeLine ("pha");
+                    AddCodeLine ("txa");
+                    AddCodeLine ("adc #$%02X", (unsigned char) (val >> 8));
+                    AddCodeLine ("tax");
+                    AddCodeLine ("pla");
+                } else {
+                    AddCodeLine ("pha");
+                    AddCodeLine ("txa");
+                    AddCodeLine ("clc");
+                    AddCodeLine ("adc #$%02X", (unsigned char) (val >> 8));
+                    AddCodeLine ("tax");
+                    AddCodeLine ("pla");
+                }
+            }
+            break;
+
+        case CF_LONG:
+            if (val <= 255) {
+                AddCodeLine ("ldy #$%02X", (unsigned char) val);
+                AddCodeLine ("jsr inceaxy");
+            } else {
+                g_add (flags | CF_CONST, val);
+            }
+            break;
+
+        default:
+            typeerror (flags);
 
     }
 }
@@ -3138,40 +3352,89 @@ void g_inc (unsigned flags, unsigned long val)
 void g_dec (unsigned flags, unsigned long val)
 /* Decrement the primary register by a given number */
 {
+    /* Don't dec by zero */
+    if (val == 0) {
+        return;
+    }
+
     /* Generate code for the supported types */
     flags &= ~CF_CONST;
-    switch (flags & CF_TYPE) {
+    switch (flags & CF_TYPEMASK) {
+
+        case CF_CHAR:
+            if (flags & CF_FORCECHAR) {
+                if ((CPUIsets[CPU] & CPU_ISET_65SC02) != 0 && val <= 2) {
+                    while (val--) {
+                        AddCodeLine ("dea");
+                    }
+                } else {
+                    AddCodeLine ("sec");
+                    AddCodeLine ("sbc #$%02X", (unsigned char)val);
+                }
+                break;
+            }
+            /* FALLTHROUGH */
+
+        case CF_INT:
+            if (IS_Get (&CodeSizeFactor) < 200) {
+                /* Use subroutines */
+                if (val <= 8) {
+                    AddCodeLine ("jsr decax%d", (int) val);
+                } else if (val <= 255) {
+                    AddCodeLine ("ldy #$%02X", (unsigned char) val);
+                    AddCodeLine ("jsr decaxy");
+                } else {
+                    g_sub (flags | CF_CONST, val);
+                }
+            } else {
+                /* Inline the code */
+                if (val < 0x300) {
+                    if ((val & 0xFF) != 0) {
+                        unsigned L = GetLocalLabel();
+                        AddCodeLine ("sec");
+                        AddCodeLine ("sbc #$%02X", (unsigned char) val);
+                        AddCodeLine ("bcs %s", LocalLabelName (L));
+                        AddCodeLine ("dex");
+                        g_defcodelabel (L);
+                    }
+                    if (val >= 0x100) {
+                        AddCodeLine ("dex");
+                    }
+                    if (val >= 0x200) {
+                        AddCodeLine ("dex");
+                    }
+                } else {
+                    if ((val & 0xFF) != 0) {
+                        AddCodeLine ("sec");
+                        AddCodeLine ("sbc #$%02X", (unsigned char) val);
+                        AddCodeLine ("pha");
+                        AddCodeLine ("txa");
+                        AddCodeLine ("sbc #$%02X", (unsigned char) (val >> 8));
+                        AddCodeLine ("tax");
+                        AddCodeLine ("pla");
+                    } else {
+                        AddCodeLine ("pha");
+                        AddCodeLine ("txa");
+                        AddCodeLine ("sec");
+                        AddCodeLine ("sbc #$%02X", (unsigned char) (val >> 8));
+                        AddCodeLine ("tax");
+                        AddCodeLine ("pla");
+                    }
+                }
+            }
+            break;
 
-       case CF_CHAR:
-           if (flags & CF_FORCECHAR) {
-               AddCodeLine ("\tsec");
-               AddCodeLine ("\tsbc\t#$%02X", val & 0xFF);
-               break;
-           }
-           /* FALLTHROUGH */
-
-       case CF_INT:
-           if (val <= 2) {
-               AddCodeLine ("\tjsr\tdecax%d", (int) val);
-           } else if (val <= 255) {
-               ldyconst (val);
-               AddCodeLine ("\tjsr\tdecaxy");
-           } else {
-               g_sub (flags | CF_CONST, val);
-           }
-           break;
-
-       case CF_LONG:
-           if (val <= 255) {
-               ldyconst (val);
-               AddCodeLine ("\tjsr\tdeceaxy");
-           } else {
-               g_sub (flags | CF_CONST, val);
-           }
-           break;
+        case CF_LONG:
+            if (val <= 255) {
+                AddCodeLine ("ldy #$%02X", (unsigned char) val);
+                AddCodeLine ("jsr deceaxy");
+            } else {
+                g_sub (flags | CF_CONST, val);
+            }
+            break;
 
-       default:
-           typeerror (flags);
+        default:
+            typeerror (flags);
 
     }
 }
@@ -3179,57 +3442,59 @@ void g_dec (unsigned flags, unsigned long val)
 
 
 /*
- * Following are the conditional operators. They compare the TOS against
- * the primary and put a literal 1 in the primary if the condition is
- * true, otherwise they clear the primary register
- */
+** Following are the conditional operators. They compare the TOS against
+** the primary and put a literal 1 in the primary if the condition is
+** true, otherwise they clear the primary register
+*/
 
 
 
 void g_eq (unsigned flags, unsigned long val)
 /* Test for equal */
 {
-    static char* ops [12] = {
-       "toseq00",      "toseqa0",      "toseqax",
-       "toseq00",      "toseqa0",      "toseqax",
-       0,              0,              "toseqeax",
-       0,              0,              "toseqeax",
+    static const char* const ops[4] = {
+        "toseqax", "toseqax", "toseqeax", "toseqeax"
     };
 
+    unsigned L;
+
     /* If the right hand side is const, the lhs is not on stack but still
-     * in the primary register.
-     */
+    ** in the primary register.
+    */
     if (flags & CF_CONST) {
 
-       switch (flags & CF_TYPE) {
-
-           case CF_CHAR:
-               if (flags & CF_FORCECHAR) {
-                   AddCodeLine ("\tcmp\t#$%02X", val & 0xFF);
-                   AddCodeLine ("\tjsr\tbooleq");
-                   return;
-               }
-               /* FALLTHROUGH */
-
-           case CF_INT:
-               AddCodeLine ("\tcpx\t#$%02X", (val >> 8) & 0xFF);
-                       AddCodeLine ("\tbne\t*+4");
-               AddCodeLine ("\tcmp\t#$%02X", val & 0xFF);
-               AddCodeLine ("\tjsr\tbooleq");
-               return;
-
-           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.
-        */
-       g_push (flags & ~CF_CONST, 0);
-
+        switch (flags & CF_TYPEMASK) {
+
+            case CF_CHAR:
+                if (flags & CF_FORCECHAR) {
+                    AddCodeLine ("cmp #$%02X", (unsigned char)val);
+                    AddCodeLine ("jsr booleq");
+                    return;
+                }
+                /* FALLTHROUGH */
+
+            case CF_INT:
+                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 booleq");
+                return;
+
+            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. Note: The standard stuff will
+        ** always work with ints.
+        */
+        flags &= ~CF_FORCECHAR;
+        g_push (flags & ~CF_CONST, 0);
     }
 
     /* Use long way over the stack */
@@ -3241,48 +3506,49 @@ void g_eq (unsigned flags, unsigned long val)
 void g_ne (unsigned flags, unsigned long val)
 /* Test for not equal */
 {
-    static char* ops [12] = {
-       "tosne00",      "tosnea0",      "tosneax",
-       "tosne00",      "tosnea0",      "tosneax",
-       0,              0,              "tosneeax",
-       0,              0,              "tosneeax",
+    static const char* const ops[4] = {
+        "tosneax", "tosneax", "tosneeax", "tosneeax"
     };
 
+    unsigned L;
 
     /* If the right hand side is const, the lhs is not on stack but still
-     * in the primary register.
-     */
+    ** in the primary register.
+    */
     if (flags & CF_CONST) {
 
-       switch (flags & CF_TYPE) {
-
-           case CF_CHAR:
-               if (flags & CF_FORCECHAR) {
-                   AddCodeLine ("\tcmp\t#$%02X", val & 0xFF);
-                   AddCodeLine ("\tjsr\tboolne");
-                   return;
-               }
-               /* FALLTHROUGH */
-
-           case CF_INT:
-               AddCodeLine ("\tcpx\t#$%02X", (val >> 8) & 0xFF);
-               AddCodeLine ("\tbne\t*+4");
-               AddCodeLine ("\tcmp\t#$%02X", val & 0xFF);
-               AddCodeLine ("\tjsr\tboolne");
-               return;
-
-           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.
-        */
-       g_push (flags & ~CF_CONST, 0);
-
+        switch (flags & CF_TYPEMASK) {
+
+            case CF_CHAR:
+                if (flags & CF_FORCECHAR) {
+                    AddCodeLine ("cmp #$%02X", (unsigned char)val);
+                    AddCodeLine ("jsr boolne");
+                    return;
+                }
+                /* FALLTHROUGH */
+
+            case CF_INT:
+                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 boolne");
+                return;
+
+            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. Note: The standard stuff will
+        ** always work with ints.
+        */
+        flags &= ~CF_FORCECHAR;
+        g_push (flags & ~CF_CONST, 0);
     }
 
     /* Use long way over the stack */
@@ -3294,69 +3560,157 @@ void g_ne (unsigned flags, unsigned long val)
 void g_lt (unsigned flags, unsigned long val)
 /* Test for less than */
 {
-    static char* ops [12] = {
-       "toslt00",      "toslta0",      "tosltax",
-       "tosult00",     "tosulta0",     "tosultax",
-       0,              0,              "toslteax",
-       0,              0,              "tosulteax",
+    static const char* const ops[4] = {
+        "tosltax", "tosultax", "toslteax", "tosulteax"
     };
 
+    unsigned Label;
+
     /* If the right hand side is const, the lhs is not on stack but still
-     * in the primary register.
-     */
+    ** in the primary register.
+    */
     if (flags & CF_CONST) {
 
-       /* Give a warning in some special cases */
-       if ((flags & CF_UNSIGNED) && val == 0) {
-           Warning (WARN_COND_NEVER_TRUE);
-       }
-
-       /* Look at the type */
-       switch (flags & CF_TYPE) {
-
-           case CF_CHAR:
-               if (flags & CF_FORCECHAR) {
-                   AddCodeLine ("\tcmp\t#$%02X", val & 0xFF);
-                   if (flags & CF_UNSIGNED) {
-                       AddCodeLine ("\tjsr\tboolult");
-                   } else {
-                       AddCodeLine ("\tjsr\tboollt");
-                   }
-                   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 ("\ttxa");
-                   AddCodeLine ("\tjsr\tboollt");
-                   return;
-               }
-               /* Direct code only for unsigned data types */
-               if (flags & CF_UNSIGNED) {
-                   AddCodeLine ("\tcpx\t#$%02X", (val >> 8) & 0xFF);
-                           AddCodeLine ("\tbne\t*+4");
-                   AddCodeLine ("\tcmp\t#$%02X", val & 0xFF);
-                   AddCodeLine ("\tjsr\tboolult");
-                   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.
-        */
-       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_TYPEMASK) {
+
+                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) {
+
+            /* A signed compare against zero must only look at the sign bit */
+            switch (flags & CF_TYPEMASK) {
+
+                case CF_CHAR:
+                    if (flags & CF_FORCECHAR) {
+                        AddCodeLine ("asl a");          /* Bit 7 -> carry */
+                        AddCodeLine ("lda #$00");
+                        AddCodeLine ("ldx #$00");
+                        AddCodeLine ("rol a");
+                        return;
+                    }
+                    /* FALLTHROUGH */
+
+                case CF_INT:
+                    /* Just check the high byte */
+                    AddCodeLine ("cpx #$80");           /* Bit 7 -> carry */
+                    AddCodeLine ("lda #$00");
+                    AddCodeLine ("ldx #$00");
+                    AddCodeLine ("rol a");
+                    return;
+
+                case CF_LONG:
+                    /* Just check the high byte */
+                    AddCodeLine ("lda sreg+1");
+                    AddCodeLine ("asl a");              /* Bit 7 -> carry */
+                    AddCodeLine ("lda #$00");
+                    AddCodeLine ("ldx #$00");
+                    AddCodeLine ("rol a");
+                    return;
+
+                default:
+                    typeerror (flags);
+            }
+
+        } else {
+
+            /* Signed compare against a constant != zero */
+            switch (flags & CF_TYPEMASK) {
+
+                case CF_CHAR:
+                    if (flags & CF_FORCECHAR) {
+                        Label = GetLocalLabel ();
+                        AddCodeLine ("sec");
+                        AddCodeLine ("sbc #$%02X", (unsigned char)val);
+                        AddCodeLine ("bvc %s", LocalLabelName (Label));
+                        AddCodeLine ("eor #$80");
+                        g_defcodelabel (Label);
+                        AddCodeLine ("asl a");          /* Bit 7 -> carry */
+                        AddCodeLine ("lda #$00");
+                        AddCodeLine ("ldx #$00");
+                        AddCodeLine ("rol a");
+                        return;
+                    }
+                    /* FALLTHROUGH */
+
+                case CF_INT:
+                    /* Do a subtraction */
+                    Label = GetLocalLabel ();
+                    AddCodeLine ("cmp #$%02X", (unsigned char)val);
+                    AddCodeLine ("txa");
+                    AddCodeLine ("sbc #$%02X", (unsigned char)(val >> 8));
+                    AddCodeLine ("bvc %s", LocalLabelName (Label));
+                    AddCodeLine ("eor #$80");
+                    g_defcodelabel (Label);
+                    AddCodeLine ("asl a");          /* Bit 7 -> carry */
+                    AddCodeLine ("lda #$00");
+                    AddCodeLine ("ldx #$00");
+                    AddCodeLine ("rol a");
+                    return;
+
+                case CF_LONG:
+                    /* This one is too costly */
+                    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. Note: The standard stuff will
+        ** always work with ints.
+        */
+        flags &= ~CF_FORCECHAR;
+        g_push (flags & ~CF_CONST, 0);
     }
 
     /* Use long way over the stack */
@@ -3368,56 +3722,110 @@ void g_lt (unsigned flags, unsigned long val)
 void g_le (unsigned flags, unsigned long val)
 /* Test for less than or equal to */
 {
-    static char* ops [12] = {
-       "tosle00",      "toslea0",      "tosleax",
-       "tosule00",     "tosulea0",     "tosuleax",
-       0,              0,              "tosleeax",
-       0,              0,              "tosuleeax",
+    static const char* const ops[4] = {
+        "tosleax", "tosuleax", "tosleeax", "tosuleeax"
     };
 
 
     /* If the right hand side is const, the lhs is not on stack but still
-     * in the primary register.
-     */
+    ** in the primary register.
+    */
     if (flags & CF_CONST) {
 
-       /* Look at the type */
-       switch (flags & CF_TYPE) {
-
-           case CF_CHAR:
-               if (flags & CF_FORCECHAR) {
-                   AddCodeLine ("\tcmp\t#$%02X", val & 0xFF);
-                   if (flags & CF_UNSIGNED) {
-                       AddCodeLine ("\tjsr\tboolule");
-                   } else {
-                       AddCodeLine ("\tjsr\tboolle");
-                   }
-                   return;
-               }
-               /* FALLTHROUGH */
-
-           case CF_INT:
-               if (flags & CF_UNSIGNED) {
-                   AddCodeLine ("\tcpx\t#$%02X", (val >> 8) & 0xFF);
-                           AddCodeLine ("\tbne\t*+4");
-                   AddCodeLine ("\tcmp\t#$%02X", val & 0xFF);
-                   AddCodeLine ("\tjsr\tboolule");
-                   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.
-        */
-       g_push (flags & ~CF_CONST, 0);
-
+        /* Look at the type */
+        switch (flags & CF_TYPEMASK) {
+
+            case CF_CHAR:
+                if (flags & CF_FORCECHAR) {
+                    if (flags & CF_UNSIGNED) {
+                        /* 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 {
+                            /* Always true */
+                            Warning ("Condition is always true");
+                            AddCodeLine ("jsr return1");
+                        }
+                    } else {
+                        /* 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 {
+                            /* Always true */
+                            Warning ("Condition is always true");
+                            AddCodeLine ("jsr return1");
+                        }
+                    }
+                    return;
+                }
+                /* FALLTHROUGH */
+
+            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;
+
+            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;
+
+            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 */
@@ -3429,74 +3837,126 @@ void g_le (unsigned flags, unsigned long val)
 void g_gt (unsigned flags, unsigned long val)
 /* Test for greater than */
 {
-    static char* ops [12] = {
-       "tosgt00",      "tosgta0",      "tosgtax",
-       "tosugt00",     "tosugta0",     "tosugtax",
-       0,              0,              "tosgteax",
-       0,              0,              "tosugteax",
+    static const char* const ops[4] = {
+        "tosgtax", "tosugtax", "tosgteax", "tosugteax"
     };
 
 
     /* If the right hand side is const, the lhs is not on stack but still
-     * in the primary register.
-     */
+    ** in the primary register.
+    */
     if (flags & CF_CONST) {
 
-       /* Look at the type */
-       switch (flags & CF_TYPE) {
-
-           case CF_CHAR:
-               if (flags & CF_FORCECHAR) {
-                   AddCodeLine ("\tcmp\t#$%02X", val & 0xFF);
-                   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 & 0xFF) {
-                           AddCodeLine ("\tjsr\tboolugt");
-                       } else {
-                           AddCodeLine ("\tjsr\tboolne");
-                       }
-                   } else {
-                       AddCodeLine ("\tjsr\tboolgt");
-                   }
-                   return;
-               }
-               /* FALLTHROUGH */
-
-           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 & 0xFFFF) == 0) {
-                       AddCodeLine ("\tstx\ttmp1");
-                       AddCodeLine ("\tora\ttmp1");
-                       AddCodeLine ("\tjsr\tboolne");
-                   } else {
-                               AddCodeLine ("\tcpx\t#$%02X", (val >> 8) & 0xFF);
-                       AddCodeLine ("\tbne\t*+4");
-                       AddCodeLine ("\tcmp\t#$%02X", val & 0xFF);
-                               AddCodeLine ("\tjsr\tboolugt");
-                   }
-                   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.
-        */
-       g_push (flags & ~CF_CONST, 0);
-
+        /* Look at the type */
+        switch (flags & CF_TYPEMASK) {
+
+            case CF_CHAR:
+                if (flags & CF_FORCECHAR) {
+                    if (flags & CF_UNSIGNED) {
+                        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 < 0xFF) {
+                            /* 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 {
+                        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;
+                }
+                /* FALLTHROUGH */
+
+            case CF_INT:
+                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 < 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;
+
+            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;
+
+            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 */
@@ -3508,61 +3968,153 @@ void g_gt (unsigned flags, unsigned long val)
 void g_ge (unsigned flags, unsigned long val)
 /* Test for greater than or equal to */
 {
-    static char* ops [12] = {
-       "tosge00",      "tosgea0",      "tosgeax",
-       "tosuge00",     "tosugea0",     "tosugeax",
-       0,              0,              "tosgeeax",
-       0,              0,              "tosugeeax",
+    static const char* const ops[4] = {
+        "tosgeax", "tosugeax", "tosgeeax", "tosugeeax"
     };
 
+    unsigned Label;
+
 
     /* If the right hand side is const, the lhs is not on stack but still
-     * in the primary register.
-     */
+    ** in the primary register.
+    */
     if (flags & CF_CONST) {
 
-       /* Give a warning in some special cases */
-       if ((flags & CF_UNSIGNED) && val == 0) {
-           Warning (WARN_COND_ALWAYS_TRUE);
-       }
-
-       /* Look at the type */
-       switch (flags & CF_TYPE) {
-
-           case CF_CHAR:
-               if (flags & CF_FORCECHAR) {
-                   AddCodeLine ("\tcmp\t#$%02X", val & 0xFF);
-                   if (flags & CF_UNSIGNED) {
-                       AddCodeLine ("\tjsr\tbooluge");
-                   } else {
-                       AddCodeLine ("\tjsr\tboolge");
-                   }
-                   return;
-               }
-               /* FALLTHROUGH */
-
-           case CF_INT:
-               if (flags & CF_UNSIGNED) {
-                           AddCodeLine ("\tcpx\t#$%02X", (val >> 8) & 0xFF);
-                           AddCodeLine ("\tbne\t*+4");
-                   AddCodeLine ("\tcmp\t#$%02X", val & 0xFF);
-                   AddCodeLine ("\tjsr\tbooluge");
-                   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.
-        */
-       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 always true");
+                AddCodeLine ("jsr return1");
+                return;
+            }
+
+            /* Look at the type */
+            switch (flags & CF_TYPEMASK) {
+
+                case CF_CHAR:
+                    if (flags & CF_FORCECHAR) {
+                        /* Do a subtraction. Condition is true if carry set */
+                        AddCodeLine ("cmp #$%02X", (unsigned char)val);
+                        AddCodeLine ("lda #$00");
+                        AddCodeLine ("ldx #$00");
+                        AddCodeLine ("rol a");
+                        return;
+                    }
+                    /* FALLTHROUGH */
+
+                case CF_INT:
+                    /* Do a subtraction. Condition is true if carry set */
+                    AddCodeLine ("cmp #$%02X", (unsigned char)val);
+                    AddCodeLine ("txa");
+                    AddCodeLine ("sbc #$%02X", (unsigned char)(val >> 8));
+                    AddCodeLine ("lda #$00");
+                    AddCodeLine ("ldx #$00");
+                    AddCodeLine ("rol a");
+                    return;
+
+                case CF_LONG:
+                    /* Do a subtraction. Condition is true if carry set */
+                    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 ("lda #$00");
+                    AddCodeLine ("ldx #$00");
+                    AddCodeLine ("rol a");
+                    return;
+
+                default:
+                    typeerror (flags);
+            }
+
+        } else if (val == 0) {
+
+            /* A signed compare against zero must only look at the sign bit */
+            switch (flags & CF_TYPEMASK) {
+
+                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);
+            }
+
+        } else {
+
+            /* Signed compare against a constant != zero */
+            switch (flags & CF_TYPEMASK) {
+
+                case CF_CHAR:
+                    if (flags & CF_FORCECHAR) {
+                        Label = GetLocalLabel ();
+                        AddCodeLine ("sec");
+                        AddCodeLine ("sbc #$%02X", (unsigned char)val);
+                        AddCodeLine ("bvs %s", LocalLabelName (Label));
+                        AddCodeLine ("eor #$80");
+                        g_defcodelabel (Label);
+                        AddCodeLine ("asl a");          /* Bit 7 -> carry */
+                        AddCodeLine ("lda #$00");
+                        AddCodeLine ("ldx #$00");
+                        AddCodeLine ("rol a");
+                        return;
+                    }
+                    /* FALLTHROUGH */
+
+                case CF_INT:
+                    /* Do a subtraction */
+                    Label = GetLocalLabel ();
+                    AddCodeLine ("cmp #$%02X", (unsigned char)val);
+                    AddCodeLine ("txa");
+                    AddCodeLine ("sbc #$%02X", (unsigned char)(val >> 8));
+                    AddCodeLine ("bvs %s", LocalLabelName (Label));
+                    AddCodeLine ("eor #$80");
+                    g_defcodelabel (Label);
+                    AddCodeLine ("asl a");          /* Bit 7 -> carry */
+                    AddCodeLine ("lda #$00");
+                    AddCodeLine ("ldx #$00");
+                    AddCodeLine ("rol a");
+                    return;
+
+                case CF_LONG:
+                    /* This one is too costly */
+                    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. Note: The standard stuff will
+        ** always work with ints.
+        */
+        flags &= ~CF_FORCECHAR;
+        g_push (flags & ~CF_CONST, 0);
     }
 
     /* Use long way over the stack */
@@ -3572,146 +4124,264 @@ void g_ge (unsigned flags, unsigned long val)
 
 
 /*****************************************************************************/
-/*                        Allocating static storage                         */
+/*                         Allocating static storage                         */
 /*****************************************************************************/
 
 
 
 void g_res (unsigned n)
-/* reserve static storage, n bytes */
+/* Reserve static storage, n bytes */
 {
-    AddCodeLine ("\t.res\t%u", n);
+    AddDataLine ("\t.res\t%u,$00", 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) {
 
-       /* Numeric constant */
-       switch (flags & CF_TYPE) {
+        /* Numeric constant */
+        switch (flags & CF_TYPEMASK) {
 
-           case CF_CHAR:
-               AddCodeLine ("\t.byte\t$%02lX", val & 0xFF);
-               break;
+            case CF_CHAR:
+                AddDataLine ("\t.byte\t$%02lX", val & 0xFF);
+                break;
 
-           case CF_INT:
-               AddCodeLine ("\t.word\t$%04lX", val & 0xFFFF);
-               break;
+            case CF_INT:
+                AddDataLine ("\t.word\t$%04lX", val & 0xFFFF);
+                break;
 
-           case CF_LONG:
-               AddCodeLine ("\t.dword\t$%08lX", val & 0xFFFFFFFF);
-               break;
+            case CF_LONG:
+                AddDataLine ("\t.dword\t$%08lX", val & 0xFFFFFFFF);
+                break;
 
-           default:
-               typeerror (flags);
-               break;
+            default:
+                typeerror (flags);
+                break;
 
-       }
+        }
 
     } else {
 
-       /* Create the correct label name */
-       const char* Label = GetLabelName (flags, val, offs);
+        /* Create the correct label name */
+        const char* Label = GetLabelName (flags, val, offs);
 
-       /* Labels are always 16 bit */
-       AddCodeLine ("\t.word\t%s", Label);
+        /* Labels are always 16 bit */
+        AddDataLine ("\t.addr\t%s", Label);
 
     }
 }
 
 
 
-void g_defbytes (const unsigned char* Bytes, unsigned Count)
-/* output a row of bytes as a constant */
+void g_defbytes (const void* Bytes, unsigned Count)
+/* Output a row of bytes as a constant */
 {
     unsigned Chunk;
     char Buf [128];
     char* B;
 
+    /* Cast the buffer pointer */
+    const unsigned char* Data = (const unsigned char*) Bytes;
+
     /* Output the stuff */
     while (Count) {
 
-       /* How many go into this line? */
-       if ((Chunk = Count) > 16) {
-           Chunk = 16;
-       }
-       Count -= Chunk;
+        /* How many go into this line? */
+        if ((Chunk = Count) > 16) {
+            Chunk = 16;
+        }
+        Count -= Chunk;
+
+        /* Output one line */
+        strcpy (Buf, "\t.byte\t");
+        B = Buf + 7;
+        do {
+            B += sprintf (B, "$%02X", *Data++);
+            if (--Chunk) {
+                *B++ = ',';
+            }
+        } while (Chunk);
+
+        /* Output the line */
+        AddDataLine ("%s", Buf);
+    }
+}
+
 
-       /* Output one line */
-       strcpy (Buf, "\t.byte\t");
-               B = Buf + 7;
-       do {
-           B += sprintf (B, "$%02X", *Bytes++ & 0xFF);
-           if (--Chunk) {
-               *B++ = ',';
-           }
-       } while (Chunk);
 
-       /* Output the line */
-       AddCodeLine (Buf);
+void g_zerobytes (unsigned Count)
+/* Output Count bytes of data initialized with zero */
+{
+    if (Count > 0) {
+        AddDataLine ("\t.res\t%u,$00", Count);
     }
 }
 
 
 
-void g_zerobytes (unsigned n)
-/* Output n bytes of data initialized with zero */
+void g_initregister (unsigned Label, unsigned Reg, unsigned Size)
+/* Initialize a register variable from static initialization data */
 {
-    AddCodeLine ("\t.res\t%u", n);
+    /* Register variables do always have less than 128 bytes */
+    unsigned CodeLabel = GetLocalLabel ();
+    AddCodeLine ("ldx #$%02X", (unsigned char) (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_initauto (unsigned Label, unsigned Size)
+/* Initialize a local variable at stack offset zero from static data */
+{
+    unsigned CodeLabel = GetLocalLabel ();
+
+    CheckLocalOffs (Size);
+    if (Size <= 128) {
+        AddCodeLine ("ldy #$%02X", 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) {
+        AddCodeLine ("ldy #$00");
+        g_defcodelabel (CodeLabel);
+        AddCodeLine ("lda %s,y", GetLabelName (CF_STATIC, Label, 0));
+        AddCodeLine ("sta (sp),y");
+        AddCodeLine ("iny");
+        AddCmpCodeIfSizeNot256 ("cpy #$%02X", 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 ();
+        AddCodeLine ("ldy #$%02X", 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 ();
+        AddCodeLine ("ldy #$00");
+        g_defcodelabel (CodeLabel);
+        AddCodeLine ("lda %s,y", GetLabelName (CF_STATIC, InitLabel, 0));
+        AddCodeLine ("sta %s,y", GetLabelName (CF_STATIC, VarLabel, 0));
+        AddCodeLine ("iny");
+        AddCmpCodeIfSizeNot256 ("cpy #$%02X", Size);
+        AddCodeLine ("bne %s", LocalLabelName (CodeLabel));
+    } else {
+        /* Use the easy way here: memcpy() */
+        g_getimmed (CF_STATIC, VarLabel, 0);
+        AddCodeLine ("jsr pushax");
+        g_getimmed (CF_STATIC, InitLabel, 0);
+        AddCodeLine ("jsr pushax");
+        g_getimmed (CF_INT | CF_UNSIGNED | CF_CONST, Size, 0);
+        AddCodeLine ("jsr %s", GetLabelName (CF_EXTERNAL, (uintptr_t) "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 = GetLabel ();
+    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 ("\tldy\t#$FF");
-       g_defloclabel (label);
-       AddCodeLine ("\tiny");
-       AddCodeLine ("\tlda\t%s,y", lbuf);
-       AddCodeLine ("\tbne\tL%04X", label);
-       AddCodeLine ("\ttya");
-       AddCodeLine ("\tldx\t#$00");
+        /* If we have a next label, define it */
+        if (NextLabel) {
+            g_defcodelabel (NextLabel);
+            NextLabel = 0;
+        }
 
-    } else {
+        /* Do the compare */
+        AddCodeLine (Compare, CN_GetValue (N));
+
+        /* 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));
 
-               /* Address not constant but in primary */
-       if (FavourSize) {
-           /* This is too much code, so call strlen instead of inlining */
-           AddCodeLine ("\tjsr\t_strlen");
-       } else {
-           /* Inline the function */
-           AddCodeLine ("\tsta\tptr1");
-           AddCodeLine ("\tstx\tptr1+1");
-           AddCodeLine ("\tldy\t#$FF");
-           g_defloclabel (label);
-           AddCodeLine ("\tiny");
-           AddCodeLine ("\tlda\t(ptr1),y");
-           AddCodeLine ("\tbne\tL%04X", label);
-           AddCodeLine ("\ttya");
-           AddCodeLine ("\tldx\t#$00");
-       }
+        } 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", (int) SB_GetLen (B), SB_GetConstBuf (B));
+}