]> git.sur5r.net Git - cc65/blobdiff - src/cc65/codegen.c
Changed code generated for compares. Fixed bugs in OptStackOps. Still
[cc65] / src / cc65 / codegen.c
index 18b1f319e82d0f61444302e7064073a4666f66f2..e8573dca22fc812daa76d82333d8ea67f0a79397 100644 (file)
 static void typeerror (unsigned type)
 /* Print an error message about an invalid operand type */
 {
-    Internal ("Invalid type in CF flags: %04X, type = %u", type, type & CF_TYPE);
+    /* Special handling for floats here: */
+    if ((type & CF_TYPE) == CF_FLOAT) {
+        Fatal ("Floating point type is currently unsupported");
+    } else {
+        Internal ("Invalid type in CF flags: %04X, type = %u", type, type & CF_TYPE);
+    }
 }
 
 
@@ -940,8 +945,8 @@ void g_leasp (int offs)
                AddCodeLine ("inx");
             } else {
                ldaconst (offs);
-               AddCodeLine ("clc");
                AddCodeLine ("ldx sp+1");
+               AddCodeLine ("clc");
                AddCodeLine ("adc sp");
                AddCodeLine ("bcc %s", LocalLabelName (L));
                AddCodeLine ("inx");
@@ -1885,8 +1890,8 @@ void g_subeqstatic (unsigned flags, unsigned long label, long offs,
                         AddCodeLine ("dec %s", lbuf);
                         AddCodeLine ("lda %s", lbuf);
                     } else {
-                               AddCodeLine ("sec");
                        AddCodeLine ("lda %s", lbuf);
+                               AddCodeLine ("sec");
                        AddCodeLine ("sbc #$%02X", (int)(val & 0xFF));
                        AddCodeLine ("sta %s", lbuf);
                     }
@@ -1907,9 +1912,9 @@ void g_subeqstatic (unsigned flags, unsigned long label, long offs,
             /* FALLTHROUGH */
 
         case CF_INT:
-            AddCodeLine ("sec");
             if (flags & CF_CONST) {
                        AddCodeLine ("lda %s", lbuf);
+                AddCodeLine ("sec");
                AddCodeLine ("sbc #$%02X", (unsigned char)val);
                AddCodeLine ("sta %s", lbuf);
                if (val < 0x100) {
@@ -1927,6 +1932,7 @@ void g_subeqstatic (unsigned flags, unsigned long label, long offs,
                 }
             } else {
                 AddCodeLine ("eor #$FF");
+                AddCodeLine ("sec");
                        AddCodeLine ("adc %s", lbuf);
                 AddCodeLine ("sta %s", lbuf);
                 AddCodeLine ("txa");
@@ -1980,12 +1986,13 @@ void g_subeqlocal (unsigned flags, int offs, unsigned long val)
             if (flags & CF_FORCECHAR) {
                ldyconst (offs);
                 AddCodeLine ("ldx #$00");
-               AddCodeLine ("sec");
                 if (flags & CF_CONST) {
                     AddCodeLine ("lda (sp),y");
+                    AddCodeLine ("sec");
                     AddCodeLine ("sbc #$%02X", (unsigned char)val);
                 } else {
                     AddCodeLine ("eor #$FF");
+                    AddCodeLine ("sec");
                    AddCodeLine ("adc (sp),y");
                 }
                AddCodeLine ("sta (sp),y");
@@ -2964,7 +2971,7 @@ void g_asr (unsigned flags, unsigned long val)
                     }
                     return;
                 } else if (val == 8 && (flags & CF_UNSIGNED)) {
-                    AddCodeLine ("txa");  
+                    AddCodeLine ("txa");
                     AddCodeLine ("ldx sreg");
                     AddCodeLine ("ldy sreg+1");
                     AddCodeLine ("sty sreg");
@@ -3228,16 +3235,21 @@ void g_inc (unsigned flags, unsigned long val)
                     if (val >= 0x300) {
                                AddCodeLine ("inx");
                     }
-                } else {
+                } else if ((val & 0xFF) != 0) {
                     AddCodeLine ("clc");
-                    if ((val & 0xFF) != 0) {
-                       AddCodeLine ("adc #$%02X", (unsigned char) val);
-                    }
+                    AddCodeLine ("adc #$%02X", (unsigned char) val);
                     AddCodeLine ("pha");
                     AddCodeLine ("txa");
                     AddCodeLine ("adc #$%02X", (unsigned char) (val >> 8));
                     AddCodeLine ("tax");
                     AddCodeLine ("pla");
+                } else {
+                    AddCodeLine ("pha");
+                    AddCodeLine ("txa");
+                    AddCodeLine ("clc");
+                    AddCodeLine ("adc #$%02X", (unsigned char) (val >> 8));
+                    AddCodeLine ("tax");
+                    AddCodeLine ("pla");
                 }
             }
             break;
@@ -3314,15 +3326,22 @@ void g_dec (unsigned flags, unsigned long val)
                                AddCodeLine ("dex");
                     }
                 } else {
-                    AddCodeLine ("sec");
                     if ((val & 0xFF) != 0) {
+                        AddCodeLine ("sec");
                        AddCodeLine ("sbc #$%02X", (unsigned char) val);
+                        AddCodeLine ("pha");
+                        AddCodeLine ("txa");
+                        AddCodeLine ("sbc #$%02X", (unsigned char) (val >> 8));
+                        AddCodeLine ("tax");
+                        AddCodeLine ("pla");
+                    } else {
+                        AddCodeLine ("pha");
+                        AddCodeLine ("txa");
+                        AddCodeLine ("sec");
+                        AddCodeLine ("sbc #$%02X", (unsigned char) (val >> 8));
+                        AddCodeLine ("tax");
+                        AddCodeLine ("pla");
                     }
-                    AddCodeLine ("pha");
-                    AddCodeLine ("txa");
-                    AddCodeLine ("sbc #$%02X", (unsigned char) (val >> 8));
-                    AddCodeLine ("tax");
-                    AddCodeLine ("pla");
                 }
             }
             break;
