diff options
| author | nsfisis <nsfisis@gmail.com> | 2024-06-02 04:14:43 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2024-06-02 04:14:43 +0900 |
| commit | a2da9e5300e7dd819fd4e2d8af41cf440ed13c79 (patch) | |
| tree | 41f00317886c57bb2fef4a58350fdc3ad4250f09 /src | |
| parent | 768eb8265c2e80b25ead00a76125ebfc18fa1fcf (diff) | |
| download | php-waddiwasi-a2da9e5300e7dd819fd4e2d8af41cf440ed13c79.tar.gz php-waddiwasi-a2da9e5300e7dd819fd4e2d8af41cf440ed13c79.tar.zst php-waddiwasi-a2da9e5300e7dd819fd4e2d8af41cf440ed13c79.zip | |
fix: i64.add and i64.sub
Diffstat (limited to 'src')
| -rw-r--r-- | src/Execution/Runtime.php | 38 |
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; + } } |
