421 lines
8.7 KiB
C
421 lines
8.7 KiB
C
/* 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 2.1 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; see the file COPYING.LIB. If not, write to
|
|
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
MA 02110-1301, USA. */
|
|
|
|
#include "config.h"
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include "mpir.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(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(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
|