]> git.sur5r.net Git - cc65/blobdiff - src/cc65/codegen.c
Renamed ExprDesc.Val to ExprDesc.IVal. Added an FVal field for a floating
[cc65] / src / cc65 / codegen.c
index ff44514abb6941d0ff628545fc6ee9989f0276eb..88cebe9a4b734ead469354eb1fb8d466a06a88f9 100644 (file)
@@ -6,8 +6,8 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 1998-2003 Ullrich von Bassewitz                                       */
-/*               Römerstrasse 52                                             */
+/* (C) 1998-2004 Ullrich von Bassewitz                                       */
+/*               Römerstraße 52                                              */
 /*               D-70794 Filderstadt                                         */
 /* EMail:        uz@cc65.org                                                 */
 /*                                                                           */
 #include "error.h"
 #include "global.h"
 #include "segments.h"
+#include "stackptr.h"
 #include "textseg.h"
 #include "util.h"
 #include "codegen.h"
 
 
 
-/*****************************************************************************/
-/*                                  Data                                    */
-/*****************************************************************************/
-
-
-
-/* Compiler relative stack pointer */
-int oursp      = 0;
-
-
-
 /*****************************************************************************/
 /*                                         Helpers                                  */
 /*****************************************************************************/
@@ -165,10 +155,18 @@ void g_preamble (void)
                    VER_MAJOR, VER_MINOR, VER_PATCH);
 
     /* If we're producing code for some other CPU, switch the command set */
