xref: /aosp_15_r20/external/musl/src/math/x86_64/remquol.c (revision c9945492fdd68bbe62686c5b452b4dc1be3f8453)
1*c9945492SAndroid Build Coastguard Worker #include <math.h>
2*c9945492SAndroid Build Coastguard Worker 
remquol(long double x,long double y,int * quo)3*c9945492SAndroid Build Coastguard Worker long double remquol(long double x, long double y, int *quo)
4*c9945492SAndroid Build Coastguard Worker {
5*c9945492SAndroid Build Coastguard Worker 	signed char *cx = (void *)&x, *cy = (void *)&y;
6*c9945492SAndroid Build Coastguard Worker 	/* By ensuring that addresses of x and y cannot be discarded,
7*c9945492SAndroid Build Coastguard Worker 	 * this empty asm guides GCC into representing extraction of
8*c9945492SAndroid Build Coastguard Worker 	 * their sign bits as memory loads rather than making x and y
9*c9945492SAndroid Build Coastguard Worker 	 * not-address-taken internally and using bitfield operations,
10*c9945492SAndroid Build Coastguard Worker 	 * which in the end wouldn't work out, as extraction from FPU
11*c9945492SAndroid Build Coastguard Worker 	 * registers needs to go through memory anyway. This way GCC
12*c9945492SAndroid Build Coastguard Worker 	 * should manage to use incoming stack slots without spills. */
13*c9945492SAndroid Build Coastguard Worker 	__asm__ ("" :: "X"(cx), "X"(cy));
14*c9945492SAndroid Build Coastguard Worker 
15*c9945492SAndroid Build Coastguard Worker 	long double t = x;
16*c9945492SAndroid Build Coastguard Worker 	unsigned fpsr;
17*c9945492SAndroid Build Coastguard Worker 	do __asm__ ("fprem1; fnstsw %%ax" : "+t"(t), "=a"(fpsr) : "u"(y));
18*c9945492SAndroid Build Coastguard Worker 	while (fpsr & 0x400);
19*c9945492SAndroid Build Coastguard Worker 	/* C0, C1, C3 flags in x87 status word carry low bits of quotient:
20*c9945492SAndroid Build Coastguard Worker 	 * 15 14 13 12 11 10  9  8
21*c9945492SAndroid Build Coastguard Worker 	 *  . C3  .  .  . C2 C1 C0
22*c9945492SAndroid Build Coastguard Worker 	 *  . b1  .  .  .  0 b0 b2 */
23*c9945492SAndroid Build Coastguard Worker 	unsigned char i = fpsr >> 8;
24*c9945492SAndroid Build Coastguard Worker 	i = i>>4 | i<<4;
25*c9945492SAndroid Build Coastguard Worker 	/* i[5:2] is now {b0 b2 ? b1}. Retrieve {0 b2 b1 b0} via
26*c9945492SAndroid Build Coastguard Worker 	 * in-register table lookup. */
27*c9945492SAndroid Build Coastguard Worker 	unsigned qbits = 0x7575313164642020 >> (i & 60);
28*c9945492SAndroid Build Coastguard Worker 	qbits &= 7;
29*c9945492SAndroid Build Coastguard Worker 
30*c9945492SAndroid Build Coastguard Worker 	*quo = (cx[9]^cy[9]) < 0 ? -qbits : qbits;
31*c9945492SAndroid Build Coastguard Worker 	return t;
32*c9945492SAndroid Build Coastguard Worker }
33