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:
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user