From dadca9e033383ccf1609015f4106e7d05686ada9 Mon Sep 17 00:00:00 2001 From: acqn Date: Sun, 13 Nov 2022 16:32:41 +0800 Subject: [PATCH] Fixed bitwise-shift in PP. --- src/cc65/ppexpr.c | 28 +++++++---- test/val/ppshift.c | 120 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 138 insertions(+), 10 deletions(-) create mode 100644 test/val/ppshift.c diff --git a/src/cc65/ppexpr.c b/src/cc65/ppexpr.c index 0942dc8f8..1610e9b92 100644 --- a/src/cc65/ppexpr.c +++ b/src/cc65/ppexpr.c @@ -519,12 +519,21 @@ static void PPhie7 (PPExpr* Expr) /* Evaluate */ if (PPEvaluationEnabled && !PPEvaluationFailed) { - /* To shift by a negative value is equivalent to shift to the - ** opposite direction. - */ - if ((Rhs.Flags & PPEXPR_UNSIGNED) != 0 && Rhs.IVal > (long)LONG_BITS) { + /* For now we use 32-bit integer types for PP integer constants */ + if ((Rhs.Flags & PPEXPR_UNSIGNED) != 0) { + if ((unsigned long)Rhs.IVal > LONG_BITS) { + Rhs.IVal = (long)LONG_BITS; + } + } else if (Rhs.IVal > (long)LONG_BITS) { Rhs.IVal = (long)LONG_BITS; + } else if (Rhs.IVal < -(long)LONG_BITS) { + Rhs.IVal = -(long)LONG_BITS; } + + /* Positive count for left-shift and negative for right-shift. So + ** to shift by a count is equivalent to shift to the opposite + ** direction by the negated count. + */ if (Op == TOK_SHR) { Rhs.IVal = -Rhs.IVal; } @@ -532,27 +541,26 @@ static void PPhie7 (PPExpr* Expr) /* Evaluate the result */ if ((Expr->Flags & PPEXPR_UNSIGNED) != 0) { if (Rhs.IVal >= (long)LONG_BITS) { - /* For now we use (unsigned) long types for integer constants */ PPWarning ("Integer overflow in preprocessor expression"); Expr->IVal = 0; } else if (Rhs.IVal > 0) { Expr->IVal <<= Rhs.IVal; - } else if (Rhs.IVal < -(long)LONG_BITS) { + } else if (Rhs.IVal <= -(long)LONG_BITS) { Expr->IVal = 0; } else if (Rhs.IVal < 0) { Expr->IVal = (unsigned long)Expr->IVal >> -Rhs.IVal; } } else { + /* -1 for sign bit */ if (Rhs.IVal >= (long)(LONG_BITS - 1)) { - /* For now we use (unsigned) long types for integer constants */ PPWarning ("Integer overflow in preprocessor expression"); Expr->IVal = 0; } else if (Rhs.IVal > 0) { Expr->IVal <<= Rhs.IVal; - } else if (Rhs.IVal < -(long)LONG_BITS) { - Expr->IVal = -1; + } else if (Rhs.IVal <= -(long)LONG_BITS) { + Expr->IVal = Expr->IVal >= 0 ? 0 : -1; } else if (Rhs.IVal < 0) { - Expr->IVal >>= Expr->IVal >> -Rhs.IVal; + Expr->IVal = (long)Expr->IVal >> -Rhs.IVal; } } } diff --git a/test/val/ppshift.c b/test/val/ppshift.c new file mode 100644 index 000000000..466b15926 --- /dev/null +++ b/test/val/ppshift.c @@ -0,0 +1,120 @@ +/* + Test of bitwise-shift in preprocessor expressions. + + Note: Keep in mind that integer constants are always 32-bit in PP for cc65. +*/ + +/* Signed lhs */ +#if 1 << 16 != 0x00010000 +#error 1 << 16 != 0x00010000 +#endif + +#if 0x00010000 << -16 != 1 +#error 0x00010000 << -16 != 1 +#endif + +#if 0x10000 >> 16 != 1 +#error 0x10000 >> 16 != 1 +#endif + +#if 1 >> -16 != 0x10000 +#error 1 >> -16 != 0x10000 +#endif + +#if 1 << 32 != 0 +#error 1 << 32 != 0 +#endif + +#if 1 << -32 != 0 +#error 1 << -32 != 0 +#endif + +#if 1 >> 32 != 0 +#error 1 >> 32 != 0 +#endif + +#if 1 >> -32 != 0 +#error 1 >> -32 != 0 +#endif + +#if -1 << 32 != 0 +#error -1 << 32 != 0 +#endif + +#if -1 << -32 != -1 +#error -1 << -32 != -1 +#endif + +#if -1 >> 32 != -1 +#error -1 >> 32 != -1 +#endif + +#if -1 >> -32 != 0 +#error -1 >> -32 != 0 +#endif + +/* NOTE: 2147483648 is an UNSIGNED integer! */ +#if -1 << 2147483648 != 0 +#error -1 << 2147483648 != 0 +#endif + +/* NOTE: -2147483648 is also an UNSIGNED integer! */ +#if -1 << -2147483648 != 0 +#error -1 << -2147483648 != 0 +#endif + +#if -1 << (-2147483647 - 1) != -1 +#error -1 << (-2147483647 - 1) != -1 +#endif + +/* NOTE: 2147483648 is an UNSIGNED integer! */ +#if -1 >> 2147483648 != -1 +#error -1 >> 2147483648 != -1 +#endif + +/* NOTE: -2147483648 is also an UNSIGNED integer! */ +#if -1 >> -2147483648 != -1 +#error -1 >> -2147483648 != 0 +#endif + +#if -1 >> (-2147483647 - 1) != 0 +#error -1 >> (-2147483647 - 1) != 0 +#endif + +/* Unsigned lhs */ +#if 1U << 16 != 0x00010000 +#error 1U << 16 != 0x00010000 +#endif + +#if 0x80000000U << -16 != 0x8000 +#error 0x80000000U << -16 != 0x8000 +#endif + +#if 0x80000000U >> 16 != 0x8000 +#error 0x80000000U >> 16 != 0x8000 +#endif + +#if 1U >> -16 != 0x10000 +#error 1U >> -16 != 0x10000 +#endif + +#if -1U << 32 != 0 +#error -1U << 32 != 0 +#endif + +#if -1U << -32 != 0 +#error -1U << -32 != 0 +#endif + +#if -1U >> 32 != 0 +#error -1U >> 32 != 0 +#endif + +#if -1U >> -32 != 0 +#error -1U >> -32 != 0 +#endif + +int main(void) +{ + return 0; +}