diff --git a/Userland/Libraries/LibJIT/Assembler.h b/Userland/Libraries/LibJIT/Assembler.h index e59a8507c3..0d2b393c80 100644 --- a/Userland/Libraries/LibJIT/Assembler.h +++ b/Userland/Libraries/LibJIT/Assembler.h @@ -525,6 +525,27 @@ struct Assembler { } } + void bitwise_xor32(Operand dst, Operand src) + { + if (dst.is_register_or_memory() && src.type == Operand::Type::Reg) { + emit_rex_for_mr(dst, src, REX_W::No); + emit8(0x31); + emit_modrm_mr(dst, src); + } else if (dst.type == Operand::Type::Reg && src.type == Operand::Type::Imm && src.fits_in_i8()) { + emit_rex_for_slash(dst, REX_W::No); + emit8(0x83); + emit_modrm_slash(6, dst); + emit8(src.offset_or_immediate); + } else if (dst.type == Operand::Type::Reg && src.type == Operand::Type::Imm && src.fits_in_i32()) { + emit_rex_for_slash(dst, REX_W::No); + emit8(0x81); + emit_modrm_slash(6, dst); + emit32(src.offset_or_immediate); + } else { + VERIFY_NOT_REACHED(); + } + } + void enter() { push(Operand::Register(Reg::RBP)); diff --git a/Userland/Libraries/LibJS/JIT/Compiler.cpp b/Userland/Libraries/LibJS/JIT/Compiler.cpp index 45906970aa..da18352acb 100644 --- a/Userland/Libraries/LibJS/JIT/Compiler.cpp +++ b/Userland/Libraries/LibJS/JIT/Compiler.cpp @@ -684,6 +684,41 @@ void Compiler::compile_bitwise_or(Bytecode::Op::BitwiseOr const& op) end.link(m_assembler); } +static Value cxx_bitwise_xor(VM& vm, Value lhs, Value rhs) +{ + return TRY_OR_SET_EXCEPTION(bitwise_xor(vm, lhs, rhs)); +} + +void Compiler::compile_bitwise_xor(Bytecode::Op::BitwiseXor const& op) +{ + load_vm_register(ARG1, op.lhs()); + load_accumulator(ARG2); + + Assembler::Label end {}; + + branch_if_both_int32(ARG1, ARG2, [&] { + // ARG1 ^= ARG2 (32-bit) + m_assembler.bitwise_xor32( + Assembler::Operand::Register(ARG1), + Assembler::Operand::Register(ARG2)); + + // 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_bitwise_xor); + 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 2dbab9dfd0..1be48841c5 100644 --- a/Userland/Libraries/LibJS/JIT/Compiler.h +++ b/Userland/Libraries/LibJS/JIT/Compiler.h @@ -54,7 +54,6 @@ private: O(LooselyEquals, abstract_equals) \ O(StrictlyInequals, typed_inequals) \ O(StrictlyEquals, typed_equals) \ - O(BitwiseXor, bitwise_xor) \ O(LeftShift, left_shift) \ O(RightShift, right_shift) \ O(UnsignedRightShift, unsigned_right_shift)