-    if (CPU == CPU_65C02) {
-       AddTextLine ("\t.setcpu\t\t\"65C02\"");
+    switch (CPU) {
+        case CPU_6502:      AddTextLine ("\t.setcpu\t\t\"6502\"");      break;
+        case CPU_6502X:     AddTextLine ("\t.setcpu\t\t\"6502X\"");     break;
+        case CPU_65SC02:    AddTextLine ("\t.setcpu\t\t\"65SC02\"");    break;
+        case CPU_65C02:     AddTextLine ("\t.setcpu\t\t\"65C02\"");     break;
+        case CPU_65816:     AddTextLine ("\t.setcpu\t\t\"65816\"");     break;
+        default:            Internal ("Unknown CPU: %d", CPU);
     }
 
+    /* Use smart mode */
+    AddTextLine ("\t.smart\t\ton");
+
     /* Allow auto import for runtime library routines */
     AddTextLine ("\t.autoimport\ton");
 
@@ -230,15 +228,11 @@ void g_usebss (void)
 
 
 
-void g_segname (segment_t Seg, const char* Name)
-/* Set the name of a segment */
+void g_segname (segment_t Seg)
+/* Emit the name of a segment if necessary */
 {
-    DataSeg* S;
-
-    /* Remember the new name */
-    NewSegName (Seg, Name);
-
     /* Emit a segment directive for the data style segments */
+    DataSeg* S;
     switch (Seg) {
        case SEG_RODATA: S = CS->ROData; break;
        case SEG_DATA:   S = CS->Data;   break;
@@ -246,7 +240,7 @@ void g_segname (segment_t Seg, const char* Name)
        default:         S = 0;          break;
     }
     if (S) {
-               DS_AddLine (S, ".segment\t\"%s\"", Name);
+               DS_AddLine (S, ".segment\t\"%s\"", GetSegName (Seg));
     }
 }
 
@@ -287,7 +281,7 @@ unsigned sizeofarg (unsigned flags)
 int pop (unsigned flags)
 /* Pop an argument of the given size */
 {
-    return oursp += sizeofarg (flags);
+    return StackPtr += sizeofarg (flags);
 }
 
 
@@ -295,7 +289,7 @@ int pop (unsigned flags)
 int push (unsigned flags)
 /* Push an argument of the given size */
 {
-    return oursp -= sizeofarg (flags);
+    return StackPtr -= sizeofarg (flags);
 }
 
 
@@ -460,21 +454,22 @@ void g_leave (void)
 /* Function epilogue */
 {
     /* How many bytes of locals do we have to drop? */
-    int k = -oursp;
+    unsigned k = (unsigned) -StackPtr;
 
     /* If we didn't have a variable argument list, don't call leave */
     if (funcargs >= 0) {
 
-       /* Drop stackframe if needed */
+       /* Drop stackframe if needed. We can only drop 255 bytes at a time. */
        k += funcargs;
-               if (k > 0) {
-           if (k <= 8) {
-           AddCodeLine ("jsr incsp%d", k);
+               while (k > 0) {
+            unsigned ToDrop = (k > 255)? 255 : k;
+           if (ToDrop <= 8) {
+               AddCodeLine ("jsr incsp%d", k);
            } else {
-               CheckLocalOffs (k);
-               ldyconst (k);
-               AddCodeLine ("jsr addysp");
+               ldyconst (ToDrop);
+               AddCodeLine ("jsr addysp");
            }
+            k -= ToDrop;
        }
 
     } else {
@@ -484,6 +479,11 @@ void g_leave (void)
            AddCodeLine ("jsr leave");
        } else {
            /* We've a stack frame to drop */
+            while (k > 255) {
+                ldyconst (255);
+                AddCodeLine ("jsr addysp");
+                k -= 255;
+            }
            ldyconst (k);
            AddCodeLine ("jsr leavey");
        }
@@ -505,7 +505,7 @@ 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 -= oursp;
+    StackOffs -= StackPtr;
     CheckLocalOffs (StackOffs);
 
     /* Generate code */
@@ -573,7 +573,7 @@ void g_save_regvars (int RegOffs, unsigned Bytes)
     }
 
     /* We pushed stuff, correct the stack pointer */
-    oursp -= Bytes;
+    StackPtr -= Bytes;
 }
 
 
@@ -582,7 +582,7 @@ 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 */
@@ -613,17 +613,38 @@ void g_restore_regvars (int StackOffs, int RegOffs, unsigned Bytes)
                AddCodeLine ("lda (sp),y");
                AddCodeLine ("sta regbank%+d", RegOffs+2);
 
+    } else if (StackOffs <= RegOffs) {
+
+        /* More bytes, but the relation between the register offset in the
+         * register bank and the stack offset allows us to generate short
+         * code that uses just one index register.
+         */
+               unsigned Label = GetLocalLabel ();
+       ldyconst (StackOffs);
+               g_defcodelabel (Label);
+       AddCodeLine ("lda (sp),y");
+       AddCodeLine ("sta regbank%+d,y", RegOffs - StackOffs);
+       AddCodeLine ("iny");
+       AddCodeLine ("cpy #$%02X", StackOffs + Bytes);
+       AddCodeLine ("bne %s", LocalLabelName (Label));
+
     } else {
 
-               /* More bytes - loop */
+        /* Ok, this is the generic code. We need to save X because the
+         * caller will only save A.
+         */
                unsigned Label = GetLocalLabel ();
-       ldyconst (StackOffs);
+        AddCodeLine ("stx tmp1");
+       ldyconst (StackOffs + Bytes - 1);
+        ldxconst (Bytes - 1);
                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));
+       AddCodeLine ("lda (sp),y");
+               AddCodeLine ("sta regbank%+d,x", RegOffs);
+       AddCodeLine ("dey");
+        AddCodeLine ("dex");
+       AddCodeLine ("bpl %s", LocalLabelName (Label));
+        AddCodeLine ("ldx tmp1");
+
     }
 }
 
