1  /* { dg-do run { target arm_eabi } } */
       2  /* { dg-options "" } */
       3  
       4  /* This file tests most of the non-C++ run-time helper functions
       5     described in Section 4 of the "Run-Time ABI for the ARM
       6     Architecture".  These are basic tests; they do not try to validate
       7     all of the corner cases in these routines.  
       8  
       9     The functions not tested here are:
      10  
      11       __aeabi_cdcmpeq
      12       __aeabi_cdcmple
      13       __aeabi_cdrcmple
      14       __aeabi_cfcmpeq
      15       __aeabi_cfcmple
      16       __aeabi_cfrcmple
      17       __aeabi_ldivmod
      18       __aeabi_uldivmod
      19       __aeabi_idivmod
      20       __aeabi_uidivmod
      21  
      22     These functions have non-standard calling conventions that would
      23     require the use of inline assembly to test.  It would be good to
      24     add such tests, but they have not yet been implemented.  
      25  
      26     There are also no tests for the "division by zero", "memory copying,
      27     clearing, and setting" functions.  */
      28  
      29  #include <stdio.h>
      30  #include <stdlib.h>
      31  #include <math.h>
      32  
      33  /* All these functions are defined to use the base ABI, so use the
      34     attribute to ensure the tests use the base ABI to call them even
      35     when the VFP ABI is otherwise in effect.  */
      36  #define PCS __attribute__((pcs("aapcs")))
      37  
      38  #define decl_float(code, type)						\
      39    extern type __aeabi_ ## code ## add (type, type) PCS;			\
      40    extern type __aeabi_ ## code ## div (type, type) PCS;			\
      41    extern type __aeabi_ ## code ## mul (type, type) PCS;			\
      42    extern type __aeabi_ ## code ## neg (type) PCS;			\
      43    extern type __aeabi_ ## code ## rsub (type, type) PCS;		\
      44    extern type __aeabi_ ## code ## sub (type, type) PCS;			\
      45    extern int __aeabi_ ## code ## cmpeq (type, type) PCS;		\
      46    extern int __aeabi_ ## code ## cmplt (type, type) PCS;		\
      47    extern int __aeabi_ ## code ## cmple (type, type) PCS;		\
      48    extern int __aeabi_ ## code ## cmpge (type, type) PCS;		\
      49    extern int __aeabi_ ## code ## cmpgt (type, type) PCS;		\
      50    extern int __aeabi_ ## code ## cmpun (type, type) PCS;		\
      51    extern int __aeabi_ ## code ## 2iz (type) PCS;			\
      52    extern unsigned int __aeabi_ ## code ## 2uiz (type) PCS;		\
      53    extern long long __aeabi_ ## code ## 2lz (type) PCS;			\
      54    extern unsigned long long __aeabi_ ## code ## 2ulz (type) PCS;	\
      55    extern type __aeabi_i2 ## code (int) PCS;				\
      56    extern type __aeabi_ui2 ## code (int) PCS;				\
      57    extern type __aeabi_l2 ## code (long long) PCS;			\
      58    extern type __aeabi_ul2 ## code (unsigned long long) PCS;		\
      59  									\
      60    type code ## zero = 0.0;						\
      61    type code ## one = 1.0;						\
      62    type code ## two = 2.0;						\
      63    type code ## four = 4.0;						\
      64    type code ## minus_one = -1.0;					\
      65    type code ## minus_two = -2.0;					\
      66    type code ## minus_four = -4.0;					\
      67    type code ## epsilon = 1E-32;						\
      68    type code ## NaN = 0.0 / 0.0;
      69  
      70  decl_float (d, double)
      71  decl_float (f, float)
      72  
      73  extern float __aeabi_d2f (double) PCS;
      74  extern double __aeabi_f2d (float) PCS;
      75  extern long long __aeabi_lmul (long long, long long);
      76  extern long long __aeabi_llsl (long long, int);
      77  extern long long __aeabi_llsr (long long, int);
      78  extern long long __aeabi_lasr (long long, int);
      79  extern int __aeabi_lcmp (long long, long long);
      80  extern int __aeabi_ulcmp (unsigned long long, unsigned long long);
      81  extern int __aeabi_idiv (int, int);
      82  extern unsigned int __aeabi_uidiv (unsigned int, unsigned int);
      83  extern int __aeabi_uread4 (void *);
      84  extern int __aeabi_uwrite4 (int, void *);
      85  extern long long __aeabi_uread8 (void *);
      86  extern long long __aeabi_uwrite8 (long long, void *);
      87  
      88  #define eq(a, b, type, abs, epsilon, format)			\
      89    {								\
      90      type a1;							\
      91      type b1;							\
      92  								\
      93      a1 = a;							\
      94      b1 = b;							\
      95      if (abs (a1 - b1) > epsilon)				\
      96      {								\
      97        fprintf (stderr, "%d: Test %s == %s\n", __LINE__, #a, #b);	\
      98        fprintf (stderr, "%d: " format " != " format "\n",	\
      99  	       __LINE__, a1, b1);				\
     100        abort ();							\
     101      }								\
     102    }
     103  
     104  #define ieq(a, b) eq (a, b, int, abs, 0, "%d")
     105  #define ueq(a, b) eq (a, b, unsigned int, abs, 0, "%u")
     106  #define leq(a, b) eq (a, b, long long, abs, 0, "%lld")
     107  #define uleq(a, b) eq (a, b, unsigned long long, abs, 0, "%llu")
     108  #define feq(a, b) eq (a, b, float, fabs, fepsilon, "%f")
     109  #define deq(a, b) eq (a, b, double, fabs, depsilon, "%g")
     110  
     111  #define NUM_CMP_VALUES 6
     112  
     113  /* Values picked to cover a range of small, large, positive and negative.  */
     114  static unsigned int cmp_val[NUM_CMP_VALUES] = 
     115  {
     116    0,
     117    1,
     118    0x40000000,
     119    0x80000000,
     120    0xc0000000,
     121    0xffffffff
     122  };
     123  
     124  /* All combinations for each of the above values. */
     125  #define ulcmp(l, s, m) \
     126      s, l, l, l, l, l,  m, s, l, l, l, l, \
     127      m, m, s, l, l, l,  m, m, m, s, l, l, \
     128      m, m, m, m, s, l,  m, m, m, m, m, s
     129  
     130  #define lcmp(l, s, m) \
     131      s, l, l, m, m, m,  m, s, l, m, m, m, \
     132      m, m, s, m, m, m,  l, l, l, s, l, l, \
     133      l, l, l, m, s, l,  l, l, l, m, m, s
     134  
     135  /* All combinations of the above for high/low words.  */
     136  static int lcmp_results[] =
     137  {
     138    lcmp(ulcmp(-1, -1, -1), ulcmp(-1, 0, 1), ulcmp(1, 1, 1))
     139  };
     140  
     141  static int ulcmp_results[] =
     142  {
     143    ulcmp(ulcmp(-1, -1, -1), ulcmp(-1, 0, 1), ulcmp(1, 1, 1))
     144  };
     145  
     146  static int signof(int i)
     147  {
     148    if (i < 0)
     149      return -1;
     150  
     151    if (i == 0)
     152      return 0;
     153  
     154    return 1;
     155  }
     156  
     157  int main () {
     158    unsigned char bytes[256];
     159    int i, j, k, n;
     160    int *result;
     161  
     162    /* Table 2.  Double-precision floating-point arithmetic.  */
     163    deq (__aeabi_dadd (dzero, done), done);
     164    deq (__aeabi_dadd (done, done), dtwo);
     165    deq (__aeabi_ddiv (dminus_four, dminus_two), dtwo);
     166    deq (__aeabi_ddiv (dminus_two, dtwo), dminus_one);
     167    deq (__aeabi_dmul (dtwo, dtwo), dfour);
     168    deq (__aeabi_dmul (dminus_one, dminus_two), dtwo);
     169    deq (__aeabi_dneg (dminus_one), done);
     170    deq (__aeabi_dneg (dfour), dminus_four);
     171    deq (__aeabi_drsub (done, dzero), dminus_one);
     172    deq (__aeabi_drsub (dtwo, dminus_two), dminus_four);
     173    deq (__aeabi_dsub (dzero, done), dminus_one);
     174    deq (__aeabi_dsub (dminus_two, dtwo), dminus_four);
     175  
     176    /* Table 3.  Double-precision floating-point comparisons.  */
     177    ieq (__aeabi_dcmpeq (done, done), 1);
     178    ieq (__aeabi_dcmpeq (done, dzero), 0);
     179    ieq (__aeabi_dcmpeq (dNaN, dzero), 0);
     180    ieq (__aeabi_dcmpeq (dNaN, dNaN), 0);
     181  
     182    ieq (__aeabi_dcmplt (dzero, done), 1);
     183    ieq (__aeabi_dcmplt (done, dzero), 0);
     184    ieq (__aeabi_dcmplt (dzero, dzero), 0);
     185    ieq (__aeabi_dcmplt (dzero, dNaN), 0);
     186    ieq (__aeabi_dcmplt (dNaN, dNaN), 0);
     187  
     188    ieq (__aeabi_dcmple (dzero, done), 1);
     189    ieq (__aeabi_dcmple (done, dzero), 0);
     190    ieq (__aeabi_dcmple (dzero, dzero), 1);
     191    ieq (__aeabi_dcmple (dzero, dNaN), 0);
     192    ieq (__aeabi_dcmple (dNaN, dNaN), 0);
     193  
     194    ieq (__aeabi_dcmpge (dzero, done), 0);
     195    ieq (__aeabi_dcmpge (done, dzero), 1);
     196    ieq (__aeabi_dcmpge (dzero, dzero), 1);
     197    ieq (__aeabi_dcmpge (dzero, dNaN), 0);
     198    ieq (__aeabi_dcmpge (dNaN, dNaN), 0);
     199  
     200    ieq (__aeabi_dcmpgt (dzero, done), 0);
     201    ieq (__aeabi_dcmpgt (done, dzero), 1);
     202    ieq (__aeabi_dcmplt (dzero, dzero), 0);
     203    ieq (__aeabi_dcmpgt (dzero, dNaN), 0);
     204    ieq (__aeabi_dcmpgt (dNaN, dNaN), 0);
     205  
     206    ieq (__aeabi_dcmpun (done, done), 0);
     207    ieq (__aeabi_dcmpun (done, dzero), 0);
     208    ieq (__aeabi_dcmpun (dNaN, dzero), 1);
     209    ieq (__aeabi_dcmpun (dNaN, dNaN), 1);
     210  
     211    /* Table 4.  Single-precision floating-point arithmetic.  */
     212    feq (__aeabi_fadd (fzero, fone), fone);
     213    feq (__aeabi_fadd (fone, fone), ftwo);
     214    feq (__aeabi_fdiv (fminus_four, fminus_two), ftwo);
     215    feq (__aeabi_fdiv (fminus_two, ftwo), fminus_one);
     216    feq (__aeabi_fmul (ftwo, ftwo), ffour);
     217    feq (__aeabi_fmul (fminus_one, fminus_two), ftwo);
     218    feq (__aeabi_fneg (fminus_one), fone);
     219    feq (__aeabi_fneg (ffour), fminus_four);
     220    feq (__aeabi_frsub (fone, fzero), fminus_one);
     221    feq (__aeabi_frsub (ftwo, fminus_two), fminus_four);
     222    feq (__aeabi_fsub (fzero, fone), fminus_one);
     223    feq (__aeabi_fsub (fminus_two, ftwo), fminus_four);
     224  
     225    /* Table 5.  Single-precision floating-point comparisons.  */
     226    ieq (__aeabi_fcmpeq (fone, fone), 1);
     227    ieq (__aeabi_fcmpeq (fone, fzero), 0);
     228    ieq (__aeabi_fcmpeq (fNaN, fzero), 0);
     229    ieq (__aeabi_fcmpeq (fNaN, fNaN), 0);
     230  
     231    ieq (__aeabi_fcmplt (fzero, fone), 1);
     232    ieq (__aeabi_fcmplt (fone, fzero), 0);
     233    ieq (__aeabi_fcmplt (fzero, fzero), 0);
     234    ieq (__aeabi_fcmplt (fzero, fNaN), 0);
     235    ieq (__aeabi_fcmplt (fNaN, fNaN), 0);
     236  
     237    ieq (__aeabi_fcmple (fzero, fone), 1);
     238    ieq (__aeabi_fcmple (fone, fzero), 0);
     239    ieq (__aeabi_fcmple (fzero, fzero), 1);
     240    ieq (__aeabi_fcmple (fzero, fNaN), 0);
     241    ieq (__aeabi_fcmple (fNaN, fNaN), 0);
     242  
     243    ieq (__aeabi_fcmpge (fzero, fone), 0);
     244    ieq (__aeabi_fcmpge (fone, fzero), 1);
     245    ieq (__aeabi_fcmpge (fzero, fzero), 1);
     246    ieq (__aeabi_fcmpge (fzero, fNaN), 0);
     247    ieq (__aeabi_fcmpge (fNaN, fNaN), 0);
     248  
     249    ieq (__aeabi_fcmpgt (fzero, fone), 0);
     250    ieq (__aeabi_fcmpgt (fone, fzero), 1);
     251    ieq (__aeabi_fcmplt (fzero, fzero), 0);
     252    ieq (__aeabi_fcmpgt (fzero, fNaN), 0);
     253    ieq (__aeabi_fcmpgt (fNaN, fNaN), 0);
     254  
     255    ieq (__aeabi_fcmpun (fone, fone), 0);
     256    ieq (__aeabi_fcmpun (fone, fzero), 0);
     257    ieq (__aeabi_fcmpun (fNaN, fzero), 1);
     258    ieq (__aeabi_fcmpun (fNaN, fNaN), 1);
     259  
     260    /* Table 6.  Floating-point to integer conversions.  */
     261    ieq (__aeabi_d2iz (dminus_one), -1);
     262    ueq (__aeabi_d2uiz (done), 1);
     263    leq (__aeabi_d2lz (dminus_two), -2LL);
     264    uleq (__aeabi_d2ulz (dfour), 4LL);
     265    ieq (__aeabi_f2iz (fminus_one), -1);
     266    ueq (__aeabi_f2uiz (fone), 1);
     267    leq (__aeabi_f2lz (fminus_two), -2LL);
     268    uleq (__aeabi_f2ulz (ffour), 4LL);
     269  
     270    /* Table 7.  Conversions between floating types.  */
     271    feq (__aeabi_d2f (dtwo), ftwo);
     272    deq (__aeabi_f2d (fminus_four), dminus_four);
     273  
     274    /* Table 8.  Integer to floating-point conversions.  */
     275    deq (__aeabi_i2d (-1), dminus_one);
     276    deq (__aeabi_ui2d (2), dtwo);
     277    deq (__aeabi_l2d (-1), dminus_one);
     278    deq (__aeabi_ul2d (2ULL), dtwo);
     279    feq (__aeabi_i2f (-1), fminus_one);
     280    feq (__aeabi_ui2f (2), ftwo);
     281    feq (__aeabi_l2f (-1), fminus_one);
     282    feq (__aeabi_ul2f (2ULL), ftwo);
     283  
     284    /* Table 9.  Long long functions.  */
     285    leq (__aeabi_lmul (4LL, -1LL), -4LL);
     286    leq (__aeabi_llsl (2LL, 1), 4LL);
     287    leq (__aeabi_llsr (-1LL, 63), 1);
     288    leq (__aeabi_lasr (-1LL, 63), -1);
     289  
     290    result = lcmp_results;
     291    for (i = 0; i < NUM_CMP_VALUES; i++)
     292      for (j = 0; j < NUM_CMP_VALUES; j++)
     293        for (k = 0; k < NUM_CMP_VALUES; k++)
     294  	for (n = 0; n < NUM_CMP_VALUES; n++)
     295  	  {
     296  	    ieq (signof (__aeabi_lcmp
     297  			  (((long long)cmp_val[i] << 32) | cmp_val[k],
     298  			   ((long long)cmp_val[j] << 32) | cmp_val[n])),
     299  			   *result);
     300  	    result++;
     301  	  }
     302    result = ulcmp_results;
     303    for (i = 0; i < NUM_CMP_VALUES; i++)
     304      for (j = 0; j < NUM_CMP_VALUES; j++)
     305        for (k = 0; k < NUM_CMP_VALUES; k++)
     306  	for (n = 0; n < NUM_CMP_VALUES; n++)
     307  	  {
     308  	    ieq (signof (__aeabi_ulcmp
     309  			  (((long long)cmp_val[i] << 32) | cmp_val[k],
     310  			   ((long long)cmp_val[j] << 32) | cmp_val[n])),
     311  			   *result);
     312  	    result++;
     313  	  }
     314  
     315    ieq (__aeabi_idiv (-550, 11), -50);
     316    ueq (__aeabi_uidiv (4000000000U, 1000000U), 4000U);
     317  
     318    for (i = 0; i < 256; i++)
     319      bytes[i] = i;
     320  
     321  #ifdef __ARMEB__
     322    ieq (__aeabi_uread4 (bytes + 1), 0x01020304U);
     323    leq (__aeabi_uread8 (bytes + 3), 0x030405060708090aLL);
     324    ieq (__aeabi_uwrite4 (0x66778899U, bytes + 5), 0x66778899U);
     325    leq (__aeabi_uwrite8 (0x2030405060708090LL, bytes + 15),
     326         0x2030405060708090LL);
     327  #else
     328    ieq (__aeabi_uread4 (bytes + 1), 0x04030201U);
     329    leq (__aeabi_uread8 (bytes + 3), 0x0a09080706050403LL);
     330    ieq (__aeabi_uwrite4 (0x99887766U, bytes + 5), 0x99887766U);
     331    leq (__aeabi_uwrite8 (0x9080706050403020LL, bytes + 15),
     332         0x9080706050403020LL);
     333  #endif
     334  
     335    for (i = 0; i < 4; i++)
     336      ieq (bytes[5 + i], (6 + i) * 0x11);
     337  
     338    for (i = 0; i < 8; i++)
     339      ieq (bytes[15 + i], (2 + i) * 0x10);
     340  
     341    exit (0);		
     342  }