mirror of
https://github.com/cc65/cc65.git
synced 2024-11-11 16:07:04 +00:00
107 lines
5.1 KiB
C
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
|