| /* Test assembler support for --enable-profiling=instrument. |
| |
| Copyright 2002, 2003 Free Software Foundation, Inc. |
| |
| This file is part of the GNU MP Library. |
| |
| The GNU MP Library is free software; you can redistribute it and/or modify |
| it under the terms of the GNU Lesser General Public License as published by |
| the Free Software Foundation; either version 3 of the License, or (at your |
| option) any later version. |
| |
| The GNU MP Library is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY |
| or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public |
| License for more details. |
| |
| You should have received a copy of the GNU Lesser General Public License |
| along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */ |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include "gmp.h" |
| #include "gmp-impl.h" |
| #include "longlong.h" |
| #include "tests.h" |
| |
| |
| #if WANT_PROFILING_INSTRUMENT |
| |
| /* This program exercises each mpn routine that might be implemented in |
| assembler. It ensures the __cyg_profile_func_enter and exit calls have |
| come out right, and that in the x86 code "ret_internal" is correctly used |
| for PIC setups. */ |
| |
| |
| /* Changes to enter_seen done by __cyg_profile_func_enter are essentially |
| unknown to the optimizer, so must use volatile. */ |
| volatile int enter_seen; |
| |
| /* Dummy used to stop various calls going dead. */ |
| unsigned long notdead; |
| |
| const char *name = "<none>"; |
| int old_ncall; |
| |
| struct { |
| void *this_fn; |
| void *call_site; |
| } call[100]; |
| int ncall; |
| |
| |
| void __cyg_profile_func_enter __GMP_PROTO ((void *this_fn, void *call_site)) |
| __attribute__ ((no_instrument_function)); |
| |
| void |
| __cyg_profile_func_enter (void *this_fn, void *call_site) |
| { |
| #if 0 |
| printf ("%24s %p %p\n", name, this_fn, call_site); |
| #endif |
| ASSERT_ALWAYS (ncall >= 0); |
| ASSERT_ALWAYS (ncall <= numberof (call)); |
| |
| if (ncall >= numberof (call)) |
| { |
| printf ("__cyg_profile_func_enter: oops, call stack full, from %s\n", name); |
| abort (); |
| } |
| |
| enter_seen = 1; |
| call[ncall].this_fn = this_fn; |
| call[ncall].call_site = call_site; |
| ncall++; |
| } |
| |
| void __cyg_profile_func_exit __GMP_PROTO ((void *this_fn, void *call_site)) |
| __attribute__ ((no_instrument_function)); |
| |
| void |
| __cyg_profile_func_exit (void *this_fn, void *call_site) |
| { |
| ASSERT_ALWAYS (ncall >= 0); |
| ASSERT_ALWAYS (ncall <= numberof (call)); |
| |
| if (ncall == 0) |
| { |
| printf ("__cyg_profile_func_exit: call stack empty, from %s\n", name); |
| abort (); |
| } |
| |
| ncall--; |
| if (this_fn != call[ncall].this_fn || call_site != call[ncall].call_site) |
| { |
| printf ("__cyg_profile_func_exit: unbalanced this_fn/call_site from %s\n", name); |
| printf (" this_fn got %p\n", this_fn); |
| printf (" want %p\n", call[ncall].this_fn); |
| printf (" call_site got %p\n", call_site); |
| printf (" want %p\n", call[ncall].call_site); |
| abort (); |
| } |
| } |
| |
| |
| void |
| pre (const char *str) |
| { |
| name = str; |
| enter_seen = 0; |
| old_ncall = ncall; |
| } |
| |
| void |
| post (void) |
| { |
| if (! enter_seen) |
| { |
| printf ("did not reach __cyg_profile_func_enter from %s\n", name); |
| abort (); |
| } |
| |
| if (ncall != old_ncall) |
| { |
| printf ("unbalance enter/exit calls from %s\n", name); |
| printf (" ncall %d\n", ncall); |
| printf (" old_ncall %d\n", old_ncall); |
| abort (); |
| } |
| } |
| |
| void |
| check (void) |
| { |
| mp_limb_t wp[100], xp[100], yp[100]; |
| mp_size_t size = 100; |
| |
| refmpn_zero (xp, size); |
| refmpn_zero (yp, size); |
| refmpn_zero (wp, size); |
| |
| pre ("mpn_add_n"); |
| mpn_add_n (wp, xp, yp, size); |
| post (); |
| |
| #if HAVE_NATIVE_mpn_add_nc |
| pre ("mpn_add_nc"); |
| mpn_add_nc (wp, xp, yp, size, CNST_LIMB(0)); |
| post (); |
| #endif |
| |
| #if HAVE_NATIVE_mpn_addlsh1_n |
| pre ("mpn_addlsh1_n"); |
| mpn_addlsh1_n (wp, xp, yp, size); |
| post (); |
| #endif |
| |
| #if HAVE_NATIVE_mpn_and_n |
| pre ("mpn_and_n"); |
| mpn_and_n (wp, xp, yp, size); |
| post (); |
| #endif |
| |
| #if HAVE_NATIVE_mpn_andn_n |
| pre ("mpn_andn_n"); |
| mpn_andn_n (wp, xp, yp, size); |
| post (); |
| #endif |
| |
| pre ("mpn_addmul_1"); |
| mpn_addmul_1 (wp, xp, size, yp[0]); |
| post (); |
| |
| #if HAVE_NATIVE_mpn_addmul_1c |
| pre ("mpn_addmul_1c"); |
| mpn_addmul_1c (wp, xp, size, yp[0], CNST_LIMB(0)); |
| post (); |
| #endif |
| |
| #if HAVE_NATIVE_mpn_com_n |
| pre ("mpn_com_n"); |
| mpn_com_n (wp, xp, size); |
| post (); |
| #endif |
| |
| #if HAVE_NATIVE_mpn_copyd |
| pre ("mpn_copyd"); |
| mpn_copyd (wp, xp, size); |
| post (); |
| #endif |
| |
| #if HAVE_NATIVE_mpn_copyi |
| pre ("mpn_copyi"); |
| mpn_copyi (wp, xp, size); |
| post (); |
| #endif |
| |
| pre ("mpn_divexact_1"); |
| mpn_divexact_1 (wp, xp, size, CNST_LIMB(123)); |
| post (); |
| |
| pre ("mpn_divexact_by3c"); |
| mpn_divexact_by3c (wp, xp, size, CNST_LIMB(0)); |
| post (); |
| |
| pre ("mpn_divrem_1"); |
| mpn_divrem_1 (wp, (mp_size_t) 0, xp, size, CNST_LIMB(123)); |
| post (); |
| |
| #if HAVE_NATIVE_mpn_divrem_1c |
| pre ("mpn_divrem_1c"); |
| mpn_divrem_1c (wp, (mp_size_t) 0, xp, size, CNST_LIMB(123), CNST_LIMB(122)); |
| post (); |
| #endif |
| |
| pre ("mpn_gcd_1"); |
| xp[0] |= 1; |
| notdead += (unsigned long) mpn_gcd_1 (xp, size, CNST_LIMB(123)); |
| post (); |
| |
| pre ("mpn_hamdist"); |
| notdead += mpn_hamdist (xp, yp, size); |
| post (); |
| |
| #if HAVE_NATIVE_mpn_ior_n |
| pre ("mpn_ior_n"); |
| mpn_ior_n (wp, xp, yp, size); |
| post (); |
| #endif |
| |
| #if HAVE_NATIVE_mpn_iorn_n |
| pre ("mpn_iorn_n"); |
| mpn_iorn_n (wp, xp, yp, size); |
| post (); |
| #endif |
| |
| pre ("mpn_lshift"); |
| mpn_lshift (wp, xp, size, 1); |
| post (); |
| |
| pre ("mpn_mod_1"); |
| notdead += mpn_mod_1 (xp, size, CNST_LIMB(123)); |
| post (); |
| |
| #if HAVE_NATIVE_mpn_mod_1c |
| pre ("mpn_mod_1c"); |
| notdead += mpn_mod_1c (xp, size, CNST_LIMB(123), CNST_LIMB(122)); |
| post (); |
| #endif |
| |
| #if GMP_NUMB_BITS % 4 == 0 |
| pre ("mpn_mod_34lsub1"); |
| notdead += mpn_mod_34lsub1 (xp, size); |
| post (); |
| #endif |
| |
| pre ("mpn_modexact_1_odd"); |
| notdead += mpn_modexact_1_odd (xp, size, CNST_LIMB(123)); |
| post (); |
| |
| pre ("mpn_modexact_1c_odd"); |
| notdead += mpn_modexact_1c_odd (xp, size, CNST_LIMB(123), CNST_LIMB(456)); |
| post (); |
| |
| pre ("mpn_mul_1"); |
| mpn_mul_1 (wp, xp, size, yp[0]); |
| post (); |
| |
| #if HAVE_NATIVE_mpn_mul_1c |
| pre ("mpn_mul_1c"); |
| mpn_mul_1c (wp, xp, size, yp[0], CNST_LIMB(0)); |
| post (); |
| #endif |
| |
| #if HAVE_NATIVE_mpn_mul_2 |
| pre ("mpn_mul_2"); |
| mpn_mul_2 (wp, xp, size-1, yp); |
| post (); |
| #endif |
| |
| pre ("mpn_mul_basecase"); |
| mpn_mul_basecase (wp, xp, (mp_size_t) 3, yp, (mp_size_t) 3); |
| post (); |
| |
| #if HAVE_NATIVE_mpn_nand_n |
| pre ("mpn_nand_n"); |
| mpn_nand_n (wp, xp, yp, size); |
| post (); |
| #endif |
| |
| #if HAVE_NATIVE_mpn_nior_n |
| pre ("mpn_nior_n"); |
| mpn_nior_n (wp, xp, yp, size); |
| post (); |
| #endif |
| |
| pre ("mpn_popcount"); |
| notdead += mpn_popcount (xp, size); |
| post (); |
| |
| pre ("mpn_preinv_mod_1"); |
| notdead += mpn_preinv_mod_1 (xp, size, GMP_NUMB_MAX, |
| refmpn_invert_limb (GMP_NUMB_MAX)); |
| post (); |
| |
| #if USE_PREINV_DIVREM_1 || HAVE_NATIVE_mpn_preinv_divrem_1 |
| pre ("mpn_preinv_divrem_1"); |
| mpn_preinv_divrem_1 (wp, (mp_size_t) 0, xp, size, GMP_NUMB_MAX, |
| refmpn_invert_limb (GMP_NUMB_MAX), 0); |
| post (); |
| #endif |
| |
| #if HAVE_NATIVE_mpn_rsh1add_n |
| pre ("mpn_rsh1add_n"); |
| mpn_rsh1add_n (wp, xp, yp, size); |
| post (); |
| #endif |
| |
| #if HAVE_NATIVE_mpn_rsh1sub_n |
| pre ("mpn_rsh1sub_n"); |
| mpn_rsh1sub_n (wp, xp, yp, size); |
| post (); |
| #endif |
| |
| pre ("mpn_rshift"); |
| mpn_rshift (wp, xp, size, 1); |
| post (); |
| |
| pre ("mpn_sqr_basecase"); |
| mpn_sqr_basecase (wp, xp, (mp_size_t) 3); |
| post (); |
| |
| pre ("mpn_submul_1"); |
| mpn_submul_1 (wp, xp, size, yp[0]); |
| post (); |
| |
| #if HAVE_NATIVE_mpn_submul_1c |
| pre ("mpn_submul_1c"); |
| mpn_submul_1c (wp, xp, size, yp[0], CNST_LIMB(0)); |
| post (); |
| #endif |
| |
| pre ("mpn_sub_n"); |
| mpn_sub_n (wp, xp, yp, size); |
| post (); |
| |
| #if HAVE_NATIVE_mpn_sub_nc |
| pre ("mpn_sub_nc"); |
| mpn_sub_nc (wp, xp, yp, size, CNST_LIMB(0)); |
| post (); |
| #endif |
| |
| #if HAVE_NATIVE_mpn_sublsh1_n |
| pre ("mpn_sublsh1_n"); |
| mpn_sublsh1_n (wp, xp, yp, size); |
| post (); |
| #endif |
| |
| #if HAVE_NATIVE_mpn_udiv_qrnnd |
| pre ("mpn_udiv_qrnnd"); |
| mpn_udiv_qrnnd (&wp[0], CNST_LIMB(122), xp[0], CNST_LIMB(123)); |
| post (); |
| #endif |
| |
| #if HAVE_NATIVE_mpn_udiv_qrnnd_r |
| pre ("mpn_udiv_qrnnd_r"); |
| mpn_udiv_qrnnd (CNST_LIMB(122), xp[0], CNST_LIMB(123), &wp[0]); |
| post (); |
| #endif |
| |
| #if HAVE_NATIVE_mpn_umul_ppmm |
| pre ("mpn_umul_ppmm"); |
| mpn_umul_ppmm (&wp[0], xp[0], yp[0]); |
| post (); |
| #endif |
| |
| #if HAVE_NATIVE_mpn_umul_ppmm_r |
| pre ("mpn_umul_ppmm_r"); |
| mpn_umul_ppmm_r (&wp[0], xp[0], yp[0]); |
| post (); |
| #endif |
| |
| #if HAVE_NATIVE_mpn_xor_n |
| pre ("mpn_xor_n"); |
| mpn_xor_n (wp, xp, yp, size); |
| post (); |
| #endif |
| |
| #if HAVE_NATIVE_mpn_xnor_n |
| pre ("mpn_xnor_n"); |
| mpn_xnor_n (wp, xp, yp, size); |
| post (); |
| #endif |
| } |
| |
| |
| int |
| main (void) |
| { |
| tests_start (); |
| |
| check (); |
| |
| tests_end (); |
| exit (0); |
| } |
| |
| |
| #else /* ! WANT_PROFILING_INSTRUMENT */ |
| |
| int |
| main (void) |
| { |
| exit (0); |
| } |
| |
| #endif |