aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2024-06-02 04:14:43 +0900
committernsfisis <nsfisis@gmail.com>2024-06-02 04:14:43 +0900
commita2da9e5300e7dd819fd4e2d8af41cf440ed13c79 (patch)
tree41f00317886c57bb2fef4a58350fdc3ad4250f09
parent768eb8265c2e80b25ead00a76125ebfc18fa1fcf (diff)
downloadphp-waddiwasi-a2da9e5300e7dd819fd4e2d8af41cf440ed13c79.tar.gz
php-waddiwasi-a2da9e5300e7dd819fd4e2d8af41cf440ed13c79.tar.zst
php-waddiwasi-a2da9e5300e7dd819fd4e2d8af41cf440ed13c79.zip
fix: i64.add and i64.sub
-rw-r--r--src/Execution/Runtime.php38
1 files changed, 23 insertions, 15 deletions
diff --git a/src/Execution/Runtime.php b/src/Execution/Runtime.php
index 5cf6c75..ade7cf1 100644
--- a/src/Execution/Runtime.php
+++ b/src/Execution/Runtime.php
@@ -1264,7 +1264,8 @@ final class Runtime
{
$c2 = $this->stack->popInt();
$c1 = $this->stack->popInt();
- $this->stack->pushValue($c1 + $c2);
+ $result = self::bigIntToPhpInt(bcadd((string)$c1, (string)$c2));
+ $this->stack->pushValue($result);
}
private function execInstrNumericI64And(Instrs\Numeric\I64And $instr): void
@@ -1462,19 +1463,8 @@ final class Runtime
{
$c2 = $this->stack->popInt();
$c1 = $this->stack->popInt();
- $result = bcmod(bcmul((string)$c1, (string)$c2), bcpow('2', '64'));
- if ($result[0] === '-') {
- // 2^63 <= -$result
- if (bccomp(bcpow('2', '63'), bcsub('0', $result)) <= 0) {
- $result = bcadd($result, bcpow('2', '64'));
- }
- } else {
- // 2^63-1 < $result
- if (bccomp(bcsub(bcpow('2', '63'), '1'), $result) < 0) {
- $result = bcsub($result, bcpow('2', '64'));
- }
- }
- $this->stack->pushValue((int)$result);
+ $result = self::bigIntToPhpInt(bcmul((string)$c1, (string)$c2));
+ $this->stack->pushValue($result);
}
private function execInstrNumericI64Ne(Instrs\Numeric\I64Ne $instr): void
@@ -1584,7 +1574,8 @@ final class Runtime
{
$c2 = $this->stack->popInt();
$c1 = $this->stack->popInt();
- $this->stack->pushValue($c1 - $c2);
+ $result = self::bigIntToPhpInt(bcsub((string)$c1, (string)$c2));
+ $this->stack->pushValue($result);
}
private function execInstrNumericI64TruncF32S(Instrs\Numeric\I64TruncF32S $instr): void
@@ -2537,4 +2528,21 @@ final class Runtime
return $x;
}
}
+
+ private static function bigIntToPhpInt(string $s): int
+ {
+ $result = bcmod($s, bcpow('2', '64'));
+ if ($result[0] === '-') {
+ // 2^63 <= -$result
+ if (bccomp(bcpow('2', '63'), bcsub('0', $result)) <= 0) {
+ $result = bcadd($result, bcpow('2', '64'));
+ }
+ } else {
+ // 2^63-1 < $result
+ if (bccomp(bcsub(bcpow('2', '63'), '1'), $result) < 0) {
+ $result = bcsub($result, bcpow('2', '64'));
+ }
+ }
+ return (int)$result;
+ }
}