@@ -3467,6 +3486,8 @@ void g_lt (unsigned flags, unsigned long val)
         "tosltax", "tosultax", "toslteax", "tosulteax",
     };
 
+    unsigned Label;
+
     /* If the right hand side is const, the lhs is not on stack but still
      * in the primary register.
      */
@@ -3526,32 +3547,84 @@ void g_lt (unsigned flags, unsigned long val)
 
         } else if (val == 0) {
 
-            /* Look at the type */
+            /* A signed compare against zero must only look at the sign bit */
             switch (flags & CF_TYPE) {
 
                 case CF_CHAR:
                     if (flags & CF_FORCECHAR) {
-                        AddCodeLine ("tax");
-                        AddCodeLine ("jsr boollt");
+                        AddCodeLine ("asl a");          /* Bit 7 -> carry */
+                        AddCodeLine ("lda #$00");
+                        AddCodeLine ("ldx #$00");
+                        AddCodeLine ("rol a");
                         return;
                     }
                     /* FALLTHROUGH */
 
                 case CF_INT:
                     /* Just check the high byte */
-                    AddCodeLine ("txa");
-                    AddCodeLine ("jsr boollt");
+                    AddCodeLine ("cpx #$80");           /* Bit 7 -> carry */
+                    AddCodeLine ("lda #$00");
+                    AddCodeLine ("ldx #$00");
+                    AddCodeLine ("rol a");
                     return;
 
                 case CF_LONG:
                     /* Just check the high byte */
                     AddCodeLine ("lda sreg+1");
-                    AddCodeLine ("jsr boollt");
+                    AddCodeLine ("asl a");              /* Bit 7 -> carry */
+                    AddCodeLine ("lda #$00");
+                    AddCodeLine ("ldx #$00");
+                    AddCodeLine ("rol a");
+                    return;
+
+                default:
+                    typeerror (flags);
+            }
+
+        } else {
+
+            /* Signed compare against a constant != zero */
+            switch (flags & CF_TYPE) {
+
+                case CF_CHAR:
+                    if (flags & CF_FORCECHAR) {
+                        Label = GetLocalLabel ();
+                        AddCodeLine ("sec");
+                        AddCodeLine ("sbc #$%02X", (unsigned char)val);
+                        AddCodeLine ("bvc %s", LocalLabelName (Label));
+                        AddCodeLine ("eor #$80");
+                        g_defcodelabel (Label);
+                        AddCodeLine ("asl a");          /* Bit 7 -> carry */
+                        AddCodeLine ("lda #$00");
+                        AddCodeLine ("ldx #$00");
+                        AddCodeLine ("rol a");
+                        return;
+                    }
+                    /* FALLTHROUGH */
+
+                case CF_INT:
+                    /* Do a subtraction */
+                    Label = GetLocalLabel ();
+                    AddCodeLine ("cmp #$%02X", (unsigned char)val);
+                    AddCodeLine ("txa");
+                    AddCodeLine ("sbc #$%02X", (unsigned char)(val >> 8));
+                    AddCodeLine ("bvc %s", LocalLabelName (Label));
+                    AddCodeLine ("eor #$80");
+                    g_defcodelabel (Label);
+                    AddCodeLine ("asl a");          /* Bit 7 -> carry */
+                    AddCodeLine ("lda #$00");
+                    AddCodeLine ("ldx #$00");
+                    AddCodeLine ("rol a");
                     return;
 
+                case CF_LONG:
+                    /* This one is too costly */
+                    break;
+
                 default:
                     typeerror (flags);
             }
+
         }
 
         /* If we go here, we didn't emit code. Push the lhs on stack and fall
@@ -3821,6 +3894,8 @@ void g_ge (unsigned flags, unsigned long val)
         "tosgeax", "tosugeax", "tosgeeax", "tosugeeax",
     };
 
+    unsigned Label;
+
 
     /* If the right hand side is const, the lhs is not on stack but still
      * in the primary register.
@@ -3845,26 +3920,27 @@ void g_ge (unsigned flags, unsigned long val)
 
                 case CF_CHAR:
                     if (flags & CF_FORCECHAR) {
+                        /* Do a subtraction. Condition is true if carry set */
                         AddCodeLine ("cmp #$%02X", (unsigned char)val);
