diff --git a/src/cc65/expr.c b/src/cc65/expr.c index 691010b0a..9460569ed 100644 --- a/src/cc65/expr.c +++ b/src/cc65/expr.c @@ -3090,9 +3090,10 @@ static void parseadd (ExprDesc* Expr, int DoArrayRef) Expr->Type = Expr2.Type; } else if (!DoArrayRef && IsClassInt (lhst) && IsClassInt (rhst)) { /* Integer addition */ - flags = typeadjust (Expr, &Expr2, 0); /* Load rhs into the primary */ LoadExpr (CF_NONE, &Expr2); + /* Adjust rhs primary if needed */ + flags = typeadjust (Expr, &Expr2, 0); } else { /* OOPS */ AddDone = -1; diff --git a/test/val/bug2060.c b/test/val/bug2060.c new file mode 100644 index 000000000..59b4774a4 --- /dev/null +++ b/test/val/bug2060.c @@ -0,0 +1,56 @@ +/* Test of bug: https://github.com/cc65/cc65/issues/2060 */ + +#include + +#define W 320 + +unsigned long test1(unsigned char* p, unsigned long n) +{ + (void)p; + return n; +} + +unsigned long test0(unsigned char* p, int x, int y, unsigned char b) +{ + (void)b; + return test1(p, (long)y * W + x); +} + +#define TEST(ta,tb) \ + expect = (long)tb * W + ta; \ + result = test0(p,ta,tb,0x56); \ + printf("%4d * %3d + %4d = %08lx",tb,W,ta,result); \ + if (expect != result) { printf(" expected: %08lx\n",expect); ++fail; } \ + else printf("\n"); + +int main(void) +{ + unsigned char* p = (unsigned char*)0x1234; + unsigned long expect, result; + int fail = 0; + + TEST(1,3); + TEST(50,60); + TEST(99,88); + TEST(128,102); + TEST(129,102); + TEST(320,102); + /* Bug 2060 indicated failure when y > 102. + Because: (y * 320) > 32767 + The promotion of x from int to long had an incorrect high word, + because it was done before loading x into AX, rather than after. + */ + TEST(0,103); + TEST(150,170); + TEST(300,180); + /* x < 0 also fails because its high word sign extend is incorrect. */ + TEST(-100,50); + TEST(-49,99); + TEST(-300,-180); + /* This passed despite the bug, because y * 320 coincidentally had the + same high word. + */ + TEST(-1,-1); + + return fail; +}