522 lines
11 KiB
C
522 lines
11 KiB
C
/* { 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 <altivec.h>
|
|
|
|
#define DEBUG 0
|
|
|
|
#if DEBUG
|
|
#include <stdio.h>
|
|
#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;
|
|
}
|
|
|