10 #define ERR err(__LINE__)
17 static volatile int expect_SIGFPE
;
19 static jmp_buf jmpbuf_SIGFPE
, jmpbuf_main
;
21 static void err(int line
)
23 /* print error information */
24 printf("error line %d; i=0x%.8lx%.8lx; j=0x%.8lx%.8lx; k=0x%.8lx%.8lx\n",
28 ex64hi(k
), ex64lo(k
));
30 /* quit after too many errors */
34 #define LENGTHOF(arr) (sizeof(arr) / sizeof(arr[0]))
36 static u64_t
getargval(int index
, int *done
)
66 /* values with corner case and random 32-bit components */
67 if (index
< LENGTHOF(values
) * LENGTHOF(values
))
68 return make64(values
[index
/ LENGTHOF(values
)], values
[index
% LENGTHOF(values
)]);
70 index
-= LENGTHOF(values
) * LENGTHOF(values
);
73 if (index
< 16) return make64(index
+ 2, 0);
77 if (index
< 16) return make64(-index
- 2, -1);
81 if (index
< 14) return make64(1 << (index
* 2 + 5), 0);
83 if (index
< 16) return make64(0, 1 << (index
* 2 + 1));
91 static void handler_SIGFPE(int signum
)
93 assert(signum
== SIGFPE
);
95 /* restore the signal handler */
96 if (signal(SIGFPE
, handler_SIGFPE
) == SIG_ERR
) ERR
;
98 /* division by zero occurred, was this expected? */
100 /* expected: jump back to test */
102 longjmp(jmpbuf_SIGFPE
, -1);
104 /* not expected: error and jump back to main */
105 longjmp(jmpbuf_main
, -1);
113 static inline int bsr64(u64_t i
)
118 for (index
= 63, mask
= 1ULL << 63; index
>= 0; --index
, mask
>>= 1) {
126 static void testmul(void)
129 u32_t ilo
= ex64lo(i
), jlo
= ex64lo(j
);
133 /* compute maximum index of highest-order bit */
134 prodbits
= bsr64(i
) + bsr64(j
) + 1;
135 if (i
== 0 || j
== 0) prodbits
= -1;
136 if (bsr64(prod
) > prodbits
) ERR
;
138 /* compare to 32-bit multiplication if possible */
139 if (ex64hi(i
) == 0 && ex64hi(j
) == 0) {
140 if (prod
!= (u64_t
)ilo
* jlo
) ERR
;
142 /* if there is no overflow we can check against pure 32-bit */
143 if (prodbits
< 32 && prod
!= ilo
* jlo
) ERR
;
146 /* in 32-bit arith low-order DWORD matches regardless of overflow */
147 if (ex64lo(prod
) != ilo
* jlo
) ERR
;
149 /* multiplication by zero yields zero */
150 if (prodbits
< 0 && prod
!= 0) ERR
;
152 /* if there is no overflow, check absence of zero divisors */
153 if (prodbits
>= 0 && prodbits
< 64 && prod
== 0) ERR
;
156 if (prod
!= j
* i
) ERR
;
158 /* loop though all argument value combinations for third argument */
159 for (kdone
= 0, kidx
= 0; k
= getargval(kidx
, &kdone
), !kdone
; kidx
++) {
161 if ((i
* j
) * k
!= i
* (j
* k
)) ERR
;
163 /* left and right distributivity */
164 if ((i
+ j
) * k
!= (i
* k
) + (j
* k
)) ERR
;
165 if (i
* (j
+ k
) != (i
* j
) + (i
* k
)) ERR
;
169 static void do_not_optimize_away(volatile u64_t
* ptr
)
172 /* TODO: does this actually do the job? */
176 static void testdiv0(void)
183 /* loop through the 5 different division functions */
184 for (funcidx
= 0; funcidx
< 5; funcidx
++) {
186 if (setjmp(jmpbuf_SIGFPE
) == 0) {
187 /* divide by zero using various functions */
189 case 0: res
= i
/ j
; ERR
; break;
190 case 1: res
= i
/ ex64lo(j
); ERR
; break;
191 case 2: res
= i
/ ex64lo(j
); ERR
; break;
192 case 3: res
= i
% j
; ERR
; break;
193 case 4: res
= i
% ex64lo(j
); ERR
; break;
194 default: assert(0); ERR
; break;
197 do_not_optimize_away((volatile u64_t
*)&res
);
199 /* if we reach this point there was no signal and an
200 * error has been recorded
204 /* a signal has been received and expect_SIGFPE has
205 * been reset; all is ok now
207 assert(!expect_SIGFPE
);
212 static void testdiv(void)
216 struct timeval tvstart
, tvend
;
218 printf("i=0x%.8x%.8x; j=0x%.8x%.8x\n",
219 ex64hi(i
), ex64lo(i
),
220 ex64hi(j
), ex64lo(j
));
222 if (gettimeofday(&tvstart
, NULL
) < 0) ERR
;
225 /* division by zero has a separate test */
231 /* perform division, store q in k to make ERR more informative */
237 if (gettimeofday(&tvend
, NULL
) < 0) ERR
;
238 tvend
.tv_sec
-= tvstart
.tv_sec
;
239 tvend
.tv_usec
-= tvstart
.tv_usec
;
240 if (tvend
.tv_usec
< 0) {
242 tvend
.tv_usec
+= 1000000;
244 printf("q=0x%.8x%.8x; r=0x%.8x%.8x; time=%d.%.6d\n",
245 ex64hi(q
), ex64lo(q
),
246 ex64hi(r
), ex64lo(r
),
247 tvend
.tv_sec
, tvend
.tv_usec
);
251 /* compare to 64/32-bit division if possible */
253 if (q
!= i
/ ex64lo(j
)) ERR
;
255 if (q
!= i
/ ex64lo(j
)) ERR
;
257 if (r
!= i
% ex64lo(j
)) ERR
;
259 /* compare to 32-bit division if possible */
261 if (q
!= ex64lo(i
) / ex64lo(j
)) ERR
;
262 if (r
!= ex64lo(i
) % ex64lo(j
)) ERR
;
266 /* check results using i = q j + r and r < j */
267 if (i
!= (q
* j
) + r
) ERR
;
271 static void test(void)
273 int idone
, jdone
, iidx
, jidx
;
275 /* loop though all argument value combinations */
276 for (idone
= 0, iidx
= 0; i
= getargval(iidx
, &idone
), !idone
; iidx
++)
277 for (jdone
= 0, jidx
= 0; j
= getargval(jidx
, &jdone
), !jdone
; jidx
++) {
287 /* set up signal handler to deal with div by zero */
288 if (setjmp(jmpbuf_main
) == 0) {
289 if (signal(SIGFPE
, handler_SIGFPE
) == SIG_ERR
) ERR
;
294 /* an unexpected SIGFPE has occurred */
301 return(-1); /* Unreachable */