(root)/
gcc-13.2.0/
gcc/
testsuite/
gcc.target/
arm/
fixed-point-exec.c
       1  /* { dg-do run { target { fixed_point } } } */
       2  /* { dg-options "-std=gnu99" } */
       3  
       4  /* Check basic arithmetic ops for ARM fixed-point/saturating operation support.
       5     Not target-independent since we make various assumptions about precision and
       6     magnitudes of various types.  */
       7  
       8  #include <stdlib.h>
       9  #include <stdio.h>
      10  #include <math.h>
      11  #include <stdfix.h>
      12  
      13  #define TEST(TYPE, OP, NAME, SUFFIX)				\
      14    TYPE NAME##SUFFIX (TYPE A, TYPE B)				\
      15      {								\
      16        return A OP B;						\
      17      }
      18  
      19  #define VARIANTS(TYPE, OP, NAME)				\
      20    TEST (short TYPE, OP, NAME, _short);				\
      21    TEST (TYPE, OP, NAME, _regular);				\
      22    TEST (long TYPE, OP, NAME, _long);				\
      23    TEST (_Sat short TYPE, OP, NAME, _sat_short);			\
      24    TEST (_Sat TYPE, OP, NAME, _sat_regular);			\
      25    TEST (_Sat long TYPE, OP, NAME, _sat_long);			\
      26    TEST (unsigned short TYPE, OP, NAME, _uns_short);		\
      27    TEST (unsigned TYPE, OP, NAME, _uns_regular);			\
      28    TEST (unsigned long TYPE, OP, NAME, _uns_long);		\
      29    TEST (unsigned _Sat short TYPE, OP, NAME, _uns_sat_short);	\
      30    TEST (unsigned _Sat TYPE, OP, NAME, _uns_sat_regular);	\
      31    TEST (unsigned _Sat long TYPE, OP, NAME, _uns_sat_long)
      32  
      33  VARIANTS (_Fract, +, plus_fract);
      34  VARIANTS (_Accum, +, plus_accum);
      35  VARIANTS (_Fract, -, minus_fract);
      36  VARIANTS (_Accum, -, minus_accum);
      37  VARIANTS (_Fract, *, mult_fract);
      38  VARIANTS (_Accum, *, mult_accum);
      39  VARIANTS (_Accum, /, div_accum);
      40  
      41  /* Inputs for signed add, multiply fractional tests.  */
      42  short _Fract sf_a = 0.9hr;
      43  short _Fract sf_b = -0.8hr;
      44  _Fract f_a = 0.9r;
      45  _Fract f_b = -0.8r;
      46  long _Fract lf_a = 0.9lr;
      47  long _Fract lf_b = -0.8lr;
      48  
      49  /* Inputs for signed subtract fractional tests.  */
      50  short _Fract sf_c = 0.7hr;
      51  short _Fract sf_d = 0.9hr;
      52  _Fract f_c = 0.7r;
      53  _Fract f_d = 0.9r;
      54  long _Fract lf_c = 0.7lr;
      55  long _Fract lf_d = 0.9lr;
      56  
      57  /* Inputs for unsigned add, subtract, multiply fractional tests.  */
      58  unsigned short _Fract usf_a = 0.4uhr;
      59  unsigned short _Fract usf_b = 0.3uhr;
      60  unsigned _Fract uf_a = 0.4ur;
      61  unsigned _Fract uf_b = 0.3ur;
      62  unsigned long _Fract ulf_a = 0.4ulr;
      63  unsigned long _Fract ulf_b = 0.3ulr;
      64  
      65  /* Inputs for saturating signed add tests.  */
      66  short _Sat _Fract sf_e = 0.8hr;
      67  short _Sat _Fract sf_f = 0.8hr;
      68  _Sat _Fract f_e = 0.8r;
      69  _Sat _Fract f_f = 0.8r;
      70  long _Sat _Fract lf_e = 0.8r;
      71  long _Sat _Fract lf_f = 0.8r;
      72  
      73  short _Sat _Fract sf_g = -0.8hr;
      74  short _Sat _Fract sf_h = -0.8hr;
      75  _Sat _Fract f_g = -0.8r;
      76  _Sat _Fract f_h = -0.8r;
      77  long _Sat _Fract lf_g = -0.8r;
      78  long _Sat _Fract lf_h = -0.8r;
      79  
      80  /* Inputs for saturating unsigned subtract tests.  */
      81  unsigned short _Sat _Fract usf_c = 0.3uhr;
      82  unsigned short _Sat _Fract usf_d = 0.4uhr;
      83  unsigned _Sat _Fract uf_c = 0.3ur;
      84  unsigned _Sat _Fract uf_d = 0.4ur;
      85  unsigned long _Sat _Fract ulf_c = 0.3ulr;
      86  unsigned long _Sat _Fract ulf_d = 0.4ulr;
      87  
      88  /* Inputs for signed accumulator tests.  */
      89  
      90  short _Accum sa_a = 1.25hk;
      91  short _Accum sa_b = -1.5hk;
      92  _Accum a_a = 100.25k;
      93  _Accum a_b = -100.5k;
      94  long _Accum la_a = 1000.25lk;
      95  long _Accum la_b = -1000.5lk;
      96  
      97  /* Inputs for unsigned accumulator tests.  */
      98  
      99  unsigned short _Accum usa_a = 2.5uhk;
     100  unsigned short _Accum usa_b = 1.75uhk;
     101  unsigned _Accum ua_a = 255.5uk;
     102  unsigned _Accum ua_b = 170.25uk;
     103  unsigned long _Accum ula_a = 1550.5ulk;
     104  unsigned long _Accum ula_b = 999.5ulk;
     105  
     106  /* Inputs for signed saturating accumulator tests.  */
     107  
     108  short _Sat _Accum sa_c = 240.0hk;
     109  short _Sat _Accum sa_d = 250.0hk;
     110  short _Sat _Accum sa_e = -240.0hk;
     111  short _Sat _Accum sa_f = -250.0hk;
     112  short _Sat _Accum sa_g = 0.5hk;
     113  
     114  _Sat _Accum a_c = 65000.0k;
     115  _Sat _Accum a_d = 20000.0k;
     116  _Sat _Accum a_e = -65000.0k;
     117  _Sat _Accum a_f = -20000.0k;
     118  _Sat _Accum a_g = 0.5k;
     119  
     120  long _Sat _Accum la_c = 3472883712.0lk;
     121  long _Sat _Accum la_d = 3456106496.0lk;
     122  long _Sat _Accum la_e = -3472883712.0lk;
     123  long _Sat _Accum la_f = -3456106496.0lk;
     124  long _Sat _Accum la_g = 0.5lk;
     125  
     126  /* Inputs for unsigned saturating accumulator tests.  */
     127  
     128  unsigned short _Sat _Accum usa_c = 250.0uhk;
     129  unsigned short _Sat _Accum usa_d = 240.0uhk;
     130  unsigned short _Sat _Accum usa_e = 0.5uhk;
     131  
     132  unsigned _Sat _Accum ua_c = 65000.0uk;
     133  unsigned _Sat _Accum ua_d = 20000.0uk;
     134  unsigned _Sat _Accum ua_e = 0.5uk;
     135  
     136  unsigned long _Sat _Accum ula_c = 3472883712.0ulk;
     137  unsigned long _Sat _Accum ula_d = 3456106496.0ulk;
     138  unsigned long _Sat _Accum ula_e = 0.5ulk;
     139  
     140  #define CHECK(FN, EXP) do {						     \
     141    if (fabs ((float) (FN) - (EXP)) > 0.05)				     \
     142      {									     \
     143        fprintf (stderr, "result for " #FN " (as float): %f\n", (double) (FN));\
     144        abort ();								     \
     145      }									     \
     146    } while (0)
     147  
     148  #define CHECK_EXACT(FN, EXP) do {					     \
     149    if ((FN) != (EXP))							     \
     150      {									     \
     151        fprintf (stderr, "result for " #FN " (as float): %f, should be %f\n",  \
     152  	       (double) (FN), (double) (EXP));				     \
     153        abort ();								     \
     154      }									     \
     155    } while (0)
     156  
     157  int
     158  main (int argc, char *argv[])
     159  {
     160    /* Fract/fract operations, non-saturating.  */
     161  
     162    CHECK (plus_fract_short (sf_a, sf_b), 0.1);
     163    CHECK (plus_fract_regular (f_a, f_b), 0.1);
     164    CHECK (plus_fract_long (lf_a, lf_b), 0.1);
     165  
     166    CHECK (plus_fract_uns_short (usf_a, usf_b), 0.7);
     167    CHECK (plus_fract_uns_regular (uf_a, uf_b), 0.7);
     168    CHECK (plus_fract_uns_long (ulf_a, ulf_b), 0.7);
     169  
     170    CHECK (minus_fract_short (sf_c, sf_d), -0.2);
     171    CHECK (minus_fract_regular (f_c, f_d), -0.2);
     172    CHECK (minus_fract_long (lf_c, lf_d), -0.2);
     173  
     174    CHECK (minus_fract_uns_short (usf_a, usf_b), 0.1);
     175    CHECK (minus_fract_uns_regular (uf_a, uf_b), 0.1);
     176    CHECK (minus_fract_uns_long (ulf_a, ulf_b), 0.1);
     177  
     178    CHECK (mult_fract_short (sf_a, sf_b), -0.72);
     179    CHECK (mult_fract_regular (f_a, f_b), -0.72);
     180    CHECK (mult_fract_long (lf_a, lf_b), -0.72);
     181  
     182    CHECK (mult_fract_uns_short (usf_a, usf_b), 0.12);
     183    CHECK (mult_fract_uns_regular (uf_a, uf_b), 0.12);
     184    CHECK (mult_fract_uns_long (ulf_a, ulf_b), 0.12);
     185  
     186    /* Fract/fract operations, saturating.  */
     187  
     188    CHECK (plus_fract_sat_short (sf_e, sf_f), 1.0);
     189    CHECK (plus_fract_sat_regular (f_e, f_f), 1.0);
     190    CHECK (plus_fract_sat_long (lf_e, lf_f), 1.0);
     191  
     192    CHECK (plus_fract_sat_short (sf_g, sf_h), -1.0);
     193    CHECK (plus_fract_sat_regular (f_g, f_h), -1.0);
     194    CHECK (plus_fract_sat_long (lf_g, lf_h), -1.0);
     195    
     196    CHECK (plus_fract_uns_sat_short (sf_e, sf_f), 1.0);
     197    CHECK (plus_fract_uns_sat_regular (f_e, f_f), 1.0);
     198    CHECK (plus_fract_uns_sat_long (lf_e, lf_f), 1.0);
     199  
     200    CHECK (plus_fract_sat_short (sf_a, sf_b), 0.1);
     201    CHECK (plus_fract_sat_regular (f_a, f_b), 0.1);
     202    CHECK (plus_fract_sat_long (lf_a, lf_b), 0.1);
     203    
     204    CHECK (plus_fract_uns_sat_short (usf_a, usf_b), 0.7);
     205    CHECK (plus_fract_uns_sat_regular (uf_a, uf_b), 0.7);
     206    CHECK (plus_fract_uns_sat_long (ulf_a, ulf_b), 0.7);
     207  
     208    CHECK (minus_fract_uns_sat_short (usf_c, usf_d), 0.0);
     209    CHECK (minus_fract_uns_sat_regular (uf_c, uf_d), 0.0);
     210    CHECK (minus_fract_uns_sat_short (ulf_c, ulf_d), 0.0);
     211    
     212    CHECK (minus_fract_sat_short (sf_c, sf_d), -0.2);
     213    CHECK (minus_fract_sat_regular (f_c, f_d), -0.2);
     214    CHECK (minus_fract_sat_long (lf_c, lf_d), -0.2);
     215  
     216    /* Accum/accum operations, non-saturating.  */
     217  
     218    CHECK (plus_accum_short (sa_a, sa_b), -0.25);
     219    CHECK (plus_accum_regular (a_a, a_b), -0.25);
     220    CHECK (plus_accum_long (la_a, la_b), -0.25);
     221  
     222    CHECK (minus_accum_short (sa_a, sa_b), 2.75);
     223    CHECK (minus_accum_regular (a_a, a_b), 200.75);
     224    CHECK (minus_accum_long (la_a, la_b), 2000.75);
     225    
     226    CHECK (mult_accum_short (sa_a, sa_b), -1.875);
     227    CHECK (mult_accum_regular (a_a, a_b), -10075.125);
     228    CHECK (mult_accum_long (la_a, la_b), -1000750.125);
     229  
     230    CHECK (div_accum_short (sa_a, sa_b), -1.25/1.5);
     231    CHECK (div_accum_regular (a_a, a_b), -100.25/100.5);
     232    CHECK (div_accum_long (la_a, la_b), -1000.25/1000.5);
     233  
     234    /* Unsigned accum/accum operations, non-saturating.  */
     235    
     236    CHECK (plus_accum_uns_short (usa_a, usa_b), 4.25);
     237    CHECK (plus_accum_uns_regular (ua_a, ua_b), 425.75);
     238    CHECK (plus_accum_uns_long (ula_a, ula_b), 2550.0);
     239  
     240    CHECK (minus_accum_uns_short (usa_a, usa_b), 0.75);
     241    CHECK (minus_accum_uns_regular (ua_a, ua_b), 85.25);
     242    CHECK (minus_accum_uns_long (ula_a, ula_b), 551.0);
     243    
     244    CHECK (mult_accum_uns_short (usa_a, usa_b), 4.375);
     245    CHECK (mult_accum_uns_regular (ua_a, ua_b), 43498.875);
     246    CHECK (mult_accum_uns_long (ula_a, ula_b), 1549724.75);
     247  
     248    CHECK (div_accum_uns_short (usa_a, usa_b), 2.5/1.75);
     249    CHECK (div_accum_uns_regular (ua_a, ua_b), 255.5/170.25);
     250    CHECK (div_accum_uns_long (ula_a, ula_b), 1550.5/999.5);
     251  
     252    /* Signed accum/accum operations, saturating.  */
     253    
     254    CHECK_EXACT (plus_accum_sat_short (sa_c, sa_d), SACCUM_MAX);
     255    CHECK_EXACT (plus_accum_sat_short (sa_e, sa_f), SACCUM_MIN);
     256    CHECK_EXACT (plus_accum_sat_regular (a_c, a_d), ACCUM_MAX);
     257    CHECK_EXACT (plus_accum_sat_regular (a_e, a_f), ACCUM_MIN);
     258    CHECK_EXACT (plus_accum_sat_long (la_c, la_d), LACCUM_MAX);
     259    CHECK_EXACT (plus_accum_sat_long (la_e, la_f), LACCUM_MIN);
     260  
     261    CHECK_EXACT (minus_accum_sat_short (sa_e, sa_d), SACCUM_MIN);
     262    CHECK_EXACT (minus_accum_sat_short (sa_c, sa_f), SACCUM_MAX);
     263    CHECK_EXACT (minus_accum_sat_regular (a_e, a_d), ACCUM_MIN);
     264    CHECK_EXACT (minus_accum_sat_regular (a_c, a_f), ACCUM_MAX);
     265    CHECK_EXACT (minus_accum_sat_long (la_e, la_d), LACCUM_MIN);
     266    CHECK_EXACT (minus_accum_sat_long (la_c, la_f), LACCUM_MAX);
     267  
     268    CHECK_EXACT (mult_accum_sat_short (sa_c, sa_d), SACCUM_MAX);
     269    CHECK_EXACT (mult_accum_sat_short (sa_c, sa_e), SACCUM_MIN);
     270    CHECK_EXACT (mult_accum_sat_regular (a_c, a_d), ACCUM_MAX);
     271    CHECK_EXACT (mult_accum_sat_regular (a_c, a_e), ACCUM_MIN);
     272    CHECK_EXACT (mult_accum_sat_long (la_c, la_d), LACCUM_MAX);
     273    CHECK_EXACT (mult_accum_sat_long (la_c, la_e), LACCUM_MIN);
     274    
     275    CHECK_EXACT (div_accum_sat_short (sa_d, sa_g), SACCUM_MAX);
     276    CHECK_EXACT (div_accum_sat_short (sa_e, sa_g), SACCUM_MIN);
     277    CHECK_EXACT (div_accum_sat_regular (a_c, a_g), ACCUM_MAX);
     278    CHECK_EXACT (div_accum_sat_regular (a_e, a_g), ACCUM_MIN);
     279    CHECK_EXACT (div_accum_sat_long (la_d, la_g), LACCUM_MAX);
     280    CHECK_EXACT (div_accum_sat_long (la_e, la_g), LACCUM_MIN);
     281  
     282    /* Unsigned accum/accum operations, saturating.  */
     283  
     284    CHECK_EXACT (plus_accum_uns_sat_short (usa_c, usa_d), USACCUM_MAX);
     285    CHECK_EXACT (plus_accum_uns_sat_regular (ua_c, ua_d), UACCUM_MAX);
     286    CHECK_EXACT (plus_accum_uns_sat_long (ula_c, ula_d), ULACCUM_MAX);
     287    
     288    CHECK_EXACT (minus_accum_uns_sat_short (usa_d, usa_c), 0uhk);
     289    CHECK_EXACT (minus_accum_uns_sat_regular (ua_d, ua_c), 0uk);
     290    CHECK_EXACT (minus_accum_uns_sat_long (ula_d, ula_c), 0ulk);
     291  
     292    CHECK_EXACT (mult_accum_uns_sat_short (usa_c, usa_d), USACCUM_MAX);
     293    CHECK_EXACT (mult_accum_uns_sat_regular (ua_c, ua_d), UACCUM_MAX);
     294    CHECK_EXACT (mult_accum_uns_sat_long (ula_c, ula_d), ULACCUM_MAX);
     295  
     296    CHECK_EXACT (div_accum_uns_sat_short (usa_c, usa_e), USACCUM_MAX);
     297    CHECK_EXACT (div_accum_uns_sat_regular (ua_c, ua_e), UACCUM_MAX);
     298    CHECK_EXACT (div_accum_uns_sat_long (ula_c, ula_e), ULACCUM_MAX);
     299  
     300    return 0;
     301  }