diff --git a/Userland/Libraries/LibJIT/X86_64/Assembler.h b/Userland/Libraries/LibJIT/X86_64/Assembler.h index 5cbe0524a6..146cfc0dca 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 shift_right32(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(5, dest); + emit8(count->offset_or_immediate); + } else { + emit_rex_for_slash(dest, REX_W::No); + emit8(0xd3); + emit_modrm_slash(5, dest); + } + } + void arithmetic_right_shift32(Operand dest, Optional count) { VERIFY(dest.type == Operand::Type::Reg); diff --git a/Userland/Libraries/LibJS/JIT/Compiler.cpp b/Userland/Libraries/LibJS/JIT/Compiler.cpp index 41b22a65de..bdd6385cc5 100644 --- a/Userland/Libraries/LibJS/JIT/Compiler.cpp +++ b/Userland/Libraries/LibJS/JIT/Compiler.cpp @@ -838,6 +838,44 @@ void Compiler::compile_right_shift(Bytecode::Op::RightShift const& op) end.link(m_assembler); } +static Value cxx_unsigned_right_shift(VM& vm, Value lhs, Value rhs) +{ + return TRY_OR_SET_EXCEPTION(unsigned_right_shift(vm, lhs, rhs)); +} + +void Compiler::compile_unsigned_right_shift(Bytecode::Op::UnsignedRightShift 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.shift_right32(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_unsigned_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 596a735e5f..dec5ff0545 100644 --- a/Userland/Libraries/LibJS/JIT/Compiler.h +++ b/Userland/Libraries/LibJS/JIT/Compiler.h @@ -52,8 +52,7 @@ private: O(LooselyInequals, abstract_inequals) \ O(LooselyEquals, abstract_equals) \ O(StrictlyInequals, typed_inequals) \ - O(StrictlyEquals, typed_equals) \ - O(UnsignedRightShift, unsigned_right_shift) + O(StrictlyEquals, typed_equals) # define JS_ENUMERATE_NEW_BUILTIN_ERROR_BYTECODE_OPS(O) \ O(NewTypeError, new_type_error, TypeError)