@@ -1054,32 +1054,34 @@ void SoftFPU::F2XM1(const X86::Instruction&)
1054
1054
}
1055
1055
void SoftFPU::FYL2X (const X86::Instruction&)
1056
1056
{
1057
- // FIXME: raise precision and under/overflow
1058
- // FIXME: detect denormal operands
1059
- // FIXME: QNaN
1060
- auto f0 = fpu_get (0 );
1061
- auto f1 = fpu_get (1 );
1062
-
1063
- if (f0 < 0 . || isnan (f0) || isnan (f1)
1064
- || (isinf (f0) && f1 == 0 .) || (f0 == 1 . && isinf (f1)))
1057
+ // FIXME: Set C1 on when result was rounded up, cleared otherwise
1058
+ // FIXME: Raise #IA #D #U #O #P
1059
+ auto x = fpu_get (0 );
1060
+ auto y = fpu_get (1 );
1061
+ if (x < 0 . && !isinf (x)) {
1065
1062
fpu_set_exception (FPU_Exception::InvalidOperation);
1066
- if (f0 == 0 .)
1063
+ // FIXME: Spec does not say what to do here....
1064
+ // So lets just ask libm....
1065
+ fpu_set (1 , y * log2l (x));
1066
+ } else if (x == 0 .) {
1067
+ if (y == 0 )
1068
+ fpu_set_exception (FPU_Exception::InvalidOperation);
1067
1069
fpu_set_exception (FPU_Exception::ZeroDivide);
1068
-
1069
- fpu_set (1 , f1 * log2l (f0));
1070
+ fpu_set (1 , INFINITY * (signbit (y) ? 1 : -1 ));
1071
+ } else {
1072
+ fpu_set (1 , y * log2l (x));
1073
+ }
1070
1074
fpu_pop ();
1071
1075
}
1072
1076
void SoftFPU::FYL2XP1 (const X86::Instruction&)
1073
1077
{
1074
- // FIXME: raise #O #U #P #D
1075
- // FIXME: QNaN
1076
- auto f0 = fpu_get (0 );
1077
- auto f1 = fpu_get (1 );
1078
- if (isnan (f0) || isnan (f1)
1079
- || (isinf (f1) && f0 == 0 ))
1078
+ // FIXME: Raise #IA #O #U #P #D
1079
+ auto x = fpu_get (0 );
1080
+ auto y = fpu_get (1 );
1081
+ if (x == 0 && isinf (y))
1080
1082
fpu_set_exception (FPU_Exception::InvalidOperation);
1081
1083
1082
- fpu_set (1 , (f1 * log2l (f0 + 1 .0l )));
1084
+ fpu_set (1 , (y * log2l (x + 1 .0l )));
1083
1085
fpu_pop ();
1084
1086
}
1085
1087
0 commit comments