-                        AddCodeLine ("jsr booluge");
+                        AddCodeLine ("lda #$00");
+                        AddCodeLine ("ldx #$00");
+                        AddCodeLine ("rol a");
                         return;
                     }
                     /* FALLTHROUGH */
 
                 case CF_INT:
-                    /* If the low byte is zero, we must only test the high byte */
-                    AddCodeLine ("cpx #$%02X", (unsigned char)(val >> 8));
-                    if ((val & 0xFF) != 0) {
-                        unsigned L = GetLocalLabel();
-                        AddCodeLine ("bne %s", LocalLabelName (L));
-                        AddCodeLine ("cmp #$%02X", (unsigned char)val);
-                        g_defcodelabel (L);
-                    }
-                    AddCodeLine ("jsr booluge");
+                    /* Do a subtraction. Condition is true if carry set */
+                    AddCodeLine ("cmp #$%02X", (unsigned char)val);
+                    AddCodeLine ("txa");
+                    AddCodeLine ("sbc #$%02X", (unsigned char)(val >> 8));
+                    AddCodeLine ("lda #$00");
+                    AddCodeLine ("ldx #$00");
+                    AddCodeLine ("rol a");
                     return;
 
                 case CF_LONG:
-                    /* Do a subtraction */
+                    /* Do a subtraction. Condition is true if carry set */
                     AddCodeLine ("cmp #$%02X", (unsigned char)val);
                     AddCodeLine ("txa");
                     AddCodeLine ("sbc #$%02X", (unsigned char)(val >> 8));
@@ -3872,7 +3948,9 @@ void g_ge (unsigned flags, unsigned long val)
                     AddCodeLine ("sbc #$%02X", (unsigned char)(val >> 16));
                     AddCodeLine ("lda sreg+1");
                     AddCodeLine ("sbc #$%02X", (unsigned char)(val >> 24));
-                    AddCodeLine ("jsr booluge");
+                    AddCodeLine ("lda #$00");
+                    AddCodeLine ("ldx #$00");
+                    AddCodeLine ("rol a");
                     return;
 
                 default:
@@ -3881,7 +3959,7 @@ void g_ge (unsigned flags, unsigned long val)
 
         } else if (val == 0) {
 
-            /* Look at the type */
+            /* A signed compare against zero must only look at the sign bit */
             switch (flags & CF_TYPE) {
 
                 case CF_CHAR:
@@ -3907,8 +3985,51 @@ void g_ge (unsigned flags, unsigned long val)
                 default:
                     typeerror (flags);
             }
-        }
 
+        } else {
+
+            /* Signed compare against a constant != zero */
+            switch (flags & CF_TYPE) {
+
+                case CF_CHAR:
+                    if (flags & CF_FORCECHAR) {
+                        Label = GetLocalLabel ();
+                        AddCodeLine ("sec");
+                        AddCodeLine ("sbc #$%02X", (unsigned char)val);
+                        AddCodeLine ("bvs %s", LocalLabelName (Label));
+                        AddCodeLine ("eor #$80");
+                        g_defcodelabel (Label);
+                        AddCodeLine ("asl a");          /* Bit 7 -> carry */
+                        AddCodeLine ("lda #$00");
+                        AddCodeLine ("ldx #$00");
+                        AddCodeLine ("rol a");
+                        return;
+                    }
+                    /* FALLTHROUGH */
+
+                case CF_INT:
+                    /* Do a subtraction */
+                    Label = GetLocalLabel ();
+                    AddCodeLine ("cmp #$%02X", (unsigned char)val);
+                    AddCodeLine ("txa");
+                    AddCodeLine ("sbc #$%02X", (unsigned char)(val >> 8));
+                    AddCodeLine ("bvs %s", LocalLabelName (Label));
+                    AddCodeLine ("eor #$80");
+                    g_defcodelabel (Label);
+                    AddCodeLine ("asl a");          /* Bit 7 -> carry */
+                    AddCodeLine ("lda #$00");
+                    AddCodeLine ("ldx #$00");
+                    AddCodeLine ("rol a");
+                    return;
+
+                case CF_LONG:
+                    /* This one is too costly */
+                    break;
+
+                default:
+                    typeerror (flags);
+            }
+        }
 
         /* If we go here, we didn't emit code. Push the lhs on stack and fall
          * into the normal, non-optimized stuff. Note: The standard stuff will