Upload Tizen:Base source
[external/gmp.git] / tests / mpn / t-instrument.c
1 /* Test assembler support for --enable-profiling=instrument.
2
3 Copyright 2002, 2003 Free Software Foundation, Inc.
4
5 This file is part of the GNU MP Library.
6
7 The GNU MP Library is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11
12 The GNU MP Library is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
15 License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along 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.  */
38 volatile int  enter_seen;
39
40 /* Dummy used to stop various calls going dead. */
41 unsigned long  notdead;
42
43 const char     *name = "<none>";
44 int  old_ncall;
45
46 struct {
47   void  *this_fn;
48   void  *call_site;
49 } call[100];
50 int  ncall;
51
52
53 void __cyg_profile_func_enter __GMP_PROTO ((void *this_fn, void *call_site))
54      __attribute__ ((no_instrument_function));
55
56 void
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
77 void __cyg_profile_func_exit __GMP_PROTO ((void *this_fn, void *call_site))
78      __attribute__ ((no_instrument_function));
79
80 void
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
105 void
106 pre (const char *str)
107 {
108   name = str;
109   enter_seen = 0;
110   old_ncall = ncall;
111 }
112
113 void
114 post (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
131 void
132 check (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
396 int
397 main (void)
398 {
399   tests_start ();
400
401   check ();
402
403   tests_end ();
404   exit (0);
405 }
406
407
408 #else /* ! WANT_PROFILING_INSTRUMENT */
409
410 int
411 main (void)
412 {
413   exit (0);
414 }
415
416 #endif