2 Copyright © 1995-2017, The AROS Development Team. All rights reserved.
5 #include <aros/debug.h>
6 #include <proto/utility.h>
7 #include "mathieeedoubbas_intern.h"
9 static void add128(ULONG
*s
, ULONG
*d
)
14 for (i
= 3; i
>= 0; i
--) {
23 /*****************************************************************************
27 AROS_LHQUAD2(double, IEEEDPMul
,
30 AROS_LHAQUAD(double, y
, D0
, D1
),
31 AROS_LHAQUAD(double, z
, D2
, D3
),
34 struct MathIeeeDoubBasBase
*, MathIeeeDoubBasBase
, 13, MathIeeeDoubBas
)
37 Multiplies two IEEE double precision numbers.
40 y - first multiplicand.
41 z - second multiplicand.
56 *****************************************************************************/
64 double *Dres
= (double *)&res
;
66 QUAD
* Qy
= (QUAD
*)&y
;
67 QUAD
* Qz
= (QUAD
*)&z
;
69 D(bug("%08x %08x * %08x %08x\n",
70 (ULONG
)Get_High32of64(*Qy
), (ULONG
)Get_Low32of64(*Qy
),
71 (ULONG
)Get_High32of64(*Qz
), (ULONG
)Get_Low32of64(*Qz
)));
73 sign
= ((Get_High32of64(*Qy
) ^ Get_High32of64(*Qz
)) & IEEEDPSign_Mask_Hi
) != 0;
75 AND64C(Qtmp1
, *Qy
, IEEEDPExponent_Mask_Hi
, IEEEDPExponent_Mask_Lo
);
76 AND64C(Qtmp2
, *Qz
, IEEEDPExponent_Mask_Hi
, IEEEDPExponent_Mask_Lo
);
78 SHRU32(exp1
, Qtmp1
, 52);
79 SHRU32(exp2
, Qtmp2
, 52);
81 exp1
= (exp1
& 0x7ff) - 1023;
82 exp2
= (exp2
& 0x7ff) - 1023;
85 D(bug("EXP %d + EXP %d = %d (%08x)\n", exp1
, exp2
, exp
, (exp
+ 1023) << 20));
87 AND64C(Qtmp1
, *Qy
, IEEEDPMantisse_Mask_Hi
, IEEEDPMantisse_Mask_Lo
);
88 AND64C(Qtmp2
, *Qz
, IEEEDPMantisse_Mask_Hi
, IEEEDPMantisse_Mask_Lo
);
90 /* (53 bit) * (53 bit) multiplication */
95 x1
= Get_High32of64(Qtmp1
);
96 x1
|= 0x00100000; /* Set "hidden" 53rd mantissa bit */
97 x2
= Get_Low32of64(Qtmp1
);
98 y1
= Get_High32of64(Qtmp2
);
99 y1
|= 0x00100000; /* Set "hidden" 53rd mantissa bit */
100 y2
= Get_Low32of64(Qtmp2
);
102 D(bug("%08x %08x %08x %08x\n", x1
, x2
, y1
, y2
));
104 Qtmp1
= UMult64(x1
, y1
);
105 t1
[0] = Get_High32of64(Qtmp1
);
106 t1
[1] = Get_Low32of64(Qtmp1
);
108 Qtmp1
= UMult64(x2
, y2
);
109 t1
[2] = Get_High32of64(Qtmp1
);
110 t1
[3] = Get_Low32of64(Qtmp1
);
112 Qtmp1
= UMult64(x1
, y2
);
114 t2
[2] = Get_High32of64(Qtmp1
);
115 t2
[1] = Get_Low32of64(Qtmp1
);
120 Qtmp1
= UMult64(x2
, y1
);
122 t2
[2] = Get_High32of64(Qtmp1
);
123 t2
[1] = Get_Low32of64(Qtmp1
);
128 D(bug("%08x %08x %08x %08x\n", t1
[0], t1
[1], t1
[2], t1
[3]));
130 /* Normalize. Probably could be more optimal */
131 if (t1
[0] || t1
[1] || t1
[2] || t1
[3]) {
132 while (t1
[0] & 0xfffffe00) {
134 t1
[3] |= (t1
[2] & 1) ? 0x80000000 : 0;
136 t1
[2] |= (t1
[1] & 1) ? 0x80000000 : 0;
138 t1
[1] |= (t1
[0] & 1) ? 0x80000000 : 0;
142 while (!(t1
[0] & 0x00000100)) {
144 t1
[0] |= (t1
[1] & 0x80000000) ? 1 : 0;
146 t1
[1] |= (t1
[2] & 0x80000000) ? 1 : 0;
148 t1
[2] |= (t1
[3] & 0x80000000) ? 1 : 0;
154 D(bug("%08x %08x %08x %08x\n", t1
[0], t1
[1], t1
[2], t1
[3]));
158 Set_Value64C(res
, 0x0, 0x0);
160 Set_Value64C(res
, IEEEDPSign_Mask_Hi
, IEEEDPSign_Mask_Lo
);
166 Set_Value64C(res
, IEEEDPPInfty_Hi
, IEEEDPPInfty_Lo
);
168 Set_Value64C(res
, IEEEDPPInfty_Hi
| IEEEDPSign_Mask_Hi
, IEEEDPPInfty_Lo
| IEEEDPSign_Mask_Lo
);
172 Set_Value64C(res
, (t1
[0] << 12) | (t1
[1] >> 20), (t1
[1] << 12) | (t1
[2] >> 20));
173 AND64QC(res
, IEEEDPMantisse_Mask_Hi
, IEEEDPMantisse_Mask_Lo
);
174 SHL64(Qtmp1
, (QUAD
)(exp
+ 1023), 52);
178 OR64(res
, IEEEDPSign_Mask_Hi
, IEEEDPSign_Mask_Lo
);