diff --git a/Userland/Libraries/LibJIT/X86_64/Assembler.h b/Userland/Libraries/LibJIT/X86_64/Assembler.h index 3bbd7d36c2..5cbe0524a6 100644 --- a/Userland/Libraries/LibJIT/X86_64/Assembler.h +++ b/Userland/Libraries/LibJIT/X86_64/Assembler.h @@ -583,6 +583,23 @@ struct X86_64Assembler { } } + void arithmetic_right_shift32(Operand dest, Optional count) + { + VERIFY(dest.type == Operand::Type::Reg); + if (count.has_value()) { + VERIFY(count->type == Operand::Type::Imm); + VERIFY(count->fits_in_u8()); + emit_rex_for_slash(dest, REX_W::No); + emit8(0xc1); + emit_modrm_slash(7, dest); + emit8(count->offset_or_immediate); + } else { + emit_rex_for_slash(dest, REX_W::No); + emit8(0xd3); + emit_modrm_slash(7, dest); + } + } + void enter() { push(Operand::Register(Reg::RBP)); diff --git a/Userland/Libraries/LibJS/JIT/Compiler.cpp b/Userland/Libraries/LibJS/JIT/Compiler.cpp index 1bf40a5814..41b22a65de 100644 --- a/Userland/Libraries/LibJS/JIT/Compiler.cpp +++ b/Userland/Libraries/LibJS/JIT/Compiler.cpp @@ -800,6 +800,44 @@ void Compiler::compile_left_shift(Bytecode::Op::LeftShift const& op) end.link(m_assembler); } +static Value cxx_right_shift(VM& vm, Value lhs, Value rhs) +{ + return TRY_OR_SET_EXCEPTION(right_shift(vm, lhs, rhs)); +} + +void Compiler::compile_right_shift(Bytecode::Op::RightShift const& op) +{ + load_vm_register(ARG1, op.lhs()); + load_accumulator(ARG2); + + Assembler::Label end {}; + + branch_if_both_int32(ARG1, ARG2, [&] { + // RCX = ARG2 + m_assembler.mov( + Assembler::Operand::Register(Assembler::Reg::RCX), + Assembler::Operand::Register(ARG2)); + + // ARG1 >>= CL (32-bit) + m_assembler.arithmetic_right_shift32(Assembler::Operand::Register(ARG1), {}); + + // accumulator = ARG1 | SHIFTED_INT32_TAG; + m_assembler.mov( + Assembler::Operand::Register(GPR0), + Assembler::Operand::Imm(SHIFTED_INT32_TAG)); + m_assembler.bitwise_or( + Assembler::Operand::Register(ARG1), + Assembler::Operand::Register(GPR0)); + store_accumulator(ARG1); + m_assembler.jump(end); + }); + + native_call((void*)cxx_right_shift); + store_accumulator(RET); + check_exception(); + end.link(m_assembler); +} + static ThrowCompletionOr not_(VM&, Value value) { return Value(!value.to_boolean()); diff --git a/Userland/Libraries/LibJS/JIT/Compiler.h b/Userland/Libraries/LibJS/JIT/Compiler.h index 66d6eac6a7..596a735e5f 100644 --- a/Userland/Libraries/LibJS/JIT/Compiler.h +++ b/Userland/Libraries/LibJS/JIT/Compiler.h @@ -53,7 +53,6 @@ private: O(LooselyEquals, abstract_equals) \ O(StrictlyInequals, typed_inequals) \ O(StrictlyEquals, typed_equals) \ - O(RightShift, right_shift) \ O(UnsignedRightShift, unsigned_right_shift) # define JS_ENUMERATE_NEW_BUILTIN_ERROR_BYTECODE_OPS(O) \