aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--BUGS.txt2
-rw-r--r--src/Execution/Runtime.php22
2 files changed, 20 insertions, 4 deletions
diff --git a/BUGS.txt b/BUGS.txt
index 4b510bd..2768b66 100644
--- a/BUGS.txt
+++ b/BUGS.txt
@@ -2,8 +2,6 @@
## Numeric
-* F64BitwiseTest
-* F32BitwiseTest
* ConversionsTest
* FloatExprsTest
* FloatLiteralsTest
diff --git a/src/Execution/Runtime.php b/src/Execution/Runtime.php
index 10bed7c..98893d0 100644
--- a/src/Execution/Runtime.php
+++ b/src/Execution/Runtime.php
@@ -599,7 +599,9 @@ final class Runtime
{
$c2 = $this->stack->popFloat();
$c1 = $this->stack->popFloat();
- $this->stack->pushValue($c1 * ($c2 < 0 ? -1 : 1));
+ $c1Sign = self::getFloatSign($c1);
+ $c2Sign = self::getFloatSign($c2);
+ $this->stack->pushValue($c1Sign === $c2Sign ? $c1 : -$c1);
}
private function execInstrNumericF32DemoteF64(Instrs\Numeric\F32DemoteF64 $instr): void
@@ -793,7 +795,9 @@ final class Runtime
{
$c2 = $this->stack->popFloat();
$c1 = $this->stack->popFloat();
- $this->stack->pushValue($c1 * ($c2 < 0 ? -1 : 1));
+ $c1Sign = self::getFloatSign($c1);
+ $c2Sign = self::getFloatSign($c2);
+ $this->stack->pushValue($c1Sign === $c2Sign ? $c1 : -$c1);
}
private function execInstrNumericF64Div(Instrs\Numeric\F64Div $instr): void
@@ -2606,4 +2610,18 @@ final class Runtime
}
return (int)$result;
}
+
+ private static function getFloatSign(float $p): int
+ {
+ if (is_nan($p)) {
+ $n = BinaryConversion::reinterpretF64AsI64($p);
+ // The MSB is the sign bit.
+ return (($n >> 63) & 1) === 1 ? -1 : 1;
+ } elseif ($p !== 0.0) {
+ return $p < 0.0 ? -1 : 1;
+ } else {
+ // Comparison with 0 does not work for -0.0.
+ return fdiv(1, $p) < 0.0 ? -1 : 1;
+ }
+ }
}