1  /* { dg-do run } */
       2  /* { dg-require-effective-target int128 } */
       3  /* { dg-require-effective-target power10_hw } */
       4  /* { dg-options "-mdejagnu-cpu=power10 -O2 -save-temps" } */
       5  /* { dg-final { scan-assembler-times {\mbcdadd\M} 7 } } */
       6  /* { dg-final { scan-assembler-times {\mbcdsub\M} 18 } } */
       7  /* { dg-final { scan-assembler-times {\mbcds\M} 2 } } */
       8  /* { dg-final { scan-assembler-times {\mdenbcdq\M} 1 } } */
       9  
      10  #include <altivec.h>
      11  
      12  #define DEBUG 0
      13  
      14  #if DEBUG
      15  #include <stdio.h>
      16  #endif
      17  
      18  
      19  #define BCD_POS0  12    //  0xC
      20  #define BCD_POS1  15    //  0xF
      21  #define BCD_NEG   13    //  0xD
      22  
      23  void abort (void);
      24  
      25    union conv_t
      26      {
      27        _Decimal128 d128;
      28        vector  unsigned char ch;
      29        vector  long long unsigned int vllui;
      30      } conv;
      31    
      32  _Decimal128 convert_vec_char (vector unsigned char a)
      33  {
      34    union conv_t conv;
      35    _Decimal128 result;
      36    
      37    conv.ch = a;
      38    result = conv.d128;
      39    return result;
      40  }
      41  			      
      42  vector unsigned char maxbcd(unsigned int sign)
      43  {
      44    vector unsigned char result;
      45    int i;
      46  
      47    for (i = 15; i > 0; i--)
      48      result[i] = 0x99;
      49  
      50    result[0] = sign << 4 | 0x9;
      51  }
      52  
      53  vector unsigned char num2bcd(long int a, int encoding)
      54  {
      55    int i;
      56    unsigned int hi, low, sign;
      57    
      58    vector unsigned char result;
      59  
      60    if (a > 0) {
      61      if (encoding == 0)
      62        sign = BCD_POS0;
      63      else
      64        sign = BCD_POS1;
      65  
      66    } else {
      67      sign = BCD_NEG;
      68      a = -a;
      69    }
      70  
      71    hi = a % 10;   // 1st digit
      72    a = a / 10;
      73    result[0] = hi << 4| sign;
      74  
      75    for (i = 1; i < 16; i++)
      76      {
      77        low = a % 10;
      78        a = a / 10;
      79        hi = a % 10;
      80        a = a / 10;
      81        result[i] = hi << 4 | low;
      82      }
      83  
      84  
      85    return result;
      86  }
      87  
      88  int main ()
      89  {
      90    int i;
      91    long int value_a, value_b, value_result;
      92    vector unsigned char a, b, result, exp_result;
      93    _Decimal128 result_d128, exp_result_d128;
      94  
      95    /* Make a and b positive BCD numbers */
      96    value_a = 1020304;
      97    a = num2bcd(value_a, 0);
      98  
      99    value_b = 101010;
     100    b = num2bcd(value_b, 0);
     101   
     102    value_result = value_a + value_b;
     103    exp_result = num2bcd(value_result, 0);
     104    
     105    result = __builtin_bcdadd (a, b, 0);
     106  
     107    for (i = 0; i < 16; i++)
     108      if (exp_result[i] != result[i]) {
     109  
     110  #if DEBUG
     111        printf("ERROR: __builtin_bcdadd result[%d] = %d does not match "
     112  	     "expected_result[%d] = %d\n",
     113  	     i, result[i], i, exp_result[i]);
     114  #else
     115        abort();
     116  #endif
     117      }
     118  
     119    /* result should be positive */
     120    if ((result[0] & 0xF) != BCD_POS0)
     121  #if DEBUG
     122        printf("ERROR: __builtin_bcdadd sign of result is %d.  Does not match "
     123  	     "expected_result = %d\n",
     124  	     result[0] & 0xF, BCD_POS0);
     125  #else
     126        abort();
     127  #endif
     128  
     129    /* Make a and b positive BCD numbers using alternate positive encoding.  */
     130    value_a = 1030507;
     131    a = num2bcd(value_a, 1);
     132  
     133    value_b = 204060;
     134    b = num2bcd(value_b, 1);
     135  
     136    value_result = value_a + value_b;
     137    exp_result = num2bcd(value_result, 1);
     138    
     139    result = __builtin_bcdadd (a, b, 1);
     140  
     141    for (i = 0; i < 16; i++)
     142      if (exp_result[i] != result[i]) {
     143  #if DEBUG
     144        printf("ERROR: __builtin_bcdadd result[%d] = %d does not match "
     145  	     "expected_result[%d] = %d\n",
     146  	     i, result[i], i, exp_result[i]);
     147  #else
     148        abort();
     149  #endif
     150      }
     151  
     152    /* Result should be positive, alternate encoding.  */
     153    if ((result[0] & 0xF) != BCD_POS1)
     154  #if DEBUG
     155      printf("ERROR: __builtin_bcdadd sign of result is %d.  Does not "
     156  	   "match expected_result = %d\n",
     157  	     result[0] & 0xF, BCD_POS1);
     158  #else
     159      abort();
     160  #endif
     161  
     162    /* Make a and b negative BCD numbers */
     163    value_a = -1030507;
     164    a = num2bcd(value_a, 0);
     165  
     166    value_b = -1010101;
     167    b = num2bcd(value_b, 0);
     168  
     169    value_result = value_a + value_b;
     170    exp_result = num2bcd(value_result, 0);
     171    
     172    result = __builtin_bcdadd (a, b, 0);
     173  
     174    for (i = 0; i < 16; i++)
     175      if (exp_result[i]  != result[i]) {
     176  #if DEBUG
     177        printf("ERROR: __builtin_bcdadd, neg result[%d] = %d does not match "
     178  	     "expected_result[%d] = %d\n",
     179  	     i, result[i], i, exp_result[i]);
     180  #else
     181        abort();
     182  #endif
     183      }
     184  
     185    /* result should be negative */
     186    if ((result[0] & 0xF) != BCD_NEG)
     187  #if DEBUG
     188      printf("ERROR: __builtin_bcdadd sign, neg of result is %d.  Does not "
     189  	   "match expected_result = %d\n",
     190  	     result[0] & 0xF, BCD_NEG);
     191  #else
     192      abort();
     193  #endif
     194  
     195   
     196    /* Make a negative, b positive BCD numbers */
     197    value_a = -1030507;
     198    a = num2bcd(value_a, 0);
     199  
     200    value_b = 1010101;
     201    b = num2bcd(value_b, 0);
     202  
     203    value_result = value_a - value_b;
     204    exp_result = num2bcd(value_result, 0);
     205    
     206    result = __builtin_bcdsub (a, b, 0);
     207  
     208    for (i = 0; i < 16; i++)
     209      if (exp_result[i] != result[i]) {
     210  #if DEBUG
     211        printf("ERROR: __builtin_bcdsub, neg result[%d] = %d does not match "
     212  	     "expected_result[%d] = %d\n",
     213  	     i, result[i], i, exp_result[i]);
     214  #else
     215        abort();
     216  #endif
     217      }
     218  
     219    /* result should be positive, alt encoding */
     220    if ((result[0] & 0xF) != BCD_NEG)
     221  #if DEBUG
     222      printf("ERROR: __builtin_bcdadd sign, of result is %d.  Does not match "
     223  	   "expected_result = %d\n",
     224  	     result[0] & 0xF, BCD_NEG);
     225  #else
     226      abort();
     227  #endif
     228  
     229    /* Make a and b positive BCD numbers */
     230    value_a = 1030507;
     231    a = num2bcd(value_a, 1);
     232  
     233    value_b = 1010101;
     234    b = num2bcd(value_b, 1);
     235  
     236    value_result = value_a - value_b;
     237    exp_result = num2bcd(value_result, 1);
     238    
     239    result = __builtin_bcdsub (a, b, 1);
     240  
     241    for (i = 0; i < 16; i++)
     242      if (exp_result[i] != result[i]) {
     243  #if DEBUG
     244        printf("ERROR:carll __builtin_bcdsub, pos result[%d] = %d does not "
     245  	     "match expected_result[%d] = %d\n",
     246  	     i, result[i], i, exp_result[i]);
     247  #else
     248        abort();
     249  #endif
     250      }
     251  
     252    /* result should be positive */
     253    if ((result[0] & 0xF) != BCD_POS1)
     254  #if DEBUG
     255      printf("ERROR: __builtin_bcdsub sign, result is %d.  Does not match "
     256  	   "expected_result = %d\n",
     257  	     result[0] & 0xF, BCD_POS1);
     258  #else
     259        abort();
     260  #endif
     261  
     262    /* Test overflow add and subtract.  */
     263    a = maxbcd(BCD_POS0);
     264    b = maxbcd(BCD_POS0);
     265  
     266    if(__builtin_bcdadd_ofl (a, b, 0) == 0)
     267  #if DEBUG
     268      printf("ERROR: __builtin_bcdadd did not overflow as expected\n");
     269  #else
     270      abort();
     271  #endif
     272  
     273    value_a = 99999999;
     274    a = num2bcd(value_a, 0);
     275  
     276    value_b = 999999999;
     277    b = num2bcd(value_b, 0);
     278  
     279    if(__builtin_bcdadd_ofl (a, b, 0))
     280  #if DEBUG
     281      printf("ERROR: __builtin_bcdadd unexpectedly overflowed\n");
     282  #else
     283      abort();
     284  #endif
     285  
     286    a = maxbcd(BCD_NEG);
     287    b = maxbcd(BCD_NEG);
     288  
     289    if (__builtin_bcdsub_ofl (a, b, 0) == 0)
     290  #if DEBUG
     291      printf("ERROR: __builtin_bcdsub did not overflow as expected\n");
     292  #else
     293      abort();
     294  #endif
     295  
     296    value_a = -99999999;
     297    a = num2bcd(value_a, 0);
     298  
     299    value_b = -999999999;
     300    b = num2bcd(value_b, 0);
     301  
     302    if (__builtin_bcdsub_ofl (a, b, 0))
     303  #if DEBUG
     304      printf("ERROR: __builtin_bcdsub unexpectedly overflowed\n");
     305  #else
     306      abort();
     307  #endif
     308  
     309    /* Test arguments for valid/invalid */
     310    if (__builtin_bcdinvalid (a))
     311  #if DEBUG
     312      printf("ERROR: __builtin_invalid input is unexpectedly invalid.\n");
     313  #else
     314      abort();
     315  #endif
     316  
     317    a[3] = 0xBB;     /* an invalid BCD digit */
     318    if (!__builtin_bcdinvalid (a))
     319  #if DEBUG
     320      printf("ERROR: __builtin_invalid input is unexpectedly valid.\n");
     321  #else
     322      abort();
     323  #endif
     324  
     325    value_a = 1020304;
     326    a = num2bcd(value_a, 0);
     327  
     328    value_b = 101010;
     329    b = num2bcd(value_b, 0);
     330  
     331    /* Test equality */
     332    if (__builtin_bcdcmpeq (a, b))
     333  #if DEBUG
     334      printf("ERROR: __builtin__bcdcmpeq result is unexpectedly 1.\n");
     335  #else
     336      abort();
     337  #endif
     338  
     339    if (!__builtin_bcdcmpeq (a, a))
     340  #if DEBUG
     341      printf("ERROR: __builtin__bcdcmpeq result is unexpectedly 0.\n");
     342  #else
     343      abort();
     344  #endif
     345  
     346  
     347    /* Test a greater then b, inputs already setup this way.  */
     348    if (!__builtin_bcdcmpgt (a, b))
     349  #if DEBUG
     350      printf("ERROR: __builtin__bcdcmpgt result is unexpectedly 0.\n");
     351  #else
     352      abort();
     353  #endif
     354  
     355    if (__builtin_bcdcmpgt (b, a))
     356  #if DEBUG
     357      printf("ERROR: __builtin__bcdcmpgt result is unexpectedly 1.\n");
     358  #else
     359      abort();
     360  #endif
     361  
     362    if (__builtin_bcdcmpgt (a, a))
     363  #if DEBUG
     364      printf("ERROR: __builtin__bcdcmpgt input equal, result is unexpectedly "
     365  	   "1.\n");
     366  #else
     367      abort();
     368  #endif
     369  
     370  
     371    if (!__builtin_bcdcmpge (a, b))
     372  #if DEBUG
     373      printf("ERROR: __builtin__bcdcmpge result is unexpectedly 0.\n");
     374  #else
     375      abort();
     376  #endif
     377  
     378    if (__builtin_bcdcmpge (b, a))
     379  #if DEBUG
     380      printf("ERROR: __builtin__bcdcmpge result is unexpectedly 1.\n");
     381  #else
     382      abort();
     383  #endif
     384  
     385    if (!__builtin_bcdcmpge (b, b))
     386  #if DEBUG
     387      printf("ERROR: __builtin__bcdcmpge inputs equal result is unexpectedly "
     388  	   "0.\n");
     389  #else
     390      abort();
     391  #endif
     392  
     393    /* Test a less then b.  */
     394    value_a = 101010;
     395    a = num2bcd(value_a, 0);
     396    value_b = 1020304;
     397    b = num2bcd(value_b, 0);
     398  
     399    if (!__builtin_bcdcmplt (a, b))
     400  #if DEBUG
     401      printf("ERROR: __builtin__bcdcmplt result is unexpectedly 0.\n");
     402  #else
     403      abort();
     404  #endif
     405  
     406    if (__builtin_bcdcmplt (b, a))
     407  #if DEBUG
     408      printf("ERROR: __builtin__bcdcmplt result is unexpectedly 1.\n");
     409  #else
     410      abort();
     411  #endif
     412  
     413    if (__builtin_bcdcmplt (b, b))
     414  #if DEBUG
     415      printf("ERROR: __builtin__bcdcmplt inputs equal result is unexpectedly "
     416  	   "1.\n");
     417  #else
     418      abort();
     419  #endif
     420  
     421  
     422    if (!__builtin_bcdcmple (a, b))
     423  #if DEBUG
     424      printf("ERROR: __builtin__bcdcmple result is unexpectedly 0.\n");
     425  #else
     426      abort();
     427  #endif
     428  
     429    if (__builtin_bcdcmple (b, a))
     430  #if DEBUG
     431      printf("ERROR: __builtin__bcdcmple result is unexpectedly 1.\n");
     432  #else
     433      abort();
     434  #endif
     435  
     436    if (!__builtin_bcdcmple (a, a))
     437  #if DEBUG
     438      printf("ERROR: __builtin__bcdcmple inputs equal result is unexpectedly "
     439  	   "0.\n");
     440  #else
     441      abort();
     442  #endif
     443  
     444    /* Test multipy 10 */
     445    value_a = 1020304;
     446    a = num2bcd(value_a, 0);
     447  
     448    value_result = value_a * 10;
     449    exp_result = num2bcd(value_result, 0);
     450    
     451    result = __builtin_bcdmul10 (a);
     452  
     453    for (i = 0; i < 16; i++)
     454      if (exp_result[i] != result[i]) {
     455  #if DEBUG
     456        printf("ERROR:carll __builtin_bcdmul10, pos result[%d] = %d does not "
     457  	     "match expected_result[%d] = %d\n",
     458  	     i, result[i], i, exp_result[i]);
     459  #else
     460        abort();
     461  #endif
     462      }
     463  
     464    /* result should be positive */
     465    if ((result[0] & 0xF) != BCD_POS0)
     466  #if 0
     467      printf("ERROR: __builtin_bcdmul10 sign, result is %d.  Does not match "
     468  	   "expected_result = %d\n",
     469  	   result[0] & 0xF, BCD_POS1);
     470  #else
     471      abort();
     472  #endif
     473  
     474    /* Test divide 10 */
     475    value_a = 1020304;
     476    a = num2bcd(value_a, 0);
     477  
     478    value_result = value_a / 10;
     479    exp_result = num2bcd(value_result, 0);
     480    
     481    result = __builtin_bcddiv10 (a);
     482  
     483    for (i = 0; i < 16; i++)
     484      if (exp_result[i] != result[i]) {
     485  #if DEBUG
     486        printf("ERROR:carll __builtin_bcddiv10, pos result[%d] = %d does not "
     487  	     "match expected_result[%d] = %d\n",
     488  	     i, result[i], i, exp_result[i]);
     489  #else
     490        abort();
     491  #endif
     492      }
     493  
     494    /* result should be positive */
     495    if ((result[0] & 0xF) != BCD_POS0)
     496  #if DEBUG
     497      printf("ERROR: __builtin_bcddiv10 sign, result is %d.  Does not match "
     498  	   "expected_result = %d\n",
     499  	     result[0] & 0xF, BCD_POS1);
     500  #else
     501      abort();
     502  #endif
     503  
     504     value_a = 1020304;
     505     exp_result_d128 = 1020304;
     506     a = num2bcd(value_a, 0);
     507  
     508     conv.ch = a;
     509     conv.d128 = __builtin_bcd2dfp (a);
     510     result_d128 = conv.d128;
     511     
     512     if (result_d128 != exp_result_d128)
     513  #if DEBUG
     514       printf("ERROR: __builtin_bcd2dfp, result does not match expected_result."
     515  	    "\n");
     516  #else
     517       abort();
     518  #endif
     519       return 0;
     520  }
     521