@@ -782,7 +803,7 @@ void g_getstatic (unsigned flags, unsigned long label, long offs)
 void g_getlocal (unsigned flags, int offs)
 /* Fetch specified local object (local var). */
 {
-    offs -= oursp;
+    offs -= StackPtr;
     CheckLocalOffs (offs);
     switch (flags & CF_TYPE) {
 
@@ -887,7 +908,7 @@ void g_leasp (int offs)
 /* Fetch the address of the specified symbol into the primary register */
 {
     /* Calculate the offset relative to sp */
-    offs -= oursp;
+    offs -= StackPtr;
 
     /* For value 0 we do direct code */
     if (offs == 0) {
@@ -899,7 +920,7 @@ void g_leasp (int offs)
                    AddCodeLine ("jsr leaasp"); /* Load effective address */
                } else {
            unsigned L = GetLocalLabel ();
-                   if (CPU == CPU_65C02 && offs == 1) {
+                   if ((CPUIsets[CPU] & CPU_ISET_65SC02) != 0 && offs == 1) {
                        AddCodeLine ("lda sp");
                        AddCodeLine ("ldx sp+1");
                        AddCodeLine ("ina");
@@ -928,13 +949,13 @@ void g_leavariadic (int Offs)
     unsigned ArgSizeOffs;
 
     /* Calculate the offset relative to sp */
-    Offs -= oursp;
+    Offs -= StackPtr;
 
     /* Get the offset of the parameter which is stored at sp+0 on function
      * entry and check if this offset is reachable with a byte offset.
      */
-    CHECK (oursp <= 0);
-    ArgSizeOffs = -oursp;
+    CHECK (StackPtr <= 0);
+    ArgSizeOffs = -StackPtr;
     CheckLocalOffs (ArgSizeOffs);
 
     /* Get the size of all parameters. */
@@ -1008,7 +1029,7 @@ void g_putstatic (unsigned flags, unsigned long label, long offs)
 void g_putlocal (unsigned Flags, int Offs, long Val)
 /* Put data into local object. */
 {
-    Offs -= oursp;
+    Offs -= StackPtr;
     CheckLocalOffs (Offs);
     switch (Flags & CF_TYPE) {
 
@@ -1527,7 +1548,7 @@ void g_addlocal (unsigned flags, int offs)
     unsigned L;
 
     /* Correct the offset and check it */
-    offs -= oursp;
+    offs -= StackPtr;
     CheckLocalOffs (offs);
 
     switch (flags & CF_TYPE) {
@@ -1734,7 +1755,7 @@ void g_addeqlocal (unsigned flags, int offs, unsigned long val)
 /* Emit += for a local variable */
 {
     /* Calculate the true offset, check it, load it into Y */
-    offs -= oursp;
+    offs -= StackPtr;
     CheckLocalOffs (offs);
 
     /* Check the size and determine operation */
@@ -1965,7 +1986,7 @@ void g_subeqlocal (unsigned flags, int offs, unsigned long val)
 /* Emit -= for a local variable */
 {
     /* Calculate the true offset, check it, load it into Y */
-    offs -= oursp;
+    offs -= StackPtr;
     CheckLocalOffs (offs);
 
     /* Check the size and determine operation */
@@ -2088,7 +2109,7 @@ void g_addaddr_local (unsigned flags attribute ((unused)), int offs)
     unsigned L = 0;
 
     /* Add the offset */
-    offs -= oursp;
+    offs -= StackPtr;
     if (offs != 0) {
        /* We cannot address more then 256 bytes of locals anyway */
        L = GetLocalLabel();
@@ -2413,7 +2434,7 @@ void g_call (unsigned Flags, const char* Label, unsigned ArgSize)
        ldyconst (ArgSize);
     }
     AddCodeLine ("jsr _%s", Label);
-    oursp += ArgSize;          /* callee pops args */
+    StackPtr += ArgSize;               /* callee pops args */
 }
 
 
@@ -2430,7 +2451,7 @@ void g_callind (unsigned Flags, unsigned ArgSize, int Offs)
        AddCodeLine ("jsr callax");
     } else {
        /* The address is on stack, offset is on Val */
-       Offs -= oursp;
+       Offs -= StackPtr;
        CheckLocalOffs (Offs);
        AddCodeLine ("pha");
        AddCodeLine ("ldy #$%02X", Offs);
@@ -2444,7 +2465,7 @@ void g_callind (unsigned Flags, unsigned ArgSize, int Offs)
     }
 
     /* Callee pops args */
-    oursp += ArgSize;
+    StackPtr += ArgSize;
 }
 
 
@@ -2751,36 +2772,52 @@ void g_or (unsigned flags, unsigned long val)
 
            case CF_CHAR:
                if (flags & CF_FORCECHAR) {
-                   if ((val & 0xFF) != 0xFF) {
+                   if ((val & 0xFF) != 0) {
                                AddCodeLine ("ora #$%02X", (unsigned char)val);
                    }
                    return;
                }
                /* FALLTHROUGH */
 
-           case CF_INT:
-               if (val <= 0xFF) {
-                   AddCodeLine ("ora #$%02X", (unsigned char)val);
-                   return;
-               }
-               break;
-
-           case CF_LONG:
-               if (val <= 0xFF) {
-                   AddCodeLine ("ora #$%02X", (unsigned char)val);
-                   return;
-               }
-               break;
+           case CF_INT:
+               if (val <= 0xFF) {
+                    if ((val & 0xFF) != 0) {
+                       AddCodeLine ("ora #$%02X", (unsigned char)val);
+                    }
+               } else if ((val & 0xFF00) == 0xFF00) {
+                    if ((val & 0xFF) != 0) {
+                       AddCodeLine ("ora #$%02X", (unsigned char)val);
+                    }
+                    ldxconst (0xFF);
+                } else if (val != 0) {
+                    AddCodeLine ("ora #$%02X", (unsigned char)val);
+                    AddCodeLine ("pha");
+                    AddCodeLine ("txa");
+                    AddCodeLine ("ora #$%02X", (unsigned char)(val >> 8));
+                    AddCodeLine ("tax");
+                    AddCodeLine ("pla");
+                }
+               return;
 
-           default:
-               typeerror (flags);
-       }
+           case CF_LONG:
+               if (val <= 0xFF) {
+                    if ((val & 0xFF) != 0) {
+                        AddCodeLine ("ora #$%02X", (unsigned char)val);
+                    }
+                   return;
+               }
+               break;
 
-       /* If we go here, we didn't emit code. Push the lhs on stack and fall
-        * into the normal, non-optimized stuff.
-        */
-       g_push (flags & ~CF_CONST, 0);
+           default:
+               typeerror (flags);
+       }
 
+       /* If we go here, we didn't emit code. Push the lhs on stack and fall
+        * into the normal, non-optimized stuff. Note: The standard stuff will
+         * always work with ints.
+        */
+        flags &= ~CF_FORCECHAR;
+               g_push (flags & ~CF_CONST, 0);
     }
 
     /* Use long way over the stack */
@@ -2821,16 +2858,17 @@ void g_xor (unsigned flags, unsigned long val)
                    if (val != 0) {
                        AddCodeLine ("eor #$%02X", (unsigned char)val);
                    }
-                   return;
-               } else if ((val & 0xFF) == 0) {
+                       } else if (val != 0) {
+                    if ((val & 0xFF) != 0) {
+                        AddCodeLine ("eor #$%02X", (unsigned char)val);
+                    }
                    AddCodeLine ("pha");
                    AddCodeLine ("txa");
                    AddCodeLine ("eor #$%02X", (unsigned char)(val >> 8));
                    AddCodeLine ("tax");
                    AddCodeLine ("pla");
-                   return;
                }
-               break;
+               return;
 
            case CF_LONG:
                if (val <= 0xFF) {
@@ -2845,11 +2883,12 @@ void g_xor (unsigned flags, unsigned long val)
                typeerror (flags);
        }
 
-       /* If we go here, we didn't emit code. Push the lhs on stack and fall
-        * into the normal, non-optimized stuff.
-        */
-       g_push (flags & ~CF_CONST, 0);
-
+       /* If we go here, we didn't emit code. Push the lhs on stack and fall
+        * into the normal, non-optimized stuff. Note: The standard stuff will
+         * always work with ints.
+        */
+        flags &= ~CF_FORCECHAR;
+               g_push (flags & ~CF_CONST, 0);
     }
 
     /* Use long way over the stack */
@@ -2858,68 +2897,70 @@ void g_xor (unsigned flags, unsigned long val)
 
 
 
-void g_and (unsigned flags, unsigned long val)
+void g_and (unsigned Flags, unsigned long Val)
 /* Primary = TOS & Primary */
 {
     static char* ops [12] = {
-       0,              "tosanda0",     "tosandax",
-       0,              "tosanda0",     "tosandax",
-       0,              0,              "tosandeax",
-       0,              0,              "tosandeax",
+       0,              "tosanda0",     "tosandax",
+       0,              "tosanda0",     "tosandax",
+       0,              0,              "tosandeax",
+       0,              0,              "tosandeax",
     };
 
     /* If the right hand side is const, the lhs is not on stack but still
      * in the primary register.
      */
-    if (flags & CF_CONST) {
+    if (Flags & CF_CONST) {
 
-       switch (flags & CF_TYPE) {
+       switch (Flags & CF_TYPE) {
 
            case CF_CHAR:
-               if (flags & CF_FORCECHAR) {
-                   AddCodeLine ("and #$%02X", (unsigned char)val);
-                   return;
-               }
-               /* FALLTHROUGH */
+               if (Flags & CF_FORCECHAR) {
+                    if ((Val & 0xFF) != 0xFF) {
+                        AddCodeLine ("and #$%02X", (unsigned char)Val);
+                    }
+                   return;
+               }
+               /* FALLTHROUGH */
            case CF_INT:
-               if ((val & 0xFFFF) != 0xFFFF) {
-                           if (val <= 0xFF) {
-                       ldxconst (0);
-                       if (val == 0) {
-                           ldaconst (0);
-                       } else if (val != 0xFF) {
-                           AddCodeLine ("and #$%02X", (unsigned char)val);
-                       }
-                   } else if ((val & 0xFF00) == 0xFF00) {
-                       AddCodeLine ("and #$%02X", (unsigned char)val);
-                   } else if ((val & 0x00FF) == 0x0000) {
-                       AddCodeLine ("txa");
-                       AddCodeLine ("and #$%02X", (unsigned char)(val >> 8));
-                       AddCodeLine ("tax");
-                       ldaconst (0);
+               if ((Val & 0xFFFF) != 0xFFFF) {
+                           if (Val <= 0xFF) {
+                       ldxconst (0);
+                       if (Val == 0) {
+                           ldaconst (0);
+                       } else if (Val != 0xFF) {
+                           AddCodeLine ("and #$%02X", (unsigned char)Val);
+                       }
+                   } else if ((Val & 0xFF00) == 0xFF00) {
+                       AddCodeLine ("and #$%02X", (unsigned char)Val);
+                   } else if ((Val & 0x00FF) == 0x0000) {
+                       AddCodeLine ("txa");
+                       AddCodeLine ("and #$%02X", (unsigned char)(Val >> 8));
+                       AddCodeLine ("tax");
+                       ldaconst (0);
                    } else {
-                       AddCodeLine ("tay");
-                       AddCodeLine ("txa");
-                       AddCodeLine ("and #$%02X", (unsigned char)(val >> 8));
-                       AddCodeLine ("tax");
-                       AddCodeLine ("tya");
-                       if ((val & 0x00FF) != 0x00FF) {
-                           AddCodeLine ("and #$%02X", (unsigned char)val);
-                       }
-                   }
-               }
+                       AddCodeLine ("tay");
+                       AddCodeLine ("txa");
+                       AddCodeLine ("and #$%02X", (unsigned char)(Val >> 8));
+                       AddCodeLine ("tax");
+                       AddCodeLine ("tya");
+                       if ((Val & 0x00FF) != 0x00FF) {
+                           AddCodeLine ("and #$%02X", (unsigned char)Val);
+                       }
+                   }
+               }
                return;
 
            case CF_LONG:
-               if (val <= 0xFF) {
+               if (Val <= 0xFF) {
                    ldxconst (0);
                    AddCodeLine ("stx sreg+1");
                    AddCodeLine ("stx sreg");
-                   if ((val & 0xFF) != 0xFF) {
-                        AddCodeLine ("and #$%02X", (unsigned char)val);
+                   if ((Val & 0xFF) != 0xFF) {
+                        AddCodeLine ("and #$%02X", (unsigned char)Val);
                    }
                    return;
-               } else if (val == 0xFF00) {
+               } else if (Val == 0xFF00) {
                    ldaconst (0);
                    AddCodeLine ("sta sreg+1");
                    AddCodeLine ("sta sreg");
@@ -2928,18 +2969,19 @@ void g_and (unsigned flags, unsigned long val)
                break;
 
            default:
-               typeerror (flags);
+               typeerror (Flags);
        }
 
-       /* If we go here, we didn't emit code. Push the lhs on stack and fall
-        * into the normal, non-optimized stuff.
-        */
-       g_push (flags & ~CF_CONST, 0);
-
+       /* If we go here, we didn't emit code. Push the lhs on stack and fall
+        * into the normal, non-optimized stuff. Note: The standard stuff will
+         * always work with ints.
+        */
+        Flags &= ~CF_FORCECHAR;
+               g_push (Flags & ~CF_CONST, 0);
     }
 
     /* Use long way over the stack */
-    oper (flags, val, ops);
+    oper (Flags, Val, ops);
 }
 
 
@@ -3021,10 +3063,11 @@ void g_asr (unsigned flags, unsigned long val)
        }
 
        /* If we go here, we didn't emit code. Push the lhs on stack and fall
-        * into the normal, non-optimized stuff.
+        * into the normal, non-optimized stuff. Note: The standard stuff will
+         * always work with ints.
         */
-       g_push (flags & ~CF_CONST, 0);
-
+        flags &= ~CF_FORCECHAR;
+               g_push (flags & ~CF_CONST, 0);
     }
 
     /* Use long way over the stack */
@@ -3102,11 +3145,12 @@ void g_asl (unsigned flags, unsigned long val)
                typeerror (flags);
        }
 
-       /* If we go here, we didn't emit code. Push the lhs on stack and fall
-        * into the normal, non-optimized stuff.
-        */
-       g_push (flags & ~CF_CONST, 0);
-
+       /* If we go here, we didn't emit code. Push the lhs on stack and fall
+        * into the normal, non-optimized stuff. Note: The standard stuff will
+         * always work with ints.
+        */
+        flags &= ~CF_FORCECHAR;
+               g_push (flags & ~CF_CONST, 0);
     }
 
     /* Use long way over the stack */
@@ -3115,12 +3159,20 @@ void g_asl (unsigned flags, unsigned long val)
 
 
 
-void g_neg (unsigned flags)
+void g_neg (unsigned Flags)
 /* Primary = -Primary */
 {
-    switch (flags & CF_TYPE) {
+    switch (Flags & CF_TYPE) {
 
        case CF_CHAR:
+            if (Flags & CF_FORCECHAR) {
+                AddCodeLine ("eor #$FF");
+                AddCodeLine ("clc");
+                AddCodeLine ("adc #$01");
+                return;
+            }
+            /* FALLTHROUGH */
+
        case CF_INT:
            AddCodeLine ("jsr negax");
            break;
@@ -3130,7 +3182,7 @@ void g_neg (unsigned flags)
            break;
 
        default:
-           typeerror (flags);
+           typeerror (Flags);
     }
 }
 
@@ -3160,12 +3212,18 @@ void g_bneg (unsigned flags)
 
 
 
-void g_com (unsigned flags)
+void g_com (unsigned Flags)
 /* Primary = ~Primary */
 {
-    switch (flags & CF_TYPE) {
+    switch (Flags & CF_TYPE) {
 
        case CF_CHAR:
+            if (Flags & CF_FORCECHAR) {
+                AddCodeLine ("eor #$FF");
+                return;
+            }
+            /* FALLTHROUGH */
+
        case CF_INT:
            AddCodeLine ("jsr complax");
            break;
@@ -3175,7 +3233,7 @@ void g_com (unsigned flags)
            break;
 
        default:
-           typeerror (flags);
+           typeerror (Flags);
     }
 }
 
@@ -3195,7 +3253,7 @@ void g_inc (unsigned flags, unsigned long val)
 
        case CF_CHAR:
            if (flags & CF_FORCECHAR) {
-               if (CPU == CPU_65C02 && val <= 2) {
+               if ((CPUIsets[CPU] & CPU_ISET_65SC02) != 0 && val <= 2) {
                    while (val--) {
                        AddCodeLine ("ina");
                    }
@@ -3208,7 +3266,7 @@ void g_inc (unsigned flags, unsigned long val)
            /* FALLTHROUGH */
 
        case CF_INT:
-           if (CPU == CPU_65C02 && val == 1) {
+           if ((CPUIsets[CPU] & CPU_ISET_65SC02) != 0 && val == 1) {
                unsigned L = GetLocalLabel();
                AddCodeLine ("ina");
                AddCodeLine ("bne %s", LocalLabelName (L));
@@ -3289,7 +3347,7 @@ void g_dec (unsigned flags, unsigned long val)
 
        case CF_CHAR:
            if (flags & CF_FORCECHAR) {
-               if (CPU == CPU_65C02 && val <= 2) {
+               if ((CPUIsets[CPU] & CPU_ISET_65SC02) != 0 && val <= 2) {
                    while (val--) {
                        AddCodeLine ("dea");
                    }
@@ -3498,7 +3556,8 @@ void g_lt (unsigned flags, unsigned long val)
     if (flags & CF_CONST) {
 
         /* Because the handling of the overflow flag is too complex for
-         * inlining, we can handle only unsigned compares here.
+         * inlining, we can handle only unsigned compares, and signed
+         * compares against zero here.
          */
         if (flags & CF_UNSIGNED) {
 
@@ -3548,6 +3607,34 @@ void g_lt (unsigned flags, unsigned long val)
                     typeerror (flags);
             }
 
+        } else if (val == 0) {
+
+            /* Look at the type */
+            switch (flags & CF_TYPE) {
+
+                case CF_CHAR:
+                    if (flags & CF_FORCECHAR) {
+                        AddCodeLine ("tax");
+                        AddCodeLine ("jsr boollt");
+                        return;
+                    }
+                    /* FALLTHROUGH */
+
+                case CF_INT:
+                    /* Just check the high byte */
+                    AddCodeLine ("txa");
+                    AddCodeLine ("jsr boollt");
+                    return;
+
+                case CF_LONG:
+                    /* Just check the high byte */
+                    AddCodeLine ("lda sreg+1");
+                    AddCodeLine ("jsr boollt");
+                    return;
+
+                default:
+                    typeerror (flags);
+            }
         }
 
        /* If we go here, we didn't emit code. Push the lhs on stack and fall
@@ -3833,7 +3920,8 @@ void g_ge (unsigned flags, unsigned long val)
     if (flags & CF_CONST) {
 
         /* Because the handling of the overflow flag is too complex for
-         * inlining, we can handle only unsigned compares here.
+         * inlining, we can handle only unsigned compares, and signed
+         * compares against zero here.
          */
         if (flags & CF_UNSIGNED) {
 
@@ -3883,8 +3971,37 @@ void g_ge (unsigned flags, unsigned long val)
                     typeerror (flags);
             }
 
+        } else if (val == 0) {
+
+            /* Look at the type */
+            switch (flags & CF_TYPE) {
+
+                case CF_CHAR:
+                    if (flags & CF_FORCECHAR) {
+                        AddCodeLine ("tax");
+                        AddCodeLine ("jsr boolge");
+                        return;
+                    }
+                    /* FALLTHROUGH */
+
+                case CF_INT:
+                    /* Just test the high byte */
+                    AddCodeLine ("txa");
+                    AddCodeLine ("jsr boolge");
+                    return;
+
+                case CF_LONG:
+                    /* Just test the high byte */
+                    AddCodeLine ("lda sreg+1");
+                    AddCodeLine ("jsr boolge");
+                    return;
+
+                default:
+                    typeerror (flags);
+            }
         }
 
+
        /* 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.
@@ -4164,53 +4281,3 @@ void g_asmcode (struct StrBuf* B)
 
 
 
-/*****************************************************************************/
-/*                         Inlined known functions                          */
-/*****************************************************************************/
-
-
-
-void g_strlen (unsigned flags, unsigned long val, long offs)
-/* Inline the strlen() function */
-{
-    /* We need a label in both cases */
-    unsigned label = GetLocalLabel ();
-
-    /* Two different encodings */
-    if (flags & CF_CONST) {
-
-       /* The address of the string is constant. Create the correct label name */
-       const char* lbuf = GetLabelName (flags, val, offs);
-
-       /* Generate the strlen code */
-       AddCodeLine ("ldy #$FF");
-       g_defcodelabel (label);
-       AddCodeLine ("iny");
-       AddCodeLine ("lda %s,y", lbuf);
-       AddCodeLine ("bne %s", LocalLabelName (label));
-               AddCodeLine ("tax");
-       AddCodeLine ("tya");
-
-    } else {
-
-               /* Address not constant but in primary */
-       if (CodeSizeFactor < 400) {
-           /* This is too much code, so call strlen instead of inlining */
-           AddCodeLine ("jsr _strlen");
-       } else {
-           /* Inline the function */
-           AddCodeLine ("sta ptr1");
-           AddCodeLine ("stx ptr1+1");
-           AddCodeLine ("ldy #$FF");
-           g_defcodelabel (label);
-           AddCodeLine ("iny");
-           AddCodeLine ("lda (ptr1),y");
-           AddCodeLine ("bne %s", LocalLabelName (label));
-                   AddCodeLine ("tax");
-           AddCodeLine ("tya");
-       }
-    }
-}
-
-
-