]> git.sur5r.net Git - cc65/blobdiff - src/cc65/codegen.c
Fixed a bug
[cc65] / src / cc65 / codegen.c
index 54d04dfea97831ee392c24daece284e280abf722..6e05351d0d22d1d335214ae46b601f774f0fde6c 100644 (file)
@@ -6,7 +6,7 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 1998-2001 Ullrich von Bassewitz                                       */
+/* (C) 1998-2002 Ullrich von Bassewitz                                       */
 /*               Wacholderweg 14                                             */
 /*               D-70597 Stuttgart                                           */
 /* EMail:        uz@cc65.org                                                 */
@@ -96,45 +96,53 @@ static void CheckLocalOffs (unsigned Offs)
 
 
 
-static char* GetLabelName (unsigned flags, unsigned long label, long offs)
+static const char* GetLabelName (unsigned Flags, unsigned long Label, long Offs)
 {
-    static char lbuf [128];            /* Label name */
+    static char Buf [256];             /* Label name */
 
     /* Create the correct label name */
-    switch (flags & CF_ADDRMASK) {
+    switch (Flags & CF_ADDRMASK) {
 
        case CF_STATIC:
                    /* Static memory cell */
-           sprintf (lbuf, "%s%+ld", LocalLabelName (label), offs);
+           if (Offs) {
+               xsprintf (Buf, sizeof (Buf), "%s%+ld", LocalLabelName (Label), Offs);
+           } else {
+                       xsprintf (Buf, sizeof (Buf), "%s", LocalLabelName (Label));
+           }
            break;
 
        case CF_EXTERNAL:
            /* External label */
-           sprintf (lbuf, "_%s%+ld", (char*) label, offs);
+           if (Offs) {
+               xsprintf (Buf, sizeof (Buf), "_%s%+ld", (char*) Label, Offs);
+           } else {
+               xsprintf (Buf, sizeof (Buf), "_%s", (char*) Label);
+           }
            break;
 
        case CF_ABSOLUTE:
            /* Absolute address */
-           sprintf (lbuf, "$%04X", (unsigned)((label+offs) & 0xFFFF));
+           xsprintf (Buf, sizeof (Buf), "$%04X", (int)((Label+Offs) & 0xFFFF));
            break;
 
        case CF_REGVAR:
            /* Variable in register bank */
-           sprintf (lbuf, "regbank+%u", (unsigned)((label+offs) & 0xFFFF));
+           xsprintf (Buf, sizeof (Buf), "regbank+%u", (unsigned)((Label+Offs) & 0xFFFF));
            break;
 
        default:
            Internal ("Invalid address flags");
     }
-
+                   
     /* Return a pointer to the static buffer */
-    return lbuf;
+    return Buf;
 }
 
 
 
 /*****************************************************************************/
-/*                           Pre- and postamble                             */
+/*                           Pre- and postamble                             */
 /*****************************************************************************/
 
 
@@ -590,25 +598,25 @@ void g_getimmed (unsigned Flags, unsigned long Val, long Offs)
                break;
 
            case CF_LONG:
-               /* Split the value into 4 bytes */
-               B1 = (unsigned char) (Val >>  0);
-               B2 = (unsigned char) (Val >>  8);
-               B3 = (unsigned char) (Val >> 16);
-               B4 = (unsigned char) (Val >> 24);
-
-               /* Remember which bytes are done */
-               Done = 0;
-
-               /* Load the value */
-               AddCodeLine ("ldx #$%02X", B2);
-               Done |= 0x02;
-               if (B2 == B3) {
-                   AddCodeLine ("stx sreg");
-                   Done |= 0x04;
-               }
-               if (B2 == B4) {
-                   AddCodeLine ("stx sreg+1");
-                   Done |= 0x08;
+               /* Split the value into 4 bytes */
+               B1 = (unsigned char) (Val >>  0);
+               B2 = (unsigned char) (Val >>  8);
+               B3 = (unsigned char) (Val >> 16);
+               B4 = (unsigned char) (Val >> 24);
+
+               /* Remember which bytes are done */
+               Done = 0;
+
+               /* Load the value */
+               AddCodeLine ("ldx #$%02X", B2);
+               Done |= 0x02;
+               if (B2 == B3) {
+                   AddCodeLine ("stx sreg");
+                   Done |= 0x04;
+               }
+               if (B2 == B4) {
+                   AddCodeLine ("stx sreg+1");
+                   Done |= 0x08;
                }
                if ((Done & 0x04) == 0 && B1 != B3) {
                    AddCodeLine ("lda #$%02X", B3);
@@ -656,7 +664,7 @@ void g_getstatic (unsigned flags, unsigned long label, long offs)
 /* Fetch an static memory cell into the primary register */
 {
     /* Create the correct label name */
-    char* lbuf = GetLabelName (flags, label, offs);
+    const char* lbuf = GetLabelName (flags, label, offs);
 
     /* Check the size and generate the correct load operation */
     switch (flags & CF_TYPE) {
@@ -905,7 +913,7 @@ void g_putstatic (unsigned flags, unsigned long label, long offs)
 /* Store the primary register into the specified static memory cell */
 {
     /* Create the correct label name */
-    char* lbuf = GetLabelName (flags, label, offs);
+    const char* lbuf = GetLabelName (flags, label, offs);
 
     /* Check the size and generate the correct store operation */
     switch (flags & CF_TYPE) {
@@ -1123,18 +1131,81 @@ void g_tosint (unsigned flags)
 
 
 
-void g_reglong (unsigned flags)
+void g_regint (unsigned Flags)
+/* Make sure, the value in the primary register an int. Convert if necessary */
+{
+    unsigned L;
+
+    switch (Flags & CF_TYPE) {
+
+       case CF_CHAR:
+            if (Flags & CF_FORCECHAR) {
+                /* Conversion is from char */
+                if (Flags & CF_UNSIGNED) {
+                    AddCodeLine ("ldx #$00");
+                } else {
+                    L = GetLocalLabel();
+                    AddCodeLine ("ldx #$00");
+                    AddCodeLine ("cmp #$80");
+                    AddCodeLine ("bcc %s", LocalLabelName (L));
+                    AddCodeLine ("dex");
+                    g_defcodelabel (L);
+                }
+            }
+            /* FALLTHROUGH */
+
+       case CF_INT:
+       case CF_LONG:
+           break;
+
+       default:
+           typeerror (Flags);
+    }
+}
+
+
+
+void g_reglong (unsigned Flags)
 /* Make sure, the value in the primary register a long. Convert if necessary */
 {
-    switch (flags & CF_TYPE) {
+    unsigned L;
+
+    switch (Flags & CF_TYPE) {
 
        case CF_CHAR:
+            if (Flags & CF_FORCECHAR) {
+                /* Conversion is from char */
+                if (Flags & CF_UNSIGNED) {
+                    if (CodeSizeFactor >= 200) {
+                        AddCodeLine ("ldx #$00");
+                        AddCodeLine ("stx sreg");
+                        AddCodeLine ("stx sreg+1");
+                    } else {
+                        AddCodeLine ("jsr aulong");
+                    }
+                } else {
+                    if (CodeSizeFactor >= 366) {
+                        L = GetLocalLabel();
+                        AddCodeLine ("ldx #$00");
+                        AddCodeLine ("cmp #$80");
+                        AddCodeLine ("bcc %s", LocalLabelName (L));
+                        AddCodeLine ("dex");
+                        g_defcodelabel (L);
+                        AddCodeLine ("stx sreg");
+                        AddCodeLine ("stx sreg+1");
+                    } else {
+                        AddCodeLine ("jsr along");
+                    }
+                }
+            }
+            /* FALLTHROUGH */
+
        case CF_INT:
-           if (flags & CF_UNSIGNED) {
+           if (Flags & CF_UNSIGNED) {
                if (CodeSizeFactor >= 200) {
                    ldyconst (0);
                    AddCodeLine ("sty sreg");
-                   AddCodeLine ("sty sreg+1");
+                   AddCodeLine ("sty sreg+1");
                } else {
                    AddCodeLine ("jsr axulong");
                }
@@ -1147,7 +1218,7 @@ void g_reglong (unsigned flags)
            break;
 
        default:
-           typeerror (flags);
+           typeerror (Flags);
     }
 }
 
@@ -1202,7 +1273,7 @@ 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.
@@ -1215,9 +1286,14 @@ unsigned g_typecast (unsigned lhs, unsigned rhs)
     rtype = rhs & CF_TYPE;
 
     /* Check if a conversion is needed */
-    if (ltype == CF_LONG && rtype != CF_LONG && (rhs & CF_CONST) == 0) {
-       /* We must promote the primary register to long */
-       g_reglong (rhs);
+    if ((rhs & CF_CONST) == 0) {
+        if (ltype == CF_LONG && rtype != CF_LONG) {
+            /* We must promote the primary register to long */
+            g_reglong (rhs);
+        } else if (ltype == CF_INT && rtype != CF_INT) {
+            /* We must promote the primary register to int */
+            g_regint (rhs);
+        }
     }
 
     /* Do not need any other action. If the left type is int, and the primary
@@ -1438,7 +1514,7 @@ void g_addstatic (unsigned flags, unsigned long label, long offs)
     unsigned L;
 
     /* Create the correct label name */
-    char* lbuf = GetLabelName (flags, label, offs);
+    const char* lbuf = GetLabelName (flags, label, offs);
 
     switch (flags & CF_TYPE) {
 
@@ -1467,7 +1543,7 @@ void g_addstatic (unsigned flags, unsigned long label, long offs)
            g_getstatic (flags, label, offs);
            g_add (flags, 0);
            break;
-                                                             
+
        default:
            typeerror (flags);
 
@@ -1487,7 +1563,7 @@ void g_addeqstatic (unsigned flags, unsigned long label, long offs,
 /* Emit += for a static variable */
 {
     /* Create the correct label name */
-    char* lbuf = GetLabelName (flags, label, offs);
+    const char* lbuf = GetLabelName (flags, label, offs);
 
     /* Check the size and determine operation */
     switch (flags & CF_TYPE) {
@@ -1566,7 +1642,7 @@ void g_addeqstatic (unsigned flags, unsigned long label, long offs,
                if (val < 0x100) {
                    AddCodeLine ("ldy #<(%s)", lbuf);
                    AddCodeLine ("sty ptr1");
-                   AddCodeLine ("ldy #>(%s+1)", lbuf);
+                   AddCodeLine ("ldy #>(%s)", lbuf);
                    if (val == 1) {
                        AddCodeLine ("jsr laddeq1");
                    } else {
@@ -1581,7 +1657,7 @@ void g_addeqstatic (unsigned flags, unsigned long label, long offs,
            } else {
                AddCodeLine ("ldy #<(%s)", lbuf);
                AddCodeLine ("sty ptr1");
-               AddCodeLine ("ldy #>(%s+1)", lbuf);
+               AddCodeLine ("ldy #>(%s)", lbuf);
                AddCodeLine ("jsr laddeq");
            }
                    break;
@@ -1730,7 +1806,7 @@ void g_subeqstatic (unsigned flags, unsigned long label, long offs,
 /* Emit -= for a static variable */
 {
     /* Create the correct label name */
-    char* lbuf = GetLabelName (flags, label, offs);
+    const char* lbuf = GetLabelName (flags, label, offs);
 
     /* Check the size and determine operation */
     switch (flags & CF_TYPE) {
@@ -1749,10 +1825,9 @@ void g_subeqstatic (unsigned flags, unsigned long label, long offs,
                                AddCodeLine ("sta %s", lbuf);
                            }
                        } else {
+                   AddCodeLine ("eor #$FF");
                            AddCodeLine ("sec");
-                           AddCodeLine ("sta tmp1");
-                           AddCodeLine ("lda %s", lbuf);
-                           AddCodeLine ("sbc tmp1");
+                           AddCodeLine ("adc %s", lbuf);
                            AddCodeLine ("sta %s", lbuf);
                        }
                        if ((flags & CF_UNSIGNED) == 0) {
@@ -1785,13 +1860,12 @@ void g_subeqstatic (unsigned flags, unsigned long label, long offs,
                    AddCodeLine ("lda %s", lbuf);
                }
            } else {
-               AddCodeLine ("sta tmp1");
-               AddCodeLine ("lda %s", lbuf);
-               AddCodeLine ("sbc tmp1");
+               AddCodeLine ("eor #$FF");
+                       AddCodeLine ("adc %s", lbuf);
                AddCodeLine ("sta %s", lbuf);
-                       AddCodeLine ("stx tmp1");
-               AddCodeLine ("lda %s+1", lbuf);
-               AddCodeLine ("sbc tmp1");
+               AddCodeLine ("txa");
+               AddCodeLine ("eor #$FF");
+                       AddCodeLine ("adc %s+1", lbuf);
                AddCodeLine ("sta %s+1", lbuf);
                AddCodeLine ("tax");
                AddCodeLine ("lda %s", lbuf);
@@ -1803,7 +1877,7 @@ void g_subeqstatic (unsigned flags, unsigned long label, long offs,
                if (val < 0x100) {
                    AddCodeLine ("ldy #<(%s)", lbuf);
                    AddCodeLine ("sty ptr1");
-                   AddCodeLine ("ldy #>(%s+1)", lbuf);
+                   AddCodeLine ("ldy #>(%s)", lbuf);
                    AddCodeLine ("lda #$%02X", (unsigned char)val);
                    AddCodeLine ("jsr lsubeqa");
                } else {
@@ -1814,7 +1888,7 @@ void g_subeqstatic (unsigned flags, unsigned long label, long offs,
            } else {
                AddCodeLine ("ldy #<(%s)", lbuf);
                AddCodeLine ("sty ptr1");
-               AddCodeLine ("ldy #>(%s+1)", lbuf);
+               AddCodeLine ("ldy #>(%s)", lbuf);
                AddCodeLine ("jsr lsubeq");
                    }
                    break;
@@ -1845,18 +1919,17 @@ void g_subeqlocal (unsigned flags, int offs, unsigned long val)
                    AddCodeLine ("lda (sp),y");
                    AddCodeLine ("sbc #$%02X", (unsigned char)val);
                } else {
-                   AddCodeLine ("sta tmp1");
-                   AddCodeLine ("lda (sp),y");
-                   AddCodeLine ("sbc tmp1");
+                   AddCodeLine ("eor #$FF");
+                   AddCodeLine ("adc (sp),y");
                }
                        AddCodeLine ("sta (sp),y");
                if ((flags & CF_UNSIGNED) == 0) {
-                   unsigned L = GetLocalLabel();
+                   unsigned L = GetLocalLabel();
                    AddCodeLine ("bpl %s", LocalLabelName (L));
-                   AddCodeLine ("dex");
-                   g_defcodelabel (L);
-               }
-                       break;
+                   AddCodeLine ("dex");
+                   g_defcodelabel (L);
+               }
+                       break;
                    }
                    /* FALLTHROUGH */
 
@@ -1986,7 +2059,7 @@ void g_addaddr_static (unsigned flags, unsigned long label, long offs)
 /* Add the address of a static variable to ax */
 {
     /* Create the correct label name */
-    char* lbuf = GetLabelName (flags, label, offs);
+    const char* lbuf = GetLabelName (flags, label, offs);
 
     /* Add the address to the current ax value */
     AddCodeLine ("clc");
@@ -2478,6 +2551,14 @@ void g_mul (unsigned flags, unsigned long val)
                            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");
@@ -2498,6 +2579,15 @@ void g_mul (unsigned flags, unsigned long val)
                    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;
@@ -3222,9 +3312,9 @@ void g_eq (unsigned flags, unsigned long val)
 {
     static char* ops [12] = {
        "toseq00",      "toseqa0",      "toseqax",
-       "toseq00",      "toseqa0",      "toseqax",
-       0,              0,              "toseqeax",
-       0,              0,              "toseqeax",
+       "toseq00",      "toseqa0",      "toseqax",
+       0,              0,              "toseqeax",
+       0,              0,              "toseqeax",
     };
 
     unsigned L;
@@ -3301,11 +3391,11 @@ void g_ne (unsigned flags, unsigned long val)
                /* FALLTHROUGH */
 
            case CF_INT:
-               L = GetLocalLabel();
+               L = GetLocalLabel();
                AddCodeLine ("cpx #$%02X", (unsigned char)(val >> 8));
                AddCodeLine ("bne %s", LocalLabelName (L));
                AddCodeLine ("cmp #$%02X", (unsigned char)val);
-               g_defcodelabel (L);
+               g_defcodelabel (L);
                AddCodeLine ("jsr boolne");
                return;
 
@@ -3335,7 +3425,7 @@ void g_lt (unsigned flags, unsigned long val)
     static char* ops [12] = {
        "toslt00",      "toslta0",      "tosltax",
        "tosult00",     "tosulta0",     "tosultax",
-       0,              0,              "toslteax",
+       0,              0,              "toslteax",
        0,              0,              "tosulteax",
     };
 
@@ -3347,6 +3437,8 @@ void g_lt (unsigned flags, unsigned long val)
        /* Give a warning in some special cases */
        if ((flags & CF_UNSIGNED) && val == 0) {
            Warning ("Condition is never true");
+           AddCodeLine ("jsr return0");
+           return;
        }
 
        /* Look at the type */
@@ -3356,7 +3448,7 @@ void g_lt (unsigned flags, unsigned long val)
                if (flags & CF_FORCECHAR) {
                    AddCodeLine ("cmp #$%02X", (unsigned char)val);
                    if (flags & CF_UNSIGNED) {
-                       AddCodeLine ("jsr boolult");
+                       AddCodeLine ("jsr boolult");
                    } else {
                        AddCodeLine ("jsr boollt");
                    }
@@ -3365,25 +3457,31 @@ void g_lt (unsigned flags, unsigned long val)
                /* FALLTHROUGH */
 
            case CF_INT:
-               if ((flags & CF_UNSIGNED) == 0 && val == 0) {
-                   /* If we have a signed compare against zero, we only need to
-                    * test the high byte.
-                    */
-                   AddCodeLine ("txa");
-                   AddCodeLine ("jsr boollt");
-                   return;
-               }
-               /* Direct code only for unsigned data types */
                if (flags & CF_UNSIGNED) {
-                   unsigned L = GetLocalLabel();
-                   AddCodeLine ("cpx #$%02X", (unsigned char)(val >> 8));
-                           AddCodeLine ("bne %s", LocalLabelName (L));
-                   AddCodeLine ("cmp #$%02X", (unsigned char)val);
-                   g_defcodelabel (L);
+                   /* Unsigned compare */
+                   /* 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;
-               }
-               break;
+               } else {
+                   /* Signed compare */
+                   if ((val & 0xFF) == 0) {
+                       /* Low byte is zero, just look at the high byte */
+                       AddCodeLine ("cpx #$%02X", (unsigned char)(val >> 8));
+                   } else {
+                       /* Subtract the two values */
+                       AddCodeLine ("cmp #$%02X", (unsigned char)val);
+                       AddCodeLine ("txa");
+                       AddCodeLine ("sbc #$%02X", (unsigned char)(val >> 8));
+                   }
+                   AddCodeLine ("jsr boollt");
+               }
+               return;
 
            case CF_LONG:
                if ((flags & CF_UNSIGNED) == 0 && val == 0) {
@@ -3391,10 +3489,25 @@ void g_lt (unsigned flags, unsigned long val)
                     * test the high byte.
                     */
                    AddCodeLine ("lda sreg+1");
+               } else {
+                   /* 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));
+               }
+               /* Emit the proper makebool routine */
+               if (flags & CF_UNSIGNED) {
+                   /* Unsigned compare */
+                   AddCodeLine ("jsr boolult");
+               } else {
+                   /* Signed compare */
                    AddCodeLine ("jsr boollt");
-                   return;
                }
-               break;
+               return;
 
            default:
                typeerror (flags);
@@ -3429,30 +3542,34 @@ void g_le (unsigned flags, unsigned long val)
      */
     if (flags & CF_CONST) {
 
-       /* <= is not very effective on the 6502, so try to convert
-        * it into < if the value is in a valid range.
-        */
-
        /* Look at the type */
        switch (flags & CF_TYPE) {
 
            case CF_CHAR:
                if (flags & CF_FORCECHAR) {
                    if (flags & CF_UNSIGNED) {
-                       if (val < 255) {
-                           AddCodeLine ("cmp #$%02X", (unsigned char)val+1);
-                           AddCodeLine ("jsr boolult");
+                       /* Unsigned compare */
+                       if (val < 0xFF) {
+                           /* Use < instead of <= because the former gives
+                            * better code on the 6502 than the latter.
+                            */
+                           g_lt (flags, val+1);
                        } else {
-                           AddCodeLine ("cmp #$%02X", (unsigned char)val);
-                           AddCodeLine ("jsr boolule");
+                           /* Always true */
+                           Warning ("Condition is always true");
+                           AddCodeLine ("jsr return1");
                        }
                    } else {
-                       if (val < 127) {
-                           AddCodeLine ("cmp #$%02X", (unsigned char)val+1);
-                           AddCodeLine ("jsr boollt");
+                       /* Signed compare */
+                       if ((long) val < 0x7F) {
+                           /* Use < instead of <= because the former gives
+                            * better code on the 6502 than the latter.
+                            */
+                           g_lt (flags, val+1);
                        } else {
-                           AddCodeLine ("cmp #$%02X", (unsigned char)val);
-                           AddCodeLine ("jsr boolle");
+                           /* Always true */
+                           Warning ("Condition is always true");
+                           AddCodeLine ("jsr return1");
                        }
                    }
                    return;
@@ -3461,23 +3578,53 @@ void g_le (unsigned flags, unsigned long val)
 
            case CF_INT:
                if (flags & CF_UNSIGNED) {
-                   unsigned L = GetLocalLabel();
-                   const char* Name = "boolule";
-                   if (val < 65535) {
-                       ++val;
-                       Name = "boolult";
+                   /* 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");
                    }
-                   AddCodeLine ("cpx #$%02X", (unsigned char)(val >> 8));
-                   AddCodeLine ("bne %s", LocalLabelName (L));
-                   AddCodeLine ("cmp #$%02X", (unsigned char)val);
-                   g_defcodelabel (L);
-                   AddCodeLine ("jsr %s", Name);
-                   return;
                }
-               break;
+               return;
 
            case CF_LONG:
-               break;
+               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);
@@ -3500,7 +3647,7 @@ void g_gt (unsigned flags, unsigned long val)
 /* Test for greater than */
 {
     static char* ops [12] = {
-       "tosgt00",      "tosgta0",      "tosgtax",
+       "tosgt00",      "tosgta0",      "tosgtax",
        "tosugt00",     "tosugta0",     "tosugtax",
        0,              0,              "tosgteax",
        0,              0,              "tosugteax",
@@ -3512,37 +3659,38 @@ void g_gt (unsigned flags, unsigned long val)
      */
     if (flags & CF_CONST) {
 
-               /* > is not very effective on the 6502, so try to convert
-        * it into >= if the value is in a valid range.
-        */
-
        /* Look at the type */
        switch (flags & CF_TYPE) {
 
            case CF_CHAR:
                if (flags & CF_FORCECHAR) {
                    if (flags & CF_UNSIGNED) {
-                       /* If we have a compare > 0, we will replace it by
-                        * != 0 here, since both are identical but the latter
-                        * is easier to optimize.
-                        */
                                if (val == 0) {
-                           AddCodeLine ("cmp #$%02X", (unsigned char)val);
-                           AddCodeLine ("jsr boolne");
-                       } else if (val < 255) {
-                           AddCodeLine ("cmp #$%02X", (unsigned char)val+1);
-                           AddCodeLine ("jsr booluge");
+                           /* If we have a compare > 0, we will replace it by
+                            * != 0 here, since both are identical but the
+                            * latter is easier to optimize.
+                            */
+                           g_ne (flags, val);
+                       } else if (val < 0xFF) {
+                           /* Use >= instead of > because the former gives
+                            * better code on the 6502 than the latter.
+                            */
+                           g_ge (flags, val+1);
                        } else {
-                           AddCodeLine ("cmp #$%02X", (unsigned char)val);
-                           AddCodeLine ("jsr boolugt");
+                           /* Never true */
+                           Warning ("Condition is never true");
+                           AddCodeLine ("jsr return0");
                        }
                    } else {
-                       if (val < 127) {
-                           AddCodeLine ("cmp #$%02X", (unsigned char)val+1);
-                           AddCodeLine ("jsr boolge");
+                       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 {
-                           AddCodeLine ("cmp #$%02X", (unsigned char)val);
-                           AddCodeLine ("jsr boolgt");
+                           /* Never true */
+                           Warning ("Condition is never true");
+                           AddCodeLine ("jsr return0");
                        }
                    }
                    return;
@@ -3551,33 +3699,65 @@ void g_gt (unsigned flags, unsigned long val)
 
            case CF_INT:
                if (flags & CF_UNSIGNED) {
-                   /* If we have a compare > 0, we will replace it by
-                    * != 0 here, since both are identical but the latter
-                    * is easier to optimize.
-                    */
+                   /* Unsigned compare */
                    if (val == 0) {
-                       AddCodeLine ("stx tmp1");
-                       AddCodeLine ("ora tmp1");
-                       AddCodeLine ("jsr boolne");
-                   } else {
-                       unsigned L = GetLocalLabel();
-                       const char* Name = "boolugt";
-                       if (val < 65535) {
-                           ++val;
-                           Name = "booluge";
-                       }
-                               AddCodeLine ("cpx #$%02X", (unsigned char)(val >> 8));
-                       AddCodeLine ("bne %s", LocalLabelName (L));
-                       AddCodeLine ("cmp #$%02X", (unsigned char)val);
-                       g_defcodelabel (L);
-                               AddCodeLine ("jsr %s", Name);
+                       /* 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");
                    }
-                   return;
-                       }
-               break;
+                       } 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:
-               break;
+               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);
@@ -3615,6 +3795,8 @@ void g_ge (unsigned flags, unsigned long val)
        /* Give a warning in some special cases */
        if ((flags & CF_UNSIGNED) && val == 0) {
            Warning ("Condition is always true");
+           AddCodeLine ("jsr return1");
+           return;
        }
 
        /* Look at the type */
@@ -3633,25 +3815,31 @@ void g_ge (unsigned flags, unsigned long val)
                /* FALLTHROUGH */
 
            case CF_INT:
-               if ((flags & CF_UNSIGNED) == 0 && val == 0) {
-                   /* If we have a signed compare against zero, we only need to
-                    * test the high byte.
-                    */
-                   AddCodeLine ("txa");
-                   AddCodeLine ("jsr boolge");
-                   return;
-               }
-               /* Direct code only for unsigned data types */
                if (flags & CF_UNSIGNED) {
-                   unsigned L = GetLocalLabel();
-                           AddCodeLine ("cpx #$%02X", (unsigned char)(val >> 8));
-                           AddCodeLine ("bne %s", LocalLabelName (L));
-                   AddCodeLine ("cmp #$%02X", (unsigned char)val);
-                   g_defcodelabel (L);
+                   /* Unsigned compare */
+                   /* If the low byte is zero, we must only test the high byte */
+                   AddCodeLine ("cpx #$%02X", (unsigned char)(val >> 8));
+                   if ((val & 0xFF) != 0) {
+                       unsigned L = GetLocalLabel();
+                       AddCodeLine ("bne %s", LocalLabelName (L));
+                       AddCodeLine ("cmp #$%02X", (unsigned char)val);
+                       g_defcodelabel (L);
+                   }
                    AddCodeLine ("jsr booluge");
-                   return;
-               }
-               break;
+               } else {
+                   /* Signed compare */
+                   if ((val & 0xFF) == 0) {
+                       /* Low byte is zero, just look at the high byte */
+                       AddCodeLine ("cpx #$%02X", (unsigned char)(val >> 8));
+                   } else {
+                       /* Subtract the two values */
+                       AddCodeLine ("cmp #$%02X", (unsigned char)val);
+                       AddCodeLine ("txa");
+                       AddCodeLine ("sbc #$%02X", (unsigned char)(val >> 8));
+                   }
+                   AddCodeLine ("jsr boolge");
+               }
+               return;
 
            case CF_LONG:
                if ((flags & CF_UNSIGNED) == 0 && val == 0) {
@@ -3659,10 +3847,25 @@ void g_ge (unsigned flags, unsigned long val)
                     * test the high byte.
                     */
                    AddCodeLine ("lda sreg+1");
+               } else {
+                   /* 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));
+               }
+               /* Emit the proper makebool routine */
+               if (flags & CF_UNSIGNED) {
+                   /* Unsigned compare */
+                   AddCodeLine ("jsr booluge");
+               } else {
+                   /* Signed compare */
                    AddCodeLine ("jsr boolge");
-                   return;
                }
-               break;
+               return;
 
            default:
                typeerror (flags);
@@ -3778,6 +3981,80 @@ void g_zerobytes (unsigned n)
 
 
 
+void g_initregister (unsigned Label, unsigned Reg, unsigned Size)
+/* Initialize a register variable from static initialization data */
+{
+    /* Register variables do always have less than 128 bytes */
+    unsigned CodeLabel = GetLocalLabel ();
+    ldxconst (Size-1);
+    g_defcodelabel (CodeLabel);
+    AddCodeLine ("lda %s,x", GetLabelName (CF_STATIC, Label, 0));
+    AddCodeLine ("sta %s,x", GetLabelName (CF_REGVAR, Reg, 0));
+    AddCodeLine ("dex");
+    AddCodeLine ("bpl %s", LocalLabelName (CodeLabel));
+}
+
+
+
+void g_initauto (unsigned Label, unsigned Size)
+/* Initialize a local variable at stack offset zero from static data */
+{
+    unsigned CodeLabel = GetLocalLabel ();
+
+    CheckLocalOffs (Size);
+    if (Size <= 128) {
+        ldyconst (Size-1);
+       g_defcodelabel (CodeLabel);
+        AddCodeLine ("lda %s,y", GetLabelName (CF_STATIC, Label, 0));
+        AddCodeLine ("sta (sp),y");
+        AddCodeLine ("dey");
+        AddCodeLine ("bpl %s", LocalLabelName (CodeLabel));
+    } else if (Size <= 256) {
+        ldyconst (0);
+       g_defcodelabel (CodeLabel);
+        AddCodeLine ("lda %s,y", GetLabelName (CF_STATIC, Label, 0));
+        AddCodeLine ("sta (sp),y");
+        AddCodeLine ("iny");
+        AddCodeLine ("cpy #$%02X", (unsigned char) Size);
+        AddCodeLine ("bne %s", LocalLabelName (CodeLabel));
+    }
+}
+
+
+
+void g_initstatic (unsigned InitLabel, unsigned VarLabel, unsigned Size)
+/* Initialize a static local variable from static initialization data */
+{
+    if (Size <= 128) {
+        unsigned CodeLabel = GetLocalLabel ();
+        ldyconst (Size-1);
+        g_defcodelabel (CodeLabel);
+        AddCodeLine ("lda %s,y", GetLabelName (CF_STATIC, InitLabel, 0));
+        AddCodeLine ("sta %s,y", GetLabelName (CF_STATIC, VarLabel, 0));
+        AddCodeLine ("dey");
+        AddCodeLine ("bpl %s", LocalLabelName (CodeLabel));
+    } else if (Size <= 256) {
+        unsigned CodeLabel = GetLocalLabel ();
+        ldyconst (0);
+       g_defcodelabel (CodeLabel);
+        AddCodeLine ("lda %s,y", GetLabelName (CF_STATIC, InitLabel, 0));
+        AddCodeLine ("sta %s,y", GetLabelName (CF_STATIC, VarLabel, 0));
+        AddCodeLine ("iny");
+        AddCodeLine ("cpy #$%02X", (unsigned char) Size);
+        AddCodeLine ("bne %s", LocalLabelName (CodeLabel));
+    } else {
+        /* Use the easy way here: memcpy */
+        g_getimmed (CF_STATIC, VarLabel, 0);
+        AddCodeLine ("jsr pushax");
+        g_getimmed (CF_STATIC, InitLabel, 0);
+        AddCodeLine ("jsr pushax");
+        g_getimmed (CF_INT | CF_UNSIGNED | CF_CONST, Size, 0);
+        AddCodeLine ("jsr %s", GetLabelName (CF_EXTERNAL, (unsigned long) "memcpy", 0));
+    }
+}
+
+
+
 /*****************************************************************************/
 /*                                    Switch statement                              */
 /*****************************************************************************/
@@ -3886,7 +4163,7 @@ void g_strlen (unsigned flags, unsigned long val, long offs)
     if (flags & CF_CONST) {
 
        /* The address of the string is constant. Create the correct label name */
-       char* lbuf = GetLabelName (flags, val, offs);
+       const char* lbuf = GetLabelName (flags, val, offs);
 
        /* Generate the strlen code */
        AddCodeLine ("ldy #$FF");