/* { dg-do run } */ /* { dg-require-effective-target int128 } */ /* { dg-require-effective-target power10_hw } */ /* { dg-options "-mdejagnu-cpu=power10 -O2 -save-temps" } */ /* { dg-final { scan-assembler-times {\mbcdadd\M} 7 } } */ /* { dg-final { scan-assembler-times {\mbcdsub\M} 18 } } */ /* { dg-final { scan-assembler-times {\mbcds\M} 2 } } */ /* { dg-final { scan-assembler-times {\mdenbcdq\M} 1 } } */ #include #define DEBUG 0 #if DEBUG #include #endif #define BCD_POS0 12 // 0xC #define BCD_POS1 15 // 0xF #define BCD_NEG 13 // 0xD void abort (void); union conv_t { _Decimal128 d128; vector unsigned char ch; vector long long unsigned int vllui; } conv; _Decimal128 convert_vec_char (vector unsigned char a) { union conv_t conv; _Decimal128 result; conv.ch = a; result = conv.d128; return result; } vector unsigned char maxbcd(unsigned int sign) { vector unsigned char result; int i; for (i = 15; i > 0; i--) result[i] = 0x99; result[0] = sign << 4 | 0x9; } vector unsigned char num2bcd(long int a, int encoding) { int i; unsigned int hi, low, sign; vector unsigned char result; if (a > 0) { if (encoding == 0) sign = BCD_POS0; else sign = BCD_POS1; } else { sign = BCD_NEG; a = -a; } hi = a % 10; // 1st digit a = a / 10; result[0] = hi << 4| sign; for (i = 1; i < 16; i++) { low = a % 10; a = a / 10; hi = a % 10; a = a / 10; result[i] = hi << 4 | low; } return result; } int main () { int i; long int value_a, value_b, value_result; vector unsigned char a, b, result, exp_result; _Decimal128 result_d128, exp_result_d128; /* Make a and b positive BCD numbers */ value_a = 1020304; a = num2bcd(value_a, 0); value_b = 101010; b = num2bcd(value_b, 0); value_result = value_a + value_b; exp_result = num2bcd(value_result, 0); result = __builtin_bcdadd (a, b, 0); for (i = 0; i < 16; i++) if (exp_result[i] != result[i]) { #if DEBUG printf("ERROR: __builtin_bcdadd result[%d] = %d does not match " "expected_result[%d] = %d\n", i, result[i], i, exp_result[i]); #else abort(); #endif } /* result should be positive */ if ((result[0] & 0xF) != BCD_POS0) #if DEBUG printf("ERROR: __builtin_bcdadd sign of result is %d. Does not match " "expected_result = %d\n", result[0] & 0xF, BCD_POS0); #else abort(); #endif /* Make a and b positive BCD numbers using alternate positive encoding. */ value_a = 1030507; a = num2bcd(value_a, 1); value_b = 204060; b = num2bcd(value_b, 1); value_result = value_a + value_b; exp_result = num2bcd(value_result, 1); result = __builtin_bcdadd (a, b, 1); for (i = 0; i < 16; i++) if (exp_result[i] != result[i]) { #if DEBUG printf("ERROR: __builtin_bcdadd result[%d] = %d does not match " "expected_result[%d] = %d\n", i, result[i], i, exp_result[i]); #else abort(); #endif } /* Result should be positive, alternate encoding. */ if ((result[0] & 0xF) != BCD_POS1) #if DEBUG printf("ERROR: __builtin_bcdadd sign of result is %d. Does not " "match expected_result = %d\n", result[0] & 0xF, BCD_POS1); #else abort(); #endif /* Make a and b negative BCD numbers */ value_a = -1030507; a = num2bcd(value_a, 0); value_b = -1010101; b = num2bcd(value_b, 0); value_result = value_a + value_b; exp_result = num2bcd(value_result, 0); result = __builtin_bcdadd (a, b, 0); for (i = 0; i < 16; i++) if (exp_result[i] != result[i]) { #if DEBUG printf("ERROR: __builtin_bcdadd, neg result[%d] = %d does not match " "expected_result[%d] = %d\n", i, result[i], i, exp_result[i]); #else abort(); #endif } /* result should be negative */ if ((result[0] & 0xF) != BCD_NEG) #if DEBUG printf("ERROR: __builtin_bcdadd sign, neg of result is %d. Does not " "match expected_result = %d\n", result[0] & 0xF, BCD_NEG); #else abort(); #endif /* Make a negative, b positive BCD numbers */ value_a = -1030507; a = num2bcd(value_a, 0); value_b = 1010101; b = num2bcd(value_b, 0); value_result = value_a - value_b; exp_result = num2bcd(value_result, 0); result = __builtin_bcdsub (a, b, 0); for (i = 0; i < 16; i++) if (exp_result[i] != result[i]) { #if DEBUG printf("ERROR: __builtin_bcdsub, neg result[%d] = %d does not match " "expected_result[%d] = %d\n", i, result[i], i, exp_result[i]); #else abort(); #endif } /* result should be positive, alt encoding */ if ((result[0] & 0xF) != BCD_NEG) #if DEBUG printf("ERROR: __builtin_bcdadd sign, of result is %d. Does not match " "expected_result = %d\n", result[0] & 0xF, BCD_NEG); #else abort(); #endif /* Make a and b positive BCD numbers */ value_a = 1030507; a = num2bcd(value_a, 1); value_b = 1010101; b = num2bcd(value_b, 1); value_result = value_a - value_b; exp_result = num2bcd(value_result, 1); result = __builtin_bcdsub (a, b, 1); for (i = 0; i < 16; i++) if (exp_result[i] != result[i]) { #if DEBUG printf("ERROR:carll __builtin_bcdsub, pos result[%d] = %d does not " "match expected_result[%d] = %d\n", i, result[i], i, exp_result[i]); #else abort(); #endif } /* result should be positive */ if ((result[0] & 0xF) != BCD_POS1) #if DEBUG printf("ERROR: __builtin_bcdsub sign, result is %d. Does not match " "expected_result = %d\n", result[0] & 0xF, BCD_POS1); #else abort(); #endif /* Test overflow add and subtract. */ a = maxbcd(BCD_POS0); b = maxbcd(BCD_POS0); if(__builtin_bcdadd_ofl (a, b, 0) == 0) #if DEBUG printf("ERROR: __builtin_bcdadd did not overflow as expected\n"); #else abort(); #endif value_a = 99999999; a = num2bcd(value_a, 0); value_b = 999999999; b = num2bcd(value_b, 0); if(__builtin_bcdadd_ofl (a, b, 0)) #if DEBUG printf("ERROR: __builtin_bcdadd unexpectedly overflowed\n"); #else abort(); #endif a = maxbcd(BCD_NEG); b = maxbcd(BCD_NEG); if (__builtin_bcdsub_ofl (a, b, 0) == 0) #if DEBUG printf("ERROR: __builtin_bcdsub did not overflow as expected\n"); #else abort(); #endif value_a = -99999999; a = num2bcd(value_a, 0); value_b = -999999999; b = num2bcd(value_b, 0); if (__builtin_bcdsub_ofl (a, b, 0)) #if DEBUG printf("ERROR: __builtin_bcdsub unexpectedly overflowed\n"); #else abort(); #endif /* Test arguments for valid/invalid */ if (__builtin_bcdinvalid (a)) #if DEBUG printf("ERROR: __builtin_invalid input is unexpectedly invalid.\n"); #else abort(); #endif a[3] = 0xBB; /* an invalid BCD digit */ if (!__builtin_bcdinvalid (a)) #if DEBUG printf("ERROR: __builtin_invalid input is unexpectedly valid.\n"); #else abort(); #endif value_a = 1020304; a = num2bcd(value_a, 0); value_b = 101010; b = num2bcd(value_b, 0); /* Test equality */ if (__builtin_bcdcmpeq (a, b)) #if DEBUG printf("ERROR: __builtin__bcdcmpeq result is unexpectedly 1.\n"); #else abort(); #endif if (!__builtin_bcdcmpeq (a, a)) #if DEBUG printf("ERROR: __builtin__bcdcmpeq result is unexpectedly 0.\n"); #else abort(); #endif /* Test a greater then b, inputs already setup this way. */ if (!__builtin_bcdcmpgt (a, b)) #if DEBUG printf("ERROR: __builtin__bcdcmpgt result is unexpectedly 0.\n"); #else abort(); #endif if (__builtin_bcdcmpgt (b, a)) #if DEBUG printf("ERROR: __builtin__bcdcmpgt result is unexpectedly 1.\n"); #else abort(); #endif if (__builtin_bcdcmpgt (a, a)) #if DEBUG printf("ERROR: __builtin__bcdcmpgt input equal, result is unexpectedly " "1.\n"); #else abort(); #endif if (!__builtin_bcdcmpge (a, b)) #if DEBUG printf("ERROR: __builtin__bcdcmpge result is unexpectedly 0.\n"); #else abort(); #endif if (__builtin_bcdcmpge (b, a)) #if DEBUG printf("ERROR: __builtin__bcdcmpge result is unexpectedly 1.\n"); #else abort(); #endif if (!__builtin_bcdcmpge (b, b)) #if DEBUG printf("ERROR: __builtin__bcdcmpge inputs equal result is unexpectedly " "0.\n"); #else abort(); #endif /* Test a less then b. */ value_a = 101010; a = num2bcd(value_a, 0); value_b = 1020304; b = num2bcd(value_b, 0); if (!__builtin_bcdcmplt (a, b)) #if DEBUG printf("ERROR: __builtin__bcdcmplt result is unexpectedly 0.\n"); #else abort(); #endif if (__builtin_bcdcmplt (b, a)) #if DEBUG printf("ERROR: __builtin__bcdcmplt result is unexpectedly 1.\n"); #else abort(); #endif if (__builtin_bcdcmplt (b, b)) #if DEBUG printf("ERROR: __builtin__bcdcmplt inputs equal result is unexpectedly " "1.\n"); #else abort(); #endif if (!__builtin_bcdcmple (a, b)) #if DEBUG printf("ERROR: __builtin__bcdcmple result is unexpectedly 0.\n"); #else abort(); #endif if (__builtin_bcdcmple (b, a)) #if DEBUG printf("ERROR: __builtin__bcdcmple result is unexpectedly 1.\n"); #else abort(); #endif if (!__builtin_bcdcmple (a, a)) #if DEBUG printf("ERROR: __builtin__bcdcmple inputs equal result is unexpectedly " "0.\n"); #else abort(); #endif /* Test multipy 10 */ value_a = 1020304; a = num2bcd(value_a, 0); value_result = value_a * 10; exp_result = num2bcd(value_result, 0); result = __builtin_bcdmul10 (a); for (i = 0; i < 16; i++) if (exp_result[i] != result[i]) { #if DEBUG printf("ERROR:carll __builtin_bcdmul10, pos result[%d] = %d does not " "match expected_result[%d] = %d\n", i, result[i], i, exp_result[i]); #else abort(); #endif } /* result should be positive */ if ((result[0] & 0xF) != BCD_POS0) #if 0 printf("ERROR: __builtin_bcdmul10 sign, result is %d. Does not match " "expected_result = %d\n", result[0] & 0xF, BCD_POS1); #else abort(); #endif /* Test divide 10 */ value_a = 1020304; a = num2bcd(value_a, 0); value_result = value_a / 10; exp_result = num2bcd(value_result, 0); result = __builtin_bcddiv10 (a); for (i = 0; i < 16; i++) if (exp_result[i] != result[i]) { #if DEBUG printf("ERROR:carll __builtin_bcddiv10, pos result[%d] = %d does not " "match expected_result[%d] = %d\n", i, result[i], i, exp_result[i]); #else abort(); #endif } /* result should be positive */ if ((result[0] & 0xF) != BCD_POS0) #if DEBUG printf("ERROR: __builtin_bcddiv10 sign, result is %d. Does not match " "expected_result = %d\n", result[0] & 0xF, BCD_POS1); #else abort(); #endif value_a = 1020304; exp_result_d128 = 1020304; a = num2bcd(value_a, 0); conv.ch = a; conv.d128 = __builtin_bcd2dfp (a); result_d128 = conv.d128; if (result_d128 != exp_result_d128) #if DEBUG printf("ERROR: __builtin_bcd2dfp, result does not match expected_result." "\n"); #else abort(); #endif return 0; }