1
0
mirror of https://github.com/cc65/cc65.git synced 2025-08-08 06:25:17 +00:00

Fix casting an r-value to char.

For example:
int f(int i, int j) { return (char) (i + 1) == j; }
f(0x1234, 0x35) returned 0.

This bug caused zlib/uncompress return Z_DATA_ERROR on correct input.
This commit is contained in:
Piotr Fusik
2014-09-22 23:47:20 +02:00
parent d75f9c2051
commit 8c1f12f06b

View File

@@ -1226,26 +1226,34 @@ void g_tosint (unsigned flags)
void g_regint (unsigned Flags) static void g_regchar (unsigned Flags)
/* Make sure, the value in the primary register an int. Convert if necessary */ /* Make sure, the value in the primary register is in the range of char. Truncate if necessary */
{ {
unsigned L; unsigned L;
AddCodeLine ("ldx #$00");
if ((Flags & CF_UNSIGNED) == 0) {
/* Sign extend */
L = GetLocalLabel();
AddCodeLine ("cmp #$80");
AddCodeLine ("bcc %s", LocalLabelName (L));
AddCodeLine ("dex");
g_defcodelabel (L);
}
}
void g_regint (unsigned Flags)
/* Make sure, the value in the primary register an int. Convert if necessary */
{
switch (Flags & CF_TYPEMASK) { switch (Flags & CF_TYPEMASK) {
case CF_CHAR: case CF_CHAR:
if (Flags & CF_FORCECHAR) { if (Flags & CF_FORCECHAR) {
/* Conversion is from char */ /* Conversion is from char */
if (Flags & CF_UNSIGNED) { g_regchar (Flags);
AddCodeLine ("ldx #$00");
} else {
L = GetLocalLabel();
AddCodeLine ("ldx #$00");
AddCodeLine ("cmp #$80");
AddCodeLine ("bcc %s", LocalLabelName (L));
AddCodeLine ("dex");
g_defcodelabel (L);
}
} }
/* FALLTHROUGH */ /* FALLTHROUGH */
@@ -1263,8 +1271,6 @@ void g_regint (unsigned Flags)
void g_reglong (unsigned Flags) void g_reglong (unsigned Flags)
/* Make sure, the value in the primary register a long. Convert if necessary */ /* Make sure, the value in the primary register a long. Convert if necessary */
{ {
unsigned L;
switch (Flags & CF_TYPEMASK) { switch (Flags & CF_TYPEMASK) {
case CF_CHAR: case CF_CHAR:
@@ -1280,12 +1286,7 @@ void g_reglong (unsigned Flags)
} }
} else { } else {
if (IS_Get (&CodeSizeFactor) >= 366) { if (IS_Get (&CodeSizeFactor) >= 366) {
L = GetLocalLabel(); g_regchar (Flags);
AddCodeLine ("ldx #$00");
AddCodeLine ("cmp #$80");
AddCodeLine ("bcc %s", LocalLabelName (L));
AddCodeLine ("dex");
g_defcodelabel (L);
AddCodeLine ("stx sreg"); AddCodeLine ("stx sreg");
AddCodeLine ("stx sreg+1"); AddCodeLine ("stx sreg+1");
} else { } else {
@@ -1374,20 +1375,27 @@ unsigned g_typecast (unsigned lhs, unsigned rhs)
** by the lhs value. Return the result value. ** by the lhs value. Return the result value.
*/ */
{ {
unsigned ltype, rtype;
/* Get the type spec from the flags */
ltype = lhs & CF_TYPEMASK;
rtype = rhs & CF_TYPEMASK;
/* Check if a conversion is needed */ /* Check if a conversion is needed */
if ((rhs & CF_CONST) == 0) { if ((rhs & CF_CONST) == 0) {
if (ltype == CF_LONG && rtype != CF_LONG) { switch (lhs & CF_TYPEMASK) {
/* We must promote the primary register to long */
g_reglong (rhs); case CF_LONG:
} else if (ltype == CF_INT && rtype != CF_INT) { /* We must promote the primary register to long */
/* We must promote the primary register to int */ g_reglong (rhs);
g_regint (rhs); break;
case CF_INT:
/* We must promote the primary register to int */
g_regint (rhs);
break;
case CF_CHAR:
/* We must truncate the primary register to char */
g_regchar (lhs);
break;
default:
typeerror (lhs);
} }
} }