1
0
mirror of https://github.com/cc65/cc65.git synced 2024-07-09 01:28:58 +00:00

Fixed a bug in signed int compares

git-svn-id: svn://svn.cc65.org/cc65/trunk@2483 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
cuz 2003-10-08 21:26:32 +00:00
parent 9a2b4dc849
commit 923ae328a5

View File

@ -676,26 +676,26 @@ void g_getimmed (unsigned Flags, unsigned long Val, long Offs)
AddCodeLine ("stx sreg+1"); AddCodeLine ("stx sreg+1");
Done |= 0x08; Done |= 0x08;
} }
if ((Done & 0x04) == 0 && B1 != B3) { if ((Done & 0x04) == 0 && B1 != B3) {
AddCodeLine ("lda #$%02X", B3); AddCodeLine ("lda #$%02X", B3);
AddCodeLine ("sta sreg"); AddCodeLine ("sta sreg");
Done |= 0x04; Done |= 0x04;
} }
if ((Done & 0x08) == 0 && B1 != B4) { if ((Done & 0x08) == 0 && B1 != B4) {
AddCodeLine ("lda #$%02X", B4); AddCodeLine ("lda #$%02X", B4);
AddCodeLine ("sta sreg+1"); AddCodeLine ("sta sreg+1");
Done |= 0x08; Done |= 0x08;
} }
AddCodeLine ("lda #$%02X", B1); AddCodeLine ("lda #$%02X", B1);
Done |= 0x01; Done |= 0x01;
if ((Done & 0x04) == 0) { if ((Done & 0x04) == 0) {
CHECK (B1 == B3); CHECK (B1 == B3);
AddCodeLine ("sta sreg"); AddCodeLine ("sta sreg");
} }
if ((Done & 0x08) == 0) { if ((Done & 0x08) == 0) {
CHECK (B1 == B4); CHECK (B1 == B4);
AddCodeLine ("sta sreg+1"); AddCodeLine ("sta sreg+1");
} }
break; break;
default: default:
@ -706,12 +706,12 @@ void g_getimmed (unsigned Flags, unsigned long Val, long Offs)
} else { } else {
/* Some sort of label */ /* Some sort of label */
const char* Label = GetLabelName (Flags, Val, Offs); const char* Label = GetLabelName (Flags, Val, Offs);
/* Load the address into the primary */ /* Load the address into the primary */
AddCodeLine ("lda #<(%s)", Label); AddCodeLine ("lda #<(%s)", Label);
AddCodeLine ("ldx #>(%s)", Label); AddCodeLine ("ldx #>(%s)", Label);
} }
} }
@ -3492,84 +3492,58 @@ void g_lt (unsigned flags, unsigned long val)
*/ */
if (flags & CF_CONST) { if (flags & CF_CONST) {
/* Give a warning in some special cases */ /* Because the handling of the overflow flag is too complex for
if ((flags & CF_UNSIGNED) && val == 0) { * inlining, we can handle only unsigned compares here.
Warning ("Condition is never true"); */
AddCodeLine ("jsr return0"); if (flags & CF_UNSIGNED) {
return;
}
/* Look at the type */ /* Give a warning in some special cases */
switch (flags & CF_TYPE) { if (val == 0) {
Warning ("Condition is never true");
AddCodeLine ("jsr return0");
return;
}
case CF_CHAR: /* Look at the type */
if (flags & CF_FORCECHAR) { switch (flags & CF_TYPE) {
AddCodeLine ("cmp #$%02X", (unsigned char)val);
if (flags & CF_UNSIGNED) {
AddCodeLine ("jsr boolult");
} else {
AddCodeLine ("jsr boollt");
}
return;
}
/* FALLTHROUGH */
case CF_INT: case CF_CHAR:
if (flags & CF_UNSIGNED) { if (flags & CF_FORCECHAR) {
/* Unsigned compare */ AddCodeLine ("cmp #$%02X", (unsigned char)val);
/* If the low byte is zero, we must only test the high byte */ AddCodeLine ("jsr boolult");
AddCodeLine ("cpx #$%02X", (unsigned char)(val >> 8)); return;
if ((val & 0xFF) != 0) { }
unsigned L = GetLocalLabel(); /* FALLTHROUGH */
AddCodeLine ("bne %s", LocalLabelName (L));
AddCodeLine ("cmp #$%02X", (unsigned char)val);
g_defcodelabel (L);
}
AddCodeLine ("jsr boolult");
} 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: case CF_INT:
if ((flags & CF_UNSIGNED) == 0 && val == 0) { /* If the low byte is zero, we must only test the high byte */
/* If we have a signed compare against zero, we only need to AddCodeLine ("cpx #$%02X", (unsigned char)(val >> 8));
* test the high byte. if ((val & 0xFF) != 0) {
*/ unsigned L = GetLocalLabel();
AddCodeLine ("lda sreg+1"); AddCodeLine ("bne %s", LocalLabelName (L));
} else { AddCodeLine ("cmp #$%02X", (unsigned char)val);
/* Do a subtraction */ g_defcodelabel (L);
AddCodeLine ("cmp #$%02X", (unsigned char)val); }
AddCodeLine ("txa"); AddCodeLine ("jsr boolult");
AddCodeLine ("sbc #$%02X", (unsigned char)(val >> 8)); return;
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;
default: case CF_LONG:
typeerror (flags); /* Do a subtraction */
} AddCodeLine ("cmp #$%02X", (unsigned char)val);
AddCodeLine ("txa");
AddCodeLine ("sbc #$%02X", (unsigned char)(val >> 8));
AddCodeLine ("lda sreg");
AddCodeLine ("sbc #$%02X", (unsigned char)(val >> 16));
AddCodeLine ("lda sreg+1");
AddCodeLine ("sbc #$%02X", (unsigned char)(val >> 24));
AddCodeLine ("jsr boolult");
return;
default:
typeerror (flags);
}
}
/* If we go here, we didn't emit code. Push the lhs on stack and fall /* 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.
@ -3591,7 +3565,7 @@ void g_le (unsigned flags, unsigned long val)
"tosle00", "toslea0", "tosleax", "tosle00", "toslea0", "tosleax",
"tosule00", "tosulea0", "tosuleax", "tosule00", "tosulea0", "tosuleax",
0, 0, "tosleeax", 0, 0, "tosleeax",
0, 0, "tosuleeax", 0, 0, "tosuleeax",
}; };
@ -3606,92 +3580,92 @@ void g_le (unsigned flags, unsigned long val)
case CF_CHAR: case CF_CHAR:
if (flags & CF_FORCECHAR) { if (flags & CF_FORCECHAR) {
if (flags & CF_UNSIGNED) { if (flags & CF_UNSIGNED) {
/* Unsigned compare */ /* Unsigned compare */
if (val < 0xFF) { if (val < 0xFF) {
/* Use < instead of <= because the former gives /* Use < instead of <= because the former gives
* better code on the 6502 than the latter. * better code on the 6502 than the latter.
*/ */
g_lt (flags, val+1); g_lt (flags, val+1);
} else { } else {
/* Always true */ /* Always true */
Warning ("Condition is always true"); Warning ("Condition is always true");
AddCodeLine ("jsr return1"); AddCodeLine ("jsr return1");
} }
} else { } else {
/* Signed compare */ /* Signed compare */
if ((long) val < 0x7F) { if ((long) val < 0x7F) {
/* Use < instead of <= because the former gives /* Use < instead of <= because the former gives
* better code on the 6502 than the latter. * better code on the 6502 than the latter.
*/ */
g_lt (flags, val+1); g_lt (flags, val+1);
} else { } else {
/* Always true */ /* Always true */
Warning ("Condition is always true"); Warning ("Condition is always true");
AddCodeLine ("jsr return1"); AddCodeLine ("jsr return1");
} }
} }
return; return;
} }
/* FALLTHROUGH */ /* FALLTHROUGH */
case CF_INT: case CF_INT:
if (flags & CF_UNSIGNED) { if (flags & CF_UNSIGNED) {
/* Unsigned compare */ /* Unsigned compare */
if (val < 0xFFFF) { if (val < 0xFFFF) {
/* Use < instead of <= because the former gives /* Use < instead of <= because the former gives
* better code on the 6502 than the latter. * better code on the 6502 than the latter.
*/ */
g_lt (flags, val+1); g_lt (flags, val+1);
} else { } else {
/* Always true */ /* Always true */
Warning ("Condition is always true"); Warning ("Condition is always true");
AddCodeLine ("jsr return1"); AddCodeLine ("jsr return1");
} }
} else { } else {
/* Signed compare */ /* Signed compare */
if ((long) val < 0x7FFF) { if ((long) val < 0x7FFF) {
g_lt (flags, val+1); g_lt (flags, val+1);
} else { } else {
/* Always true */ /* Always true */
Warning ("Condition is always true"); Warning ("Condition is always true");
AddCodeLine ("jsr return1"); AddCodeLine ("jsr return1");
} }
} }
return; return;
case CF_LONG: case CF_LONG:
if (flags & CF_UNSIGNED) { if (flags & CF_UNSIGNED) {
/* Unsigned compare */ /* Unsigned compare */
if (val < 0xFFFFFFFF) { if (val < 0xFFFFFFFF) {
/* Use < instead of <= because the former gives /* Use < instead of <= because the former gives
* better code on the 6502 than the latter. * better code on the 6502 than the latter.
*/ */
g_lt (flags, val+1); g_lt (flags, val+1);
} else { } else {
/* Always true */ /* Always true */
Warning ("Condition is always true"); Warning ("Condition is always true");
AddCodeLine ("jsr return1"); AddCodeLine ("jsr return1");
} }
} else { } else {
/* Signed compare */ /* Signed compare */
if ((long) val < 0x7FFFFFFF) { if ((long) val < 0x7FFFFFFF) {
g_lt (flags, val+1); g_lt (flags, val+1);
} else { } else {
/* Always true */ /* Always true */
Warning ("Condition is always true"); Warning ("Condition is always true");
AddCodeLine ("jsr return1"); AddCodeLine ("jsr return1");
} }
} }
return; return;
default: default:
typeerror (flags); typeerror (flags);
} }
/* If we go here, we didn't emit code. Push the lhs on stack and fall /* 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.
*/ */
g_push (flags & ~CF_CONST, 0); g_push (flags & ~CF_CONST, 0);
} }
@ -3707,8 +3681,8 @@ void g_gt (unsigned flags, unsigned long val)
static char* ops [12] = { static char* ops [12] = {
"tosgt00", "tosgta0", "tosgtax", "tosgt00", "tosgta0", "tosgtax",
"tosugt00", "tosugta0", "tosugtax", "tosugt00", "tosugta0", "tosugtax",
0, 0, "tosgteax", 0, 0, "tosgteax",
0, 0, "tosugteax", 0, 0, "tosugteax",
}; };
@ -3724,32 +3698,32 @@ void g_gt (unsigned flags, unsigned long val)
if (flags & CF_FORCECHAR) { if (flags & CF_FORCECHAR) {
if (flags & CF_UNSIGNED) { if (flags & CF_UNSIGNED) {
if (val == 0) { if (val == 0) {
/* If we have a compare > 0, we will replace it by /* If we have a compare > 0, we will replace it by
* != 0 here, since both are identical but the * != 0 here, since both are identical but the
* latter is easier to optimize. * latter is easier to optimize.
*/ */
g_ne (flags, val); g_ne (flags, val);
} else if (val < 0xFF) { } else if (val < 0xFF) {
/* Use >= instead of > because the former gives /* Use >= instead of > because the former gives
* better code on the 6502 than the latter. * better code on the 6502 than the latter.
*/ */
g_ge (flags, val+1); g_ge (flags, val+1);
} else { } else {
/* Never true */ /* Never true */
Warning ("Condition is never true"); Warning ("Condition is never true");
AddCodeLine ("jsr return0"); AddCodeLine ("jsr return0");
} }
} else { } else {
if ((long) val < 0x7F) { if ((long) val < 0x7F) {
/* Use >= instead of > because the former gives /* Use >= instead of > because the former gives
* better code on the 6502 than the latter. * better code on the 6502 than the latter.
*/ */
g_ge (flags, val+1); g_ge (flags, val+1);
} else { } else {
/* Never true */ /* Never true */
Warning ("Condition is never true"); Warning ("Condition is never true");
AddCodeLine ("jsr return0"); AddCodeLine ("jsr return0");
} }
} }
return; return;
} }
@ -3757,74 +3731,74 @@ void g_gt (unsigned flags, unsigned long val)
case CF_INT: case CF_INT:
if (flags & CF_UNSIGNED) { if (flags & CF_UNSIGNED) {
/* Unsigned compare */ /* Unsigned compare */
if (val == 0) { if (val == 0) {
/* If we have a compare > 0, we will replace it by /* If we have a compare > 0, we will replace it by
* != 0 here, since both are identical but the latter * != 0 here, since both are identical but the latter
* is easier to optimize. * is easier to optimize.
*/ */
g_ne (flags, val); g_ne (flags, val);
} else if (val < 0xFFFF) { } else if (val < 0xFFFF) {
/* Use >= instead of > because the former gives better /* Use >= instead of > because the former gives better
* code on the 6502 than the latter. * code on the 6502 than the latter.
*/ */
g_ge (flags, val+1); g_ge (flags, val+1);
} else { } else {
/* Never true */ /* Never true */
Warning ("Condition is never true"); Warning ("Condition is never true");
AddCodeLine ("jsr return0"); AddCodeLine ("jsr return0");
} }
} else { } else {
/* Signed compare */ /* Signed compare */
if ((long) val < 0x7FFF) { if ((long) val < 0x7FFF) {
g_ge (flags, val+1); g_ge (flags, val+1);
} else { } else {
/* Never true */ /* Never true */
Warning ("Condition is never true"); Warning ("Condition is never true");
AddCodeLine ("jsr return0"); AddCodeLine ("jsr return0");
} }
} }
return; return;
case CF_LONG: case CF_LONG:
if (flags & CF_UNSIGNED) { if (flags & CF_UNSIGNED) {
/* Unsigned compare */ /* Unsigned compare */
if (val == 0) { if (val == 0) {
/* If we have a compare > 0, we will replace it by /* If we have a compare > 0, we will replace it by
* != 0 here, since both are identical but the latter * != 0 here, since both are identical but the latter
* is easier to optimize. * is easier to optimize.
*/ */
g_ne (flags, val); g_ne (flags, val);
} else if (val < 0xFFFFFFFF) { } else if (val < 0xFFFFFFFF) {
/* Use >= instead of > because the former gives better /* Use >= instead of > because the former gives better
* code on the 6502 than the latter. * code on the 6502 than the latter.
*/ */
g_ge (flags, val+1); g_ge (flags, val+1);
} else { } else {
/* Never true */ /* Never true */
Warning ("Condition is never true"); Warning ("Condition is never true");
AddCodeLine ("jsr return0"); AddCodeLine ("jsr return0");
} }
} else { } else {
/* Signed compare */ /* Signed compare */
if ((long) val < 0x7FFFFFFF) { if ((long) val < 0x7FFFFFFF) {
g_ge (flags, val+1); g_ge (flags, val+1);
} else { } else {
/* Never true */ /* Never true */
Warning ("Condition is never true"); Warning ("Condition is never true");
AddCodeLine ("jsr return0"); AddCodeLine ("jsr return0");
} }
} }
return; return;
default: default:
typeerror (flags); typeerror (flags);
} }
/* If we go here, we didn't emit code. Push the lhs on stack and fall /* 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.
*/ */
g_push (flags & ~CF_CONST, 0); g_push (flags & ~CF_CONST, 0);
} }
@ -3850,84 +3824,58 @@ void g_ge (unsigned flags, unsigned long val)
*/ */
if (flags & CF_CONST) { if (flags & CF_CONST) {
/* Give a warning in some special cases */ /* Because the handling of the overflow flag is too complex for
if ((flags & CF_UNSIGNED) && val == 0) { * inlining, we can handle only unsigned compares here.
Warning ("Condition is always true"); */
AddCodeLine ("jsr return1"); if (flags & CF_UNSIGNED) {
return;
}
/* Look at the type */ /* Give a warning in some special cases */
switch (flags & CF_TYPE) { if (val == 0) {
Warning ("Condition is always true");
AddCodeLine ("jsr return1");
return;
}
case CF_CHAR: /* Look at the type */
if (flags & CF_FORCECHAR) { switch (flags & CF_TYPE) {
AddCodeLine ("cmp #$%02X", (unsigned char)val);
if (flags & CF_UNSIGNED) {
AddCodeLine ("jsr booluge");
} else {
AddCodeLine ("jsr boolge");
}
return;
}
/* FALLTHROUGH */
case CF_INT: case CF_CHAR:
if (flags & CF_UNSIGNED) { if (flags & CF_FORCECHAR) {
/* Unsigned compare */ AddCodeLine ("cmp #$%02X", (unsigned char)val);
/* If the low byte is zero, we must only test the high byte */ AddCodeLine ("jsr booluge");
AddCodeLine ("cpx #$%02X", (unsigned char)(val >> 8)); return;
if ((val & 0xFF) != 0) { }
unsigned L = GetLocalLabel(); /* FALLTHROUGH */
AddCodeLine ("bne %s", LocalLabelName (L));
AddCodeLine ("cmp #$%02X", (unsigned char)val);
g_defcodelabel (L);
}
AddCodeLine ("jsr booluge");
} 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: case CF_INT:
if ((flags & CF_UNSIGNED) == 0 && val == 0) { /* If the low byte is zero, we must only test the high byte */
/* If we have a signed compare against zero, we only need to AddCodeLine ("cpx #$%02X", (unsigned char)(val >> 8));
* test the high byte. if ((val & 0xFF) != 0) {
*/ unsigned L = GetLocalLabel();
AddCodeLine ("lda sreg+1"); AddCodeLine ("bne %s", LocalLabelName (L));
} else { AddCodeLine ("cmp #$%02X", (unsigned char)val);
/* Do a subtraction */ g_defcodelabel (L);
AddCodeLine ("cmp #$%02X", (unsigned char)val); }
AddCodeLine ("txa"); AddCodeLine ("jsr booluge");
AddCodeLine ("sbc #$%02X", (unsigned char)(val >> 8)); return;
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;
default: case CF_LONG:
typeerror (flags); /* Do a subtraction */
} AddCodeLine ("cmp #$%02X", (unsigned char)val);
AddCodeLine ("txa");
AddCodeLine ("sbc #$%02X", (unsigned char)(val >> 8));
AddCodeLine ("lda sreg");
AddCodeLine ("sbc #$%02X", (unsigned char)(val >> 16));
AddCodeLine ("lda sreg+1");
AddCodeLine ("sbc #$%02X", (unsigned char)(val >> 24));
AddCodeLine ("jsr booluge");
return;
default:
typeerror (flags);
}
}
/* If we go here, we didn't emit code. Push the lhs on stack and fall /* 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.