1/* Test assembler support for --enable-profiling=instrument. 2 3Copyright 2002, 2003 Free Software Foundation, Inc. 4 5This file is part of the GNU MP Library. 6 7The GNU MP Library is free software; you can redistribute it and/or modify 8it under the terms of the GNU Lesser General Public License as published by 9the Free Software Foundation; either version 3 of the License, or (at your 10option) any later version. 11 12The GNU MP Library is distributed in the hope that it will be useful, but 13WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 14or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 15License for more details. 16 17You should have received a copy of the GNU Lesser General Public License 18along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */ 19 20#include <stdio.h> 21#include <stdlib.h> 22#include "gmp.h" 23#include "gmp-impl.h" 24#include "longlong.h" 25#include "tests.h" 26 27 28#if WANT_PROFILING_INSTRUMENT 29 30/* This program exercises each mpn routine that might be implemented in 31 assembler. It ensures the __cyg_profile_func_enter and exit calls have 32 come out right, and that in the x86 code "ret_internal" is correctly used 33 for PIC setups. */ 34 35 36/* Changes to enter_seen done by __cyg_profile_func_enter are essentially 37 unknown to the optimizer, so must use volatile. */ 38volatile int enter_seen; 39 40/* Dummy used to stop various calls going dead. */ 41unsigned long notdead; 42 43const char *name = "<none>"; 44int old_ncall; 45 46struct { 47 void *this_fn; 48 void *call_site; 49} call[100]; 50int ncall; 51 52 53void __cyg_profile_func_enter __GMP_PROTO ((void *this_fn, void *call_site)) 54 __attribute__ ((no_instrument_function)); 55 56void 57__cyg_profile_func_enter (void *this_fn, void *call_site) 58{ 59#if 0 60 printf ("%24s %p %p\n", name, this_fn, call_site); 61#endif 62 ASSERT_ALWAYS (ncall >= 0); 63 ASSERT_ALWAYS (ncall <= numberof (call)); 64 65 if (ncall >= numberof (call)) 66 { 67 printf ("__cyg_profile_func_enter: oops, call stack full, from %s\n", name); 68 abort (); 69 } 70 71 enter_seen = 1; 72 call[ncall].this_fn = this_fn; 73 call[ncall].call_site = call_site; 74 ncall++; 75} 76 77void __cyg_profile_func_exit __GMP_PROTO ((void *this_fn, void *call_site)) 78 __attribute__ ((no_instrument_function)); 79 80void 81__cyg_profile_func_exit (void *this_fn, void *call_site) 82{ 83 ASSERT_ALWAYS (ncall >= 0); 84 ASSERT_ALWAYS (ncall <= numberof (call)); 85 86 if (ncall == 0) 87 { 88 printf ("__cyg_profile_func_exit: call stack empty, from %s\n", name); 89 abort (); 90 } 91 92 ncall--; 93 if (this_fn != call[ncall].this_fn || call_site != call[ncall].call_site) 94 { 95 printf ("__cyg_profile_func_exit: unbalanced this_fn/call_site from %s\n", name); 96 printf (" this_fn got %p\n", this_fn); 97 printf (" want %p\n", call[ncall].this_fn); 98 printf (" call_site got %p\n", call_site); 99 printf (" want %p\n", call[ncall].call_site); 100 abort (); 101 } 102} 103 104 105void 106pre (const char *str) 107{ 108 name = str; 109 enter_seen = 0; 110 old_ncall = ncall; 111} 112 113void 114post (void) 115{ 116 if (! enter_seen) 117 { 118 printf ("did not reach __cyg_profile_func_enter from %s\n", name); 119 abort (); 120 } 121 122 if (ncall != old_ncall) 123 { 124 printf ("unbalance enter/exit calls from %s\n", name); 125 printf (" ncall %d\n", ncall); 126 printf (" old_ncall %d\n", old_ncall); 127 abort (); 128 } 129} 130 131void 132check (void) 133{ 134 mp_limb_t wp[100], xp[100], yp[100]; 135 mp_size_t size = 100; 136 137 refmpn_zero (xp, size); 138 refmpn_zero (yp, size); 139 refmpn_zero (wp, size); 140 141 pre ("mpn_add_n"); 142 mpn_add_n (wp, xp, yp, size); 143 post (); 144 145#if HAVE_NATIVE_mpn_add_nc 146 pre ("mpn_add_nc"); 147 mpn_add_nc (wp, xp, yp, size, CNST_LIMB(0)); 148 post (); 149#endif 150 151#if HAVE_NATIVE_mpn_addlsh1_n 152 pre ("mpn_addlsh1_n"); 153 mpn_addlsh1_n (wp, xp, yp, size); 154 post (); 155#endif 156 157#if HAVE_NATIVE_mpn_and_n 158 pre ("mpn_and_n"); 159 mpn_and_n (wp, xp, yp, size); 160 post (); 161#endif 162 163#if HAVE_NATIVE_mpn_andn_n 164 pre ("mpn_andn_n"); 165 mpn_andn_n (wp, xp, yp, size); 166 post (); 167#endif 168 169 pre ("mpn_addmul_1"); 170 mpn_addmul_1 (wp, xp, size, yp[0]); 171 post (); 172 173#if HAVE_NATIVE_mpn_addmul_1c 174 pre ("mpn_addmul_1c"); 175 mpn_addmul_1c (wp, xp, size, yp[0], CNST_LIMB(0)); 176 post (); 177#endif 178 179#if HAVE_NATIVE_mpn_com 180 pre ("mpn_com"); 181 mpn_com (wp, xp, size); 182 post (); 183#endif 184 185#if HAVE_NATIVE_mpn_copyd 186 pre ("mpn_copyd"); 187 mpn_copyd (wp, xp, size); 188 post (); 189#endif 190 191#if HAVE_NATIVE_mpn_copyi 192 pre ("mpn_copyi"); 193 mpn_copyi (wp, xp, size); 194 post (); 195#endif 196 197 pre ("mpn_divexact_1"); 198 mpn_divexact_1 (wp, xp, size, CNST_LIMB(123)); 199 post (); 200 201 pre ("mpn_divexact_by3c"); 202 mpn_divexact_by3c (wp, xp, size, CNST_LIMB(0)); 203 post (); 204 205 pre ("mpn_divrem_1"); 206 mpn_divrem_1 (wp, (mp_size_t) 0, xp, size, CNST_LIMB(123)); 207 post (); 208 209#if HAVE_NATIVE_mpn_divrem_1c 210 pre ("mpn_divrem_1c"); 211 mpn_divrem_1c (wp, (mp_size_t) 0, xp, size, CNST_LIMB(123), CNST_LIMB(122)); 212 post (); 213#endif 214 215 pre ("mpn_gcd_1"); 216 xp[0] |= 1; 217 notdead += (unsigned long) mpn_gcd_1 (xp, size, CNST_LIMB(123)); 218 post (); 219 220 pre ("mpn_hamdist"); 221 notdead += mpn_hamdist (xp, yp, size); 222 post (); 223 224#if HAVE_NATIVE_mpn_ior_n 225 pre ("mpn_ior_n"); 226 mpn_ior_n (wp, xp, yp, size); 227 post (); 228#endif 229 230#if HAVE_NATIVE_mpn_iorn_n 231 pre ("mpn_iorn_n"); 232 mpn_iorn_n (wp, xp, yp, size); 233 post (); 234#endif 235 236 pre ("mpn_lshift"); 237 mpn_lshift (wp, xp, size, 1); 238 post (); 239 240 pre ("mpn_mod_1"); 241 notdead += mpn_mod_1 (xp, size, CNST_LIMB(123)); 242 post (); 243 244#if HAVE_NATIVE_mpn_mod_1c 245 pre ("mpn_mod_1c"); 246 notdead += mpn_mod_1c (xp, size, CNST_LIMB(123), CNST_LIMB(122)); 247 post (); 248#endif 249 250#if GMP_NUMB_BITS % 4 == 0 251 pre ("mpn_mod_34lsub1"); 252 notdead += mpn_mod_34lsub1 (xp, size); 253 post (); 254#endif 255 256 pre ("mpn_modexact_1_odd"); 257 notdead += mpn_modexact_1_odd (xp, size, CNST_LIMB(123)); 258 post (); 259 260 pre ("mpn_modexact_1c_odd"); 261 notdead += mpn_modexact_1c_odd (xp, size, CNST_LIMB(123), CNST_LIMB(456)); 262 post (); 263 264 pre ("mpn_mul_1"); 265 mpn_mul_1 (wp, xp, size, yp[0]); 266 post (); 267 268#if HAVE_NATIVE_mpn_mul_1c 269 pre ("mpn_mul_1c"); 270 mpn_mul_1c (wp, xp, size, yp[0], CNST_LIMB(0)); 271 post (); 272#endif 273 274#if HAVE_NATIVE_mpn_mul_2 275 pre ("mpn_mul_2"); 276 mpn_mul_2 (wp, xp, size-1, yp); 277 post (); 278#endif 279 280 pre ("mpn_mul_basecase"); 281 mpn_mul_basecase (wp, xp, (mp_size_t) 3, yp, (mp_size_t) 3); 282 post (); 283 284#if HAVE_NATIVE_mpn_nand_n 285 pre ("mpn_nand_n"); 286 mpn_nand_n (wp, xp, yp, size); 287 post (); 288#endif 289 290#if HAVE_NATIVE_mpn_nior_n 291 pre ("mpn_nior_n"); 292 mpn_nior_n (wp, xp, yp, size); 293 post (); 294#endif 295 296 pre ("mpn_popcount"); 297 notdead += mpn_popcount (xp, size); 298 post (); 299 300 pre ("mpn_preinv_mod_1"); 301 notdead += mpn_preinv_mod_1 (xp, size, GMP_NUMB_MAX, 302 refmpn_invert_limb (GMP_NUMB_MAX)); 303 post (); 304 305#if USE_PREINV_DIVREM_1 || HAVE_NATIVE_mpn_preinv_divrem_1 306 pre ("mpn_preinv_divrem_1"); 307 mpn_preinv_divrem_1 (wp, (mp_size_t) 0, xp, size, GMP_NUMB_MAX, 308 refmpn_invert_limb (GMP_NUMB_MAX), 0); 309 post (); 310#endif 311 312#if HAVE_NATIVE_mpn_rsh1add_n 313 pre ("mpn_rsh1add_n"); 314 mpn_rsh1add_n (wp, xp, yp, size); 315 post (); 316#endif 317 318#if HAVE_NATIVE_mpn_rsh1sub_n 319 pre ("mpn_rsh1sub_n"); 320 mpn_rsh1sub_n (wp, xp, yp, size); 321 post (); 322#endif 323 324 pre ("mpn_rshift"); 325 mpn_rshift (wp, xp, size, 1); 326 post (); 327 328 pre ("mpn_sqr_basecase"); 329 mpn_sqr_basecase (wp, xp, (mp_size_t) 3); 330 post (); 331 332 pre ("mpn_submul_1"); 333 mpn_submul_1 (wp, xp, size, yp[0]); 334 post (); 335 336#if HAVE_NATIVE_mpn_submul_1c 337 pre ("mpn_submul_1c"); 338 mpn_submul_1c (wp, xp, size, yp[0], CNST_LIMB(0)); 339 post (); 340#endif 341 342 pre ("mpn_sub_n"); 343 mpn_sub_n (wp, xp, yp, size); 344 post (); 345 346#if HAVE_NATIVE_mpn_sub_nc 347 pre ("mpn_sub_nc"); 348 mpn_sub_nc (wp, xp, yp, size, CNST_LIMB(0)); 349 post (); 350#endif 351 352#if HAVE_NATIVE_mpn_sublsh1_n 353 pre ("mpn_sublsh1_n"); 354 mpn_sublsh1_n (wp, xp, yp, size); 355 post (); 356#endif 357 358#if HAVE_NATIVE_mpn_udiv_qrnnd 359 pre ("mpn_udiv_qrnnd"); 360 mpn_udiv_qrnnd (&wp[0], CNST_LIMB(122), xp[0], CNST_LIMB(123)); 361 post (); 362#endif 363 364#if HAVE_NATIVE_mpn_udiv_qrnnd_r 365 pre ("mpn_udiv_qrnnd_r"); 366 mpn_udiv_qrnnd (CNST_LIMB(122), xp[0], CNST_LIMB(123), &wp[0]); 367 post (); 368#endif 369 370#if HAVE_NATIVE_mpn_umul_ppmm 371 pre ("mpn_umul_ppmm"); 372 mpn_umul_ppmm (&wp[0], xp[0], yp[0]); 373 post (); 374#endif 375 376#if HAVE_NATIVE_mpn_umul_ppmm_r 377 pre ("mpn_umul_ppmm_r"); 378 mpn_umul_ppmm_r (&wp[0], xp[0], yp[0]); 379 post (); 380#endif 381 382#if HAVE_NATIVE_mpn_xor_n 383 pre ("mpn_xor_n"); 384 mpn_xor_n (wp, xp, yp, size); 385 post (); 386#endif 387 388#if HAVE_NATIVE_mpn_xnor_n 389 pre ("mpn_xnor_n"); 390 mpn_xnor_n (wp, xp, yp, size); 391 post (); 392#endif 393} 394 395 396int 397main (void) 398{ 399 tests_start (); 400 401 check (); 402 403 tests_end (); 404 exit (0); 405} 406 407 408#else /* ! WANT_PROFILING_INSTRUMENT */ 409 410int 411main (void) 412{ 413 exit (0); 414} 415 416#endif 417