]> git.sur5r.net Git - cc65/blobdiff - src/cc65/codegen.c
Optimizations, cleanup in codegen
[cc65] / src / cc65 / codegen.c
index 898ce17fb5a6f89b8fc65b8e09bc2788055cb2ca..245a56b8e41ba14992a407bf467dcbded3092e40 100644 (file)
@@ -143,32 +143,44 @@ void g_preamble (void)
     PushSegments (0);
 
     /* Identify the compiler version */
+    AddTextLine (";");
     AddTextLine ("; File generated by cc65 v %u.%u.%u",
                 VER_MAJOR, VER_MINOR, VER_PATCH);
+    AddTextLine (";");
 
     /* Insert some object file options */
-    AddTextLine (".fopt\t\tcompiler,\"cc65 v %u.%u.%u\"",
+    AddTextLine ("\t.fopt\t\tcompiler,\"cc65 v %u.%u.%u\"",
                    VER_MAJOR, VER_MINOR, VER_PATCH);
 
     /* If we're producing code for some other CPU, switch the command set */
     if (CPU == CPU_65C02) {
-       AddTextLine (".pc02");
+       AddTextLine ("\t.pc02");
     }
 
     /* Allow auto import for runtime library routines */
-    AddTextLine (".autoimport\ton");
+    AddTextLine ("\t.autoimport\ton");
 
     /* Switch the assembler into case sensitive mode */
-    AddTextLine (".case\t\ton");
+    AddTextLine ("\t.case\t\ton");
 
     /* Tell the assembler if we want to generate debug info */
-    AddTextLine (".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 */
-    AddTextLine (".importzp\tsp, sreg, regsave, regbank, tmp1, ptr1");
+    AddTextLine ("\t.importzp\tsp, sreg, regsave, regbank, tmp1, ptr1");
 
     /* Define long branch macros */
-    AddTextLine (".macpack\tlongbranch");
+    AddTextLine ("\t.macpack\tlongbranch");
+}
+
+
+
+void g_fileinfo (const char* Name, unsigned long Size, unsigned long MTime)
+/* If debug info is enabled, place a file info into the source */
+{
+    if (DebugInfo) {
+               AddTextLine ("\t.dbg\t\tfile, \"%s\", %lu, %lu", Name, Size, MTime);
+    }
 }
 
 
@@ -203,8 +215,41 @@ void g_usebss (void)
 
 
 
+static void OutputDataLine (DataSeg* S, const char* Format, ...)
+/* Add a line to the current data segment */
+{
+    va_list ap;
+    va_start (ap, Format);
+    DS_AddLine (S, Format, ap);
+    va_end (ap);
+}
+
+
+
+void g_segname (segment_t Seg, const char* Name)
+/* Set the name of a segment */
+{
+    DataSeg* S;
+
+    /* Remember the new name */
+    NewSegName (Seg, Name);
+
+    /* Emit a segment directive for the data style segments */
+    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) {
+               OutputDataLine (S, ".segment\t\"%s\"", Name);
+    }
+}
+
+
+
 /*****************************************************************************/
-/*                                  Code                                    */
+/*                                          Code                                    */
 /*****************************************************************************/
 
 
@@ -286,7 +331,7 @@ static unsigned MakeByteOffs (unsigned Flags, unsigned Offs)
 void g_defcodelabel (unsigned label)
 /* Define a local code label */
 {
-    AddCodeLabel (CS->Code, LocalLabelName (label));
+    CS_AddLabel (CS->Code, LocalLabelName (label));
 }
 
 
@@ -525,65 +570,74 @@ void g_restore_regvars (int StackOffs, int RegOffs, unsigned Bytes)
 
 
 
