From 1461ad6fccd3c7317f25158c44122007f106436e Mon Sep 17 00:00:00 2001 From: bbbradsmith Date: Thu, 16 May 2019 15:56:09 -0400 Subject: [PATCH] unit test to catch regression of bug #895 --- test/val/bug895.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 test/val/bug895.c diff --git a/test/val/bug895.c b/test/val/bug895.c new file mode 100644 index 000000000..dc9f1cb42 --- /dev/null +++ b/test/val/bug895.c @@ -0,0 +1,81 @@ +/** This test is related to GitHub issue 895 + ** https://github.com/cc65/cc65/issues/895 + ** + ** The OptCmp8 optimization attempts to eliminate an unnecessary + ** comparison and branch when the operands of the comparison are + ** known to be constant at compile time. + ** + ** For 8-bit types it worked well, but for larger types it failed + ** to generate correct code. The bug manifest as a branch on an + ** uninitialized carry flag. + ** + ** This does four tests for each type tested: + ** 1: < with carry clear + ** 2: >= with carry clear + ** 3: < with carry set + ** 4: >= with carry set + */ + +#include "unittest.h" + +signed char sca, scb; +signed int sia, sib; +signed long sla, slb; + +unsigned char uca, ucb; +unsigned int uia, uib; +unsigned long ula, ulb; + +#define OPTCMP8TEST(vara,varb,startb,starta,cmpa,setb,printterm,typename,name) \ + void name ## 1(void) { \ + varb = startb; \ + asm("clc"); \ + vara = starta; \ + if (vara < cmpa) varb = setb; \ + ASSERT_AreEqual(startb, varb, printterm, "Incorrect optimization of " typename " comparison (1: < clc)."); \ + } \ + void name ## 2(void) { \ + varb = startb; \ + asm("sec"); \ + vara = starta; \ + if (vara < cmpa) varb = setb; \ + ASSERT_AreEqual(startb, varb, printterm, "Incorrect optimization of " typename " comparison (2: < sec)."); \ + } \ + void name ## 3(void) { \ + varb = startb; \ + asm("clc"); \ + vara = starta; \ + if (vara >= cmpa) varb = setb; \ + ASSERT_AreEqual(setb, varb, printterm, "Incorrect optimization of " typename " comparison (3: >= clc)."); \ + } \ + void name ## 4(void) { \ + varb = startb; \ + asm("sec"); \ + vara = starta; \ + if (vara >= cmpa) varb = setb; \ + ASSERT_AreEqual(setb, varb, printterm, "Incorrect optimization of " typename " comparison (4: >= sec)."); \ + } + +#define RUNOPTCMP8TEST(name) \ + name ## 1(); \ + name ## 2(); \ + name ## 3(); \ + name ## 4(); + +OPTCMP8TEST(sca,scb,-20,100,50,5,"%d","signed char",signed_char); +OPTCMP8TEST(uca,ucb,20,100,50,5,"%u","unsigned char",unsigned_char); +OPTCMP8TEST(sia,sib,-2000,1000,500,50,"%d","signed int",signed_int); +OPTCMP8TEST(uia,uib,2000,1000,500,50,"%u","unsigned int",unsigned_int); +OPTCMP8TEST(sla,slb,-200000L,100000L,50000L,5000L,"%d","signed long",signed_long); +OPTCMP8TEST(ula,ulb,200000UL,100000UL,50000UL,5000UL,"%u","unsigned long",unsigned_long); + +TEST +{ + RUNOPTCMP8TEST(signed_char); + RUNOPTCMP8TEST(unsigned_char); + RUNOPTCMP8TEST(signed_int); + RUNOPTCMP8TEST(unsigned_int); + RUNOPTCMP8TEST(signed_long); + RUNOPTCMP8TEST(unsigned_long); +} +ENDTEST