1
0
mirror of https://github.com/cc65/cc65.git synced 2024-11-11 16:07:04 +00:00
cc65/test/val/bug895.c
2019-05-27 10:03:25 +02:00

107 lines
5.1 KiB
C

/** This test is related to GitHub issue 895
** https://github.com/cc65/cc65/issues/895
**
** The OptCmp8 optimization attempted 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 16-bit types it failed
** to generate correct code for some cases. The bug manifest as a
** branch on an uninitialized carry flag.
*/
#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_SINGLE(num,cmpop,asmprefix,vara,varb,b0,b1,a0,a1,typename,name) \
typename name ## _ ## num ## (void) { \
varb = b0; \
asm( asmprefix ); \
vara = a0; \
if (vara cmpop a1) varb = b1; \
return varb; \
}
#define OPTCMP8TEST_VERIFY(num,b,desc,printterm,name) \
ASSERT_AreEqual(name ## _ ## num ##(),b,printterm,"Incorrect optimization of const comparison (" #name "_" #num ": " desc ").");
/* Generates a set of comparison tests for one type and set of test values.
** name = a name for this test (no spaces)
** typename = the type used
** b0 = result if comparison is false
** b1 = result if comparison is true
** a0 = a low value to use for the comparison tests (a0 < a1)
** a1 = a high value to use for the comparison tests (a0 < a1)
** vara = temporary variable of the type to be examined
** varb = temporary variable of the type to be examined
** printterm = printf term to display the variable type
*/
#define OPTCMP8TEST(name,typename,b0,b1,a0,a1,vara,varb,printterm) \
OPTCMP8TEST_SINGLE(1,<,"clc",vara,varb,b0,b1,a0,a1,typename,name); \
OPTCMP8TEST_SINGLE(2,<,"sec",vara,varb,b0,b1,a0,a1,typename,name); \
OPTCMP8TEST_SINGLE(3,<,"clc",vara,varb,b0,b1,a1,a0,typename,name); \
OPTCMP8TEST_SINGLE(4,<,"sec",vara,varb,b0,b1,a1,a0,typename,name); \
OPTCMP8TEST_SINGLE(5,>,"clc",vara,varb,b0,b1,a0,a1,typename,name); \
OPTCMP8TEST_SINGLE(6,>,"sec",vara,varb,b0,b1,a0,a1,typename,name); \
OPTCMP8TEST_SINGLE(7,>,"clc",vara,varb,b0,b1,a1,a0,typename,name); \
OPTCMP8TEST_SINGLE(8,>,"sec",vara,varb,b0,b1,a1,a0,typename,name); \
OPTCMP8TEST_SINGLE(9,<=,"clc",vara,varb,b0,b1,a0,a1,typename,name); \
OPTCMP8TEST_SINGLE(10,<=,"sec",vara,varb,b0,b1,a0,a1,typename,name); \
OPTCMP8TEST_SINGLE(11,<=,"clc",vara,varb,b0,b1,a1,a0,typename,name); \
OPTCMP8TEST_SINGLE(12,<=,"sec",vara,varb,b0,b1,a1,a0,typename,name); \
OPTCMP8TEST_SINGLE(13,>=,"clc",vara,varb,b0,b1,a0,a1,typename,name); \
OPTCMP8TEST_SINGLE(14,>=,"sec",vara,varb,b0,b1,a0,a1,typename,name); \
OPTCMP8TEST_SINGLE(15,>=,"clc",vara,varb,b0,b1,a1,a0,typename,name); \
OPTCMP8TEST_SINGLE(16,>=,"sec",vara,varb,b0,b1,a1,a0,typename,name); \
OPTCMP8TEST_SINGLE(17,==,"nop",vara,varb,b0,b1,a0,a1,typename,name); \
OPTCMP8TEST_SINGLE(18,==,"nop",vara,varb,b0,b1,a1,a1,typename,name); \
OPTCMP8TEST_SINGLE(19,!=,"nop",vara,varb,b0,b1,a0,a1,typename,name); \
OPTCMP8TEST_SINGLE(20,!=,"nop",vara,varb,b0,b1,a1,a1,typename,name); \
void name ## _ ## test(void) { \
OPTCMP8TEST_VERIFY(1,b1,"low < high, clc",printterm,name); \
OPTCMP8TEST_VERIFY(2,b1,"low < high, sec",printterm,name); \
OPTCMP8TEST_VERIFY(3,b0,"high < low, clc",printterm,name); \
OPTCMP8TEST_VERIFY(4,b0,"high < low, sec",printterm,name); \
OPTCMP8TEST_VERIFY(5,b0,"low > high, clc",printterm,name); \
OPTCMP8TEST_VERIFY(6,b0,"low > high, sec",printterm,name); \
OPTCMP8TEST_VERIFY(7,b1,"high > low, clc",printterm,name); \
OPTCMP8TEST_VERIFY(8,b1,"high > low, sec",printterm,name); \
OPTCMP8TEST_VERIFY(9,b1,"low <= high, clc",printterm,name); \
OPTCMP8TEST_VERIFY(10,b1,"low <= high, sec",printterm,name); \
OPTCMP8TEST_VERIFY(11,b0,"high <= low, clc",printterm,name); \
OPTCMP8TEST_VERIFY(12,b0,"high <= low, sec",printterm,name); \
OPTCMP8TEST_VERIFY(13,b0,"low >= high, clc",printterm,name); \
OPTCMP8TEST_VERIFY(14,b0,"low >= high, sec",printterm,name); \
OPTCMP8TEST_VERIFY(15,b1,"high >= low, clc",printterm,name); \
OPTCMP8TEST_VERIFY(16,b1,"high >= low, sec",printterm,name); \
OPTCMP8TEST_VERIFY(17,b0,"low == high, nop",printterm,name); \
OPTCMP8TEST_VERIFY(18,b1,"high == high, nop",printterm,name); \
OPTCMP8TEST_VERIFY(19,b1,"low != high, nop",printterm,name); \
OPTCMP8TEST_VERIFY(20,b0,"high != high, nop",printterm,name); \
}
OPTCMP8TEST(signed_char,signed char,-20,5,60,100,sca,scb,"%d");
OPTCMP8TEST(unsigned_char,unsigned char,20,5,60,100,uca,ucb,"%u");
OPTCMP8TEST(signed_int,signed int,-2000,50,600,1000,sia,sib,"%d");
OPTCMP8TEST(unsigned_int,unsigned int,2000,50,600,1000,uia,uib,"%u");
OPTCMP8TEST(signed_long,signed long,-200000L,5000L,60000L,100000L,sla,slb,"%d");
OPTCMP8TEST(unsigned_long,unsigned long,200000UL,5000UL,60000UL,100000UL,ula,ulb,"%u");
TEST
{
signed_char_test();
unsigned_char_test();
signed_int_test();
unsigned_int_test();
signed_long_test();
unsigned_long_test();
}
ENDTEST