-void g_getimmed (unsigned flags, unsigned long val, unsigned offs)
+void g_getimmed (unsigned Flags, unsigned long Val, unsigned Offs)
 /* Load a constant into the primary register */
 {
-    if ((flags & CF_CONST) != 0) {
+    unsigned char B1, B2, B3, B4;
+    unsigned      Done;
+
+
+    if ((Flags & CF_CONST) != 0) {
 
        /* Numeric constant */
-       switch (flags & CF_TYPE) {
+       switch (Flags & CF_TYPE) {
 
            case CF_CHAR:
-               if ((flags & CF_FORCECHAR) != 0) {
-                   ldaconst (val);
+               if ((Flags & CF_FORCECHAR) != 0) {
+                   ldaconst (Val);
                    break;
                }
                /* FALL THROUGH */
            case CF_INT:
-               ldxconst ((val >> 8) & 0xFF);
-               ldaconst (val & 0xFF);
+               ldxconst ((Val >> 8) & 0xFF);
+               ldaconst (Val & 0xFF);
                break;
 
            case CF_LONG:
-               if (val < 0x100) {
-                   AddCodeLine ("ldx #$00");
-                   AddCodeLine ("stx sreg+1");
-                   AddCodeLine ("stx sreg");
-                   AddCodeLine ("lda #$%02X", (unsigned char) val);
-               } else if ((val & 0xFFFF00FF) == 0) {
-                   AddCodeLine ("lda #$00");
-                   AddCodeLine ("sta sreg+1");
-                   AddCodeLine ("sta sreg");
-                   AddCodeLine ("ldx #$%02X", (unsigned char) (val >> 8));
-               } else if ((val & 0xFFFF0000) == 0 && CodeSizeFactor > 140) {
-                   AddCodeLine ("lda #$00");
-                   AddCodeLine ("sta sreg+1");
-                   AddCodeLine ("sta sreg");
-                   AddCodeLine ("lda #$%02X", (unsigned char) val);
-                   AddCodeLine ("ldx #$%02X", (unsigned char) (val >> 8));
-               } else if ((val & 0xFFFFFF00) == 0xFFFFFF00) {
-                   AddCodeLine ("ldx #$FF");
-                   AddCodeLine ("stx sreg+1");
-                   AddCodeLine ("stx sreg");
-                   if ((val & 0xFF) == 0xFF) {
-                       AddCodeLine ("txa");
-                   } else {
-                       AddCodeLine ("lda #$%02X", (unsigned char) val);
-                   }
-               } else if ((val & 0xFFFF00FF) == 0xFFFF00FF) {
-                   AddCodeLine ("lda #$FF");
-                   AddCodeLine ("sta sreg+1");
-                   AddCodeLine ("sta sreg");
-                   AddCodeLine ("ldx #$%02X", (unsigned char) (val >> 8));
-               } else {
-                   /* Call a subroutine that will load following value */
-                   AddCodeLine ("jsr ldeax");
-                   AddCodeLine (".dword $%08lX", val & 0xFFFFFFFF);
-               }
+               /* 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);
+               typeerror (Flags);
                break;
 
        }
@@ -591,7 +645,7 @@ void g_getimmed (unsigned flags, unsigned long val, unsigned offs)
     } else {
 
        /* Some sort of label */
-       const char* Label = GetLabelName (flags, val, offs);
+       const char* Label = GetLabelName (Flags, Val, Offs);
 
        /* Load the address into the primary */
        AddCodeLine ("lda #<(%s)", Label);
@@ -619,9 +673,10 @@ void g_getstatic (unsigned flags, unsigned long label, unsigned offs)
                AddCodeLine ("lda %s", lbuf);   /* load A from the label */
                if (!(flags & CF_UNSIGNED)) {
                    /* Must sign extend */
-                   AddCodeLine ("bpl *+3");
+                   unsigned L = GetLocalLabel ();
+                   AddCodeLine ("bpl %s", LocalLabelName (L));
                    AddCodeLine ("dex");
-                   AddCodeHint ("x:!");                /* X is invalid now */
+                   g_defcodelabel (L);
                }
            }
            break;
@@ -675,18 +730,14 @@ void g_getlocal (unsigned flags, int offs)
                    AddCodeLine ("lda (sp),y");
                }
            } else {
-               if (offs == 0) {
-                   AddCodeLine ("ldx #$00");
-                   AddCodeLine ("lda (sp,x)");
-               } else {
-                   ldyconst (offs);
-                   AddCodeLine ("ldx #$00");
-                   AddCodeLine ("lda (sp),y");
-               }
+               ldyconst (offs);
+               AddCodeLine ("ldx #$00");
+               AddCodeLine ("lda (sp),y");
                if ((flags & CF_UNSIGNED) == 0) {
-                   AddCodeLine ("bpl *+3");
+                   unsigned L = GetLocalLabel();
+                   AddCodeLine ("bpl %s", LocalLabelName (L));
                    AddCodeLine ("dex");
-                   AddCodeHint ("x:!");        /* X is invalid now */
+                   g_defcodelabel (L);
                }
            }
            break;
@@ -748,32 +799,18 @@ void g_getind (unsigned flags, unsigned offs)
 
        case CF_CHAR:
                    /* Character sized */
-           if (offs) {
-               ldyconst (offs);
-               if (flags & CF_UNSIGNED) {
-                   AddCodeLine ("jsr ldauidx");
-                       } else {
-                   AddCodeLine ("jsr ldaidx");
-               }
-           } else {
-               if (flags & CF_UNSIGNED) {
-                   if (CodeSizeFactor > 250) {
-                       AddCodeLine ("sta ptr1");
-                       AddCodeLine ("stx ptr1+1");
-                       AddCodeLine ("ldx #$00");
-                       AddCodeLine ("lda (ptr1,x)");
-                   } else {
-                       AddCodeLine ("jsr ldaui");
-                   }
-               } else {
-                           AddCodeLine ("jsr ldai");
-               }
-                   }
+           if (flags & CF_UNSIGNED) {
+               ldyconst (offs);
+               AddCodeLine ("jsr ldauidx");
+           } else {
+               ldyconst (offs);
+               AddCodeLine ("jsr ldaidx");
+           }
            break;
 
        case CF_INT:
            if (flags & CF_TEST) {
-               ldyconst (offs);
+               ldyconst (offs);
                AddCodeLine ("sta ptr1");
                AddCodeLine ("stx ptr1+1");
                AddCodeLine ("lda (ptr1),y");
@@ -824,22 +861,22 @@ void g_leasp (int offs)
                    ldaconst (offs);                    /* Load A with offset value */
                    AddCodeLine ("jsr leaasp"); /* Load effective address */
                } else {
+           unsigned L = GetLocalLabel ();
                    if (CPU == CPU_65C02 && offs == 1) {
                        AddCodeLine ("lda sp");
                        AddCodeLine ("ldx sp+1");
                        AddCodeLine ("ina");
-                       AddCodeLine ("bne *+3");
+                       AddCodeLine ("bne %s", LocalLabelName (L));
                        AddCodeLine ("inx");
-                       AddCodeHint ("x:!");            /* Invalidate X */
                    } else {
                        ldaconst (offs);
                        AddCodeLine ("clc");
                        AddCodeLine ("ldx sp+1");
                        AddCodeLine ("adc sp");
-                       AddCodeLine ("bcc *+3");
+                       AddCodeLine ("bcc %s", LocalLabelName (L));
                        AddCodeLine ("inx");
-                       AddCodeHint ("x:!");            /* Invalidate X */
                    }
+           g_defcodelabel (L);
                }
     }
 }
@@ -873,12 +910,13 @@ void g_leavariadic (int Offs)
 
     /* Add the value of the stackpointer */
     if (CodeSizeFactor > 250) {
+       unsigned L = GetLocalLabel();
                AddCodeLine ("ldx sp+1");
                AddCodeLine ("clc");
                AddCodeLine ("adc sp");
-               AddCodeLine ("bcc *+3");
+               AddCodeLine ("bcc %s", LocalLabelName (L));
                AddCodeLine ("inx");
-               AddCodeHint ("x:!");            /* Invalidate X */
+       g_defcodelabel (L);
     } else {
                AddCodeLine ("jsr leaasp");
     }
@@ -1068,12 +1106,8 @@ void g_putind (unsigned Flags, unsigned Offs)
     switch (Flags & CF_TYPE) {
 
        case CF_CHAR:
-           if (Offs) {
-               ldyconst (Offs);
-               AddCodeLine ("jsr staspidx");
-           } else {
-               AddCodeLine ("jsr staspp");
-           }
+           ldyconst (Offs);
+           AddCodeLine ("jsr staspidx");
            break;
 
        case CF_INT:
@@ -1286,9 +1320,9 @@ void g_scale (unsigned flags, long val)
     } else if (val > 0) {
 
        /* Scale up */
-       if ((p2 = powerof2 (val)) > 0 && p2 <= 3) {
+       if ((p2 = powerof2 (val)) > 0 && p2 <= 4) {
 
-           /* Factor is 2, 4 or 8, use special function */
+                   /* Factor is 2, 4, 8 and 16, use special function */
            switch (flags & CF_TYPE) {
 
                case CF_CHAR:
@@ -1301,11 +1335,11 @@ void g_scale (unsigned flags, long val)
                    /* FALLTHROUGH */
 
                case CF_INT:
-                   if (CodeSizeFactor >= (p2+1)*130U) {
+                   if (CodeSizeFactor >= (p2+1)*130U) {
                        AddCodeLine ("stx tmp1");
                        while (p2--) {
                            AddCodeLine ("asl a");
-                           AddCodeLine ("rol tmp1");
+                           AddCodeLine ("rol tmp1");
                        }
                        AddCodeLine ("ldx tmp1");
                    } else {
@@ -1341,9 +1375,9 @@ void g_scale (unsigned flags, long val)
 
        /* Scale down */
        val = -val;
-       if ((p2 = powerof2 (val)) > 0 && p2 <= 3) {
+       if ((p2 = powerof2 (val)) > 0 && p2 <= 4) {
 
-           /* Factor is 2, 4 or 8, use special function */
+           /* Factor is 2, 4, 8 and 16 use special function */
            switch (flags & CF_TYPE) {
 
                case CF_CHAR:
@@ -1421,6 +1455,8 @@ 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;
     CheckLocalOffs (offs);
@@ -1428,12 +1464,13 @@ void g_addlocal (unsigned flags, int offs)
     switch (flags & CF_TYPE) {
 
        case CF_CHAR:
+           L = GetLocalLabel();
            AddCodeLine ("ldy #$%02X", offs & 0xFF);
            AddCodeLine ("clc");
            AddCodeLine ("adc (sp),y");
-           AddCodeLine ("bcc *+3");
+           AddCodeLine ("bcc %s", LocalLabelName (L));
            AddCodeLine ("inx");
-           AddCodeHint ("x:!");
+           g_defcodelabel (L);
            break;
 
        case CF_INT:
@@ -1466,17 +1503,20 @@ void g_addlocal (unsigned flags, int offs)
 void g_addstatic (unsigned flags, unsigned long label, unsigned offs)
 /* Add a static variable to ax */
 {
+    unsigned L;
+
     /* Create the correct label name */
     char* lbuf = GetLabelName (flags, label, offs);
 
     switch (flags & CF_TYPE) {
 
        case CF_CHAR:
+           L = GetLocalLabel();
            AddCodeLine ("clc");
            AddCodeLine ("adc %s", lbuf);
-           AddCodeLine ("bcc *+3");
+           AddCodeLine ("bcc %s", LocalLabelName (L));
            AddCodeLine ("inx");
-           AddCodeHint ("x:!");
+           g_defcodelabel (L);
            break;
 
        case CF_INT:
@@ -1561,9 +1601,10 @@ void g_addeqstatic (unsigned flags, unsigned long label, unsigned offs,
                    AddCodeLine ("sta %s", lbuf);
                        }
                if ((flags & CF_UNSIGNED) == 0) {
-                   AddCodeLine ("bpl *+3");
+                   unsigned L = GetLocalLabel();
+                   AddCodeLine ("bpl %s", LocalLabelName (L));
                    AddCodeLine ("dex");
-                   AddCodeHint ("x:!");                /* Invalidate X */
+                   g_defcodelabel (L);
                }
                        break;
                    }
@@ -1654,36 +1695,23 @@ void g_addeqlocal (unsigned flags, int offs, unsigned long val)
 
                case CF_CHAR:
                    if (flags & CF_FORCECHAR) {
-                       if (offs == 0) {
-                           AddCodeLine ("ldx #$00");
-                           if (flags & CF_CONST) {
-                               AddCodeLine ("clc");
-                               AddCodeLine ("lda #$%02X", (int)(val & 0xFF));
-                               AddCodeLine ("adc (sp,x)");
-                               AddCodeLine ("sta (sp,x)");
-                           } else {
-                               AddCodeLine ("clc");
-                               AddCodeLine ("adc (sp,x)");
-                               AddCodeLine ("sta (sp,x)");
-                           }
-                       } else {
-                           ldyconst (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");
-                   }
-               }
+               ldyconst (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) {
-                   AddCodeLine ("bpl *+3");
+                   unsigned L = GetLocalLabel();
+                   AddCodeLine ("bpl %s", LocalLabelName (L));
                    AddCodeLine ("dex");
-                   AddCodeHint ("x:!");        /* Invalidate X */
+                   g_defcodelabel (L);
                }
                        break;
                    }
@@ -1735,20 +1763,12 @@ void g_addeqind (unsigned flags, unsigned offs, unsigned long val)
                case CF_CHAR:
            AddCodeLine ("sta ptr1");
            AddCodeLine ("stx ptr1+1");
-           if (offs == 0) {
-               AddCodeLine ("ldx #$00");
-               AddCodeLine ("lda #$%02X", (int)(val & 0xFF));
-               AddCodeLine ("clc");
-               AddCodeLine ("adc (ptr1,x)");
-               AddCodeLine ("sta (ptr1,x)");
-           } else {
-               AddCodeLine ("ldy #$%02X", offs);
-                       AddCodeLine ("ldx #$00");
-                       AddCodeLine ("lda #$%02X", (int)(val & 0xFF));
-                       AddCodeLine ("clc");
-                       AddCodeLine ("adc (ptr1),y");
-                       AddCodeLine ("sta (ptr1),y");
-           }
+           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:
@@ -1818,9 +1838,10 @@ void g_subeqstatic (unsigned flags, unsigned long label, unsigned offs,
                            AddCodeLine ("sta %s", lbuf);
                        }
                        if ((flags & CF_UNSIGNED) == 0) {
-                           AddCodeLine ("bpl *+3");
+                   unsigned L = GetLocalLabel();
+                           AddCodeLine ("bpl %s", LocalLabelName (L));
                            AddCodeLine ("dex");
-                           AddCodeHint ("x:!");                /* Invalidate X */
+                   g_defcodelabel (L);
                        }
                        break;
                    }
@@ -1916,9 +1937,10 @@ void g_subeqlocal (unsigned flags, int offs, unsigned long val)
                }
                        AddCodeLine ("sta (sp),y");
                if ((flags & CF_UNSIGNED) == 0) {
-                   AddCodeLine ("bpl *+3");
+                   unsigned L = GetLocalLabel();
+                   AddCodeLine ("bpl %s", LocalLabelName (L));
                    AddCodeLine ("dex");
-                   AddCodeHint ("x:!");                /* Invalidate X */
+                   g_defcodelabel (L);
                }
                        break;
                    }
@@ -1970,20 +1992,12 @@ void g_subeqind (unsigned flags, unsigned offs, unsigned long val)
                case CF_CHAR:
            AddCodeLine ("sta ptr1");
            AddCodeLine ("stx ptr1+1");
-           if (offs == 0) {
-               AddCodeLine ("ldx #$00");
-               AddCodeLine ("lda (ptr1,x)");
-                       AddCodeLine ("sec");
-               AddCodeLine ("sbc #$%02X", (unsigned char)val);
-               AddCodeLine ("sta (ptr1,x)");
-           } else {
-                       AddCodeLine ("ldy #$%02X", offs);
-               AddCodeLine ("ldx #$00");
-               AddCodeLine ("lda (ptr1),y");
-               AddCodeLine ("sec");
-               AddCodeLine ("sbc #$%02X", (unsigned char)val);
-               AddCodeLine ("sta (ptr1),y");
-           }
+           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:
@@ -2031,20 +2045,27 @@ void g_subeqind (unsigned flags, unsigned offs, unsigned long val)
 void g_addaddr_local (unsigned flags, int offs)
 /* Add the address of a local variable to ax */
 {
+    unsigned L = 0;
+
     /* Add the offset */
     offs -= oursp;
     if (offs != 0) {
        /* We cannot address more then 256 bytes of locals anyway */
+       L = GetLocalLabel();
        CheckLocalOffs (offs);
        AddCodeLine ("clc");
        AddCodeLine ("adc #$%02X", offs & 0xFF);
-               AddCodeLine ("bcc *+4");        /* Do also skip the CLC insn below */
+       /* Do also skip the CLC insn below */
+               AddCodeLine ("bcc %s", LocalLabelName (L));
        AddCodeLine ("inx");
-       AddCodeHint ("x:!");                    /* Invalidate X */
     }
 
     /* Add the current stackpointer value */
     AddCodeLine ("clc");
+    if (L != 0) {
+       /* Label was used above */
+       g_defcodelabel (L);
+    }
     AddCodeLine ("adc sp");
     AddCodeLine ("tay");
     AddCodeLine ("txa");
@@ -2142,20 +2163,24 @@ void g_cmp (unsigned flags, unsigned long val)
  * will be set.
  */
 {
+    unsigned L;
+
     /* Check the size and determine operation */
     switch (flags & CF_TYPE) {
 
        case CF_CHAR:
            if (flags & CF_FORCECHAR) {
                AddCodeLine ("cmp #$%02X", (unsigned char)val);
-               break;
+               break;
            }
            /* FALLTHROUGH */
 
        case CF_INT:
+           L = GetLocalLabel();
            AddCodeLine ("cmp #$%02X", (unsigned char)val);
-                   AddCodeLine ("bne *+4");
+                   AddCodeLine ("bne %s", LocalLabelName (L));
            AddCodeLine ("cpx #$%02X", (unsigned char)(val >> 8));
+           g_defcodelabel (L);
            break;
 
         case CF_LONG:
@@ -2915,7 +2940,7 @@ void g_asr (unsigned flags, unsigned long val)
 
            case CF_CHAR:
            case CF_INT:
-               if (val >= 1 && val <= 3) {
+               if (val >= 1 && val <= 4) {
                    if (flags & CF_UNSIGNED) {
                        AddCodeLine ("jsr shrax%ld", val);
                    } else {
@@ -2930,7 +2955,7 @@ void g_asr (unsigned flags, unsigned long val)
                break;
 
            case CF_LONG:
-               if (val >= 1 && val <= 3) {
+               if (val >= 1 && val <= 4) {
                    if (flags & CF_UNSIGNED) {
                        AddCodeLine ("jsr shreax%ld", val);
                    } else {
@@ -2949,9 +2974,10 @@ void g_asr (unsigned flags, unsigned long val)
                    AddCodeLine ("ldy #$00");
                    AddCodeLine ("ldx sreg+1");
                    if ((flags & CF_UNSIGNED) == 0) {
-                       AddCodeLine ("bpl *+3");
+                       unsigned L = GetLocalLabel();
+                       AddCodeLine ("bpl %s", LocalLabelName (L));
                        AddCodeLine ("dey");
-                       AddCodeHint ("y:!");
+                       g_defcodelabel (L);
                    }
                    AddCodeLine ("lda sreg");
                    AddCodeLine ("sty sreg+1");
@@ -2997,7 +3023,7 @@ void g_asl (unsigned flags, unsigned long val)
 
            case CF_CHAR:
            case CF_INT:
-               if (val >= 1 && val <= 3) {
+               if (val >= 1 && val <= 4) {
                    if (flags & CF_UNSIGNED) {
                        AddCodeLine ("jsr shlax%ld", val);
                    } else {
@@ -3012,7 +3038,7 @@ void g_asl (unsigned flags, unsigned long val)
                break;
 
            case CF_LONG:
-               if (val >= 1 && val <= 3) {
+               if (val >= 1 && val <= 4) {
                    if (flags & CF_UNSIGNED) {
                        AddCodeLine ("jsr shleax%ld", val);
                    } else {
@@ -3146,11 +3172,11 @@ void g_inc (unsigned flags, unsigned long val)
 
        case CF_INT:
            if (CPU == CPU_65C02 && val == 1) {
+               unsigned L = GetLocalLabel();
                AddCodeLine ("ina");
-               AddCodeLine ("bne *+3");
+               AddCodeLine ("bne %s", LocalLabelName (L));
                AddCodeLine ("inx");
-               /* Tell the optimizer that the X register may be invalid */
-               AddCodeHint ("x:!");
+               g_defcodelabel (L);
            } else if (CodeSizeFactor < 200) {
                /* Use jsr calls */
                if (val <= 8) {
@@ -3165,12 +3191,12 @@ void g_inc (unsigned flags, unsigned long val)
                /* Inline the code */
                if (val < 0x300) {
                    if ((val & 0xFF) != 0) {
+                       unsigned L = GetLocalLabel();
                        AddCodeLine ("clc");
                        AddCodeLine ("adc #$%02X", (unsigned char) val);
-                       AddCodeLine ("bcc *+3");
+                       AddCodeLine ("bcc %s", LocalLabelName (L));
                        AddCodeLine ("inx");
-                       /* Tell the optimizer that the X register may be invalid */
-                               AddCodeHint ("x:!");
+                       g_defcodelabel (L);
                    }
                    if (val >= 0x100) {
                        AddCodeLine ("inx");
@@ -3182,8 +3208,6 @@ void g_inc (unsigned flags, unsigned long val)
                    AddCodeLine ("clc");
                    if ((val & 0xFF) != 0) {
                        AddCodeLine ("adc #$%02X", (unsigned char) val);
-                       /* Tell the optimizer that the X register may be invalid */
-                       AddCodeHint ("x:!");
                    }
                    AddCodeLine ("pha");
                    AddCodeLine ("txa");
@@ -3252,12 +3276,12 @@ void g_dec (unsigned flags, unsigned long val)
                /* Inline the code */
                if (val < 0x300) {
                    if ((val & 0xFF) != 0) {
+                       unsigned L = GetLocalLabel();
                        AddCodeLine ("sec");
                        AddCodeLine ("sbc #$%02X", (unsigned char) val);
-                       AddCodeLine ("bcs *+3");
+                       AddCodeLine ("bcs %s", LocalLabelName (L));
                        AddCodeLine ("dex");
-                       /* Tell the optimizer that the X register may be invalid */
-                               AddCodeHint ("x:!");
+                       g_defcodelabel (L);
                    }
                    if (val >= 0x100) {
                        AddCodeLine ("dex");
@@ -3269,8 +3293,6 @@ void g_dec (unsigned flags, unsigned long val)
                    AddCodeLine ("sec");
                    if ((val & 0xFF) != 0) {
                        AddCodeLine ("sbc #$%02X", (unsigned char) val);
-                       /* Tell the optimizer that the X register may be invalid */
-                       AddCodeHint ("x:!");
                    }
                    AddCodeLine ("pha");
                    AddCodeLine ("txa");
@@ -3312,10 +3334,12 @@ void g_eq (unsigned flags, unsigned long val)
     static char* ops [12] = {
        "toseq00",      "toseqa0",      "toseqax",
        "toseq00",      "toseqa0",      "toseqax",
-       0,              0,              "toseqeax",
-       0,              0,              "toseqeax",
+       0,              0,              "toseqeax",
+       0,              0,              "toseqeax",
     };
 
+    unsigned L;
+
     /* If the right hand side is const, the lhs is not on stack but still
      * in the primary register.
      */
@@ -3332,9 +3356,11 @@ void g_eq (unsigned flags, unsigned long val)
                /* FALLTHROUGH */
 
            case CF_INT:
+               L = GetLocalLabel();
                AddCodeLine ("cpx #$%02X", (unsigned char)(val >> 8));
-                       AddCodeLine ("bne *+4");
+                       AddCodeLine ("bne %s", LocalLabelName (L));
                AddCodeLine ("cmp #$%02X", (unsigned char)val);
+               g_defcodelabel (L);
                AddCodeLine ("jsr booleq");
                return;
 
@@ -3368,6 +3394,7 @@ void g_ne (unsigned flags, unsigned long val)
        0,              0,              "tosneeax",
     };
 
+    unsigned L;
 
     /* If the right hand side is const, the lhs is not on stack but still
      * in the primary register.
@@ -3385,9 +3412,11 @@ void g_ne (unsigned flags, unsigned long val)
                /* FALLTHROUGH */
 
            case CF_INT:
+               L = GetLocalLabel();
                AddCodeLine ("cpx #$%02X", (unsigned char)(val >> 8));
-               AddCodeLine ("bne *+4");
+               AddCodeLine ("bne %s", LocalLabelName (L));
                AddCodeLine ("cmp #$%02X", (unsigned char)val);
+               g_defcodelabel (L);
                AddCodeLine ("jsr boolne");
                return;
 
@@ -3415,10 +3444,10 @@ 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",
+       "toslt00",      "toslta0",      "tosltax",
+       "tosult00",     "tosulta0",     "tosultax",
+       0,              0,              "toslteax",
+       0,              0,              "tosulteax",
     };
 
     /* If the right hand side is const, the lhs is not on stack but still
@@ -3435,31 +3464,33 @@ void g_lt (unsigned flags, unsigned long val)
        switch (flags & CF_TYPE) {
 
            case CF_CHAR:
-               if (flags & CF_FORCECHAR) {
-                   AddCodeLine ("cmp #$%02X", (unsigned char)val);
-                   if (flags & CF_UNSIGNED) {
-                       AddCodeLine ("jsr boolult");
-                   } else {
-                       AddCodeLine ("jsr boollt");
-                   }
-                   return;
-               }
-               /* FALLTHROUGH */
+               if (flags & CF_FORCECHAR) {
+                   AddCodeLine ("cmp #$%02X", (unsigned char)val);
+                   if (flags & CF_UNSIGNED) {
+                       AddCodeLine ("jsr boolult");
+                   } else {
+                       AddCodeLine ("jsr boollt");
+                   }
+                   return;
+               }
+               /* FALLTHROUGH */
 
            case CF_INT:
-               if ((flags & CF_UNSIGNED) == 0 && val == 0) {
-                   /* If we have a signed compare against zero, we only need to
-                    * test the high byte.
-                    */
-                   AddCodeLine ("txa");
-                   AddCodeLine ("jsr boollt");
-                   return;
-               }
-               /* Direct code only for unsigned data types */
-               if (flags & CF_UNSIGNED) {
-                   AddCodeLine ("cpx #$%02X", (unsigned char)(val >> 8));
-                           AddCodeLine ("bne *+4");
-                   AddCodeLine ("cmp #$%02X", (unsigned char)val);
+               if ((flags & CF_UNSIGNED) == 0 && val == 0) {
+                   /* If we have a signed compare against zero, we only need to
+                    * test the high byte.
+                    */
+                   AddCodeLine ("txa");
+                   AddCodeLine ("jsr boollt");
+                   return;
+               }
+               /* Direct code only for unsigned data types */
+               if (flags & CF_UNSIGNED) {
+                   unsigned L = GetLocalLabel();
+                   AddCodeLine ("cpx #$%02X", (unsigned char)(val >> 8));
+                           AddCodeLine ("bne %s", LocalLabelName (L));
+                   AddCodeLine ("cmp #$%02X", (unsigned char)val);
+                   g_defcodelabel (L);
                    AddCodeLine ("jsr boolult");
                    return;
                }
@@ -3483,7 +3514,7 @@ void g_lt (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.
         */
-       g_push (flags & ~CF_CONST, 0);      
+       g_push (flags & ~CF_CONST, 0);
 
     }
 
@@ -3509,16 +3540,31 @@ 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) {
-                   AddCodeLine ("cmp #$%02X", (unsigned char)val);
-                   if (flags & CF_UNSIGNED) {
-                       AddCodeLine ("jsr boolule");
-                   } else {
-                       AddCodeLine ("jsr boolle");
+           case CF_CHAR:
+               if (flags & CF_FORCECHAR) {
+                   if (flags & CF_UNSIGNED) {
+                       if (val < 255) {
+                           AddCodeLine ("cmp #$%02X", (unsigned char)val+1);
+                           AddCodeLine ("jsr boolult");
+                       } else {
+                           AddCodeLine ("cmp #$%02X", (unsigned char)val);
+                           AddCodeLine ("jsr boolule");
+                       }
+                   } else {
+                       if (val < 127) {
+                           AddCodeLine ("cmp #$%02X", (unsigned char)val+1);
+                           AddCodeLine ("jsr boollt");
+                       } else {
+                           AddCodeLine ("cmp #$%02X", (unsigned char)val);
+                           AddCodeLine ("jsr boolle");
+                       }
                    }
                    return;
                }
@@ -3526,10 +3572,17 @@ 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";
+                   }
                    AddCodeLine ("cpx #$%02X", (unsigned char)(val >> 8));
-                           AddCodeLine ("bne *+4");
-                   AddCodeLine ("cmp #$%02X", (unsigned char)val);
-                   AddCodeLine ("jsr boolule");
+                   AddCodeLine ("bne %s", LocalLabelName (L));
+                   AddCodeLine ("cmp #$%02X", (unsigned char)val);
+                   g_defcodelabel (L);
+                   AddCodeLine ("jsr %s", Name);
                    return;
                }
                break;
@@ -3558,10 +3611,10 @@ 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",
+       "tosgt00",      "tosgta0",      "tosgtax",
+       "tosugt00",     "tosugta0",     "tosugtax",
+       0,              0,              "tosgteax",
+       0,              0,              "tosugteax",
     };
 
 
@@ -3570,44 +3623,65 @@ 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) {
-                   AddCodeLine ("cmp #$%02X", (unsigned char)val);
-                   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 ("jsr boolugt");
-                       } else {
-                           AddCodeLine ("jsr boolne");
-                       }
-                   } else {
-                       AddCodeLine ("jsr boolgt");
-                   }
-                   return;
-               }
-               /* FALLTHROUGH */
+           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");
+                       } else {
+                           AddCodeLine ("cmp #$%02X", (unsigned char)val);
+                           AddCodeLine ("jsr boolugt");
+                       }
+                   } else {
+                       if (val < 127) {
+                           AddCodeLine ("cmp #$%02X", (unsigned char)val+1);
+                           AddCodeLine ("jsr boolge");
+                       } else {
+                           AddCodeLine ("cmp #$%02X", (unsigned char)val);
+                           AddCodeLine ("jsr boolgt");
+                       }
+                   }
+                   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.
+           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 ("stx tmp1");
-                       AddCodeLine ("ora tmp1");
-                       AddCodeLine ("jsr boolne");
+                   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 *+4");
-                       AddCodeLine ("cmp #$%02X", (unsigned char)val);
-                               AddCodeLine ("jsr boolugt");
+                       AddCodeLine ("bne %s", LocalLabelName (L));
+                       AddCodeLine ("cmp #$%02X", (unsigned char)val);
+                       g_defcodelabel (L);
+                               AddCodeLine ("jsr %s", Name);
                    }
                    return;
                        }
@@ -3680,9 +3754,11 @@ void g_ge (unsigned flags, unsigned long val)
                }
                /* Direct code only for unsigned data types */
                if (flags & CF_UNSIGNED) {
+                   unsigned L = GetLocalLabel();
                            AddCodeLine ("cpx #$%02X", (unsigned char)(val >> 8));
-                           AddCodeLine ("bne *+4");
+                           AddCodeLine ("bne %s", LocalLabelName (L));
                    AddCodeLine ("cmp #$%02X", (unsigned char)val);
+                   g_defcodelabel (L);
                    AddCodeLine ("jsr booluge");
                    return;
                }