11cb0ef41Sopenharmony_ci// Copyright 2017 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci#ifndef V8_WASM_BASELINE_X64_LIFTOFF_ASSEMBLER_X64_H_ 61cb0ef41Sopenharmony_ci#define V8_WASM_BASELINE_X64_LIFTOFF_ASSEMBLER_X64_H_ 71cb0ef41Sopenharmony_ci 81cb0ef41Sopenharmony_ci#include "src/base/platform/wrappers.h" 91cb0ef41Sopenharmony_ci#include "src/codegen/assembler.h" 101cb0ef41Sopenharmony_ci#include "src/codegen/cpu-features.h" 111cb0ef41Sopenharmony_ci#include "src/codegen/machine-type.h" 121cb0ef41Sopenharmony_ci#include "src/codegen/x64/register-x64.h" 131cb0ef41Sopenharmony_ci#include "src/heap/memory-chunk.h" 141cb0ef41Sopenharmony_ci#include "src/wasm/baseline/liftoff-assembler.h" 151cb0ef41Sopenharmony_ci#include "src/wasm/simd-shuffle.h" 161cb0ef41Sopenharmony_ci#include "src/wasm/wasm-objects.h" 171cb0ef41Sopenharmony_ci 181cb0ef41Sopenharmony_cinamespace v8 { 191cb0ef41Sopenharmony_cinamespace internal { 201cb0ef41Sopenharmony_cinamespace wasm { 211cb0ef41Sopenharmony_ci 221cb0ef41Sopenharmony_ci#define RETURN_FALSE_IF_MISSING_CPU_FEATURE(name) \ 231cb0ef41Sopenharmony_ci if (!CpuFeatures::IsSupported(name)) return false; \ 241cb0ef41Sopenharmony_ci CpuFeatureScope feature(this, name); 251cb0ef41Sopenharmony_ci 261cb0ef41Sopenharmony_cinamespace liftoff { 271cb0ef41Sopenharmony_ci 281cb0ef41Sopenharmony_ciinline constexpr Condition ToCondition(LiftoffCondition liftoff_cond) { 291cb0ef41Sopenharmony_ci switch (liftoff_cond) { 301cb0ef41Sopenharmony_ci case kEqual: 311cb0ef41Sopenharmony_ci return equal; 321cb0ef41Sopenharmony_ci case kUnequal: 331cb0ef41Sopenharmony_ci return not_equal; 341cb0ef41Sopenharmony_ci case kSignedLessThan: 351cb0ef41Sopenharmony_ci return less; 361cb0ef41Sopenharmony_ci case kSignedLessEqual: 371cb0ef41Sopenharmony_ci return less_equal; 381cb0ef41Sopenharmony_ci case kSignedGreaterThan: 391cb0ef41Sopenharmony_ci return greater; 401cb0ef41Sopenharmony_ci case kSignedGreaterEqual: 411cb0ef41Sopenharmony_ci return greater_equal; 421cb0ef41Sopenharmony_ci case kUnsignedLessThan: 431cb0ef41Sopenharmony_ci return below; 441cb0ef41Sopenharmony_ci case kUnsignedLessEqual: 451cb0ef41Sopenharmony_ci return below_equal; 461cb0ef41Sopenharmony_ci case kUnsignedGreaterThan: 471cb0ef41Sopenharmony_ci return above; 481cb0ef41Sopenharmony_ci case kUnsignedGreaterEqual: 491cb0ef41Sopenharmony_ci return above_equal; 501cb0ef41Sopenharmony_ci } 511cb0ef41Sopenharmony_ci} 521cb0ef41Sopenharmony_ci 531cb0ef41Sopenharmony_ciconstexpr Register kScratchRegister2 = r11; 541cb0ef41Sopenharmony_cistatic_assert(kScratchRegister != kScratchRegister2, "collision"); 551cb0ef41Sopenharmony_cistatic_assert((kLiftoffAssemblerGpCacheRegs & 561cb0ef41Sopenharmony_ci RegList{kScratchRegister, kScratchRegister2}) 571cb0ef41Sopenharmony_ci .is_empty(), 581cb0ef41Sopenharmony_ci "scratch registers must not be used as cache registers"); 591cb0ef41Sopenharmony_ci 601cb0ef41Sopenharmony_ciconstexpr DoubleRegister kScratchDoubleReg2 = xmm14; 611cb0ef41Sopenharmony_cistatic_assert(kScratchDoubleReg != kScratchDoubleReg2, "collision"); 621cb0ef41Sopenharmony_cistatic_assert((kLiftoffAssemblerFpCacheRegs & 631cb0ef41Sopenharmony_ci DoubleRegList{kScratchDoubleReg, kScratchDoubleReg2}) 641cb0ef41Sopenharmony_ci .is_empty(), 651cb0ef41Sopenharmony_ci "scratch registers must not be used as cache registers"); 661cb0ef41Sopenharmony_ci 671cb0ef41Sopenharmony_ci// rbp-8 holds the stack marker, rbp-16 is the instance parameter. 681cb0ef41Sopenharmony_ciconstexpr int kInstanceOffset = 16; 691cb0ef41Sopenharmony_ciconstexpr int kFeedbackVectorOffset = 24; // rbp-24 is the feedback vector. 701cb0ef41Sopenharmony_ciconstexpr int kTierupBudgetOffset = 32; // rbp-32 is the feedback vector. 711cb0ef41Sopenharmony_ci 721cb0ef41Sopenharmony_ciinline Operand GetStackSlot(int offset) { return Operand(rbp, -offset); } 731cb0ef41Sopenharmony_ci 741cb0ef41Sopenharmony_ci// TODO(clemensb): Make this a constexpr variable once Operand is constexpr. 751cb0ef41Sopenharmony_ciinline Operand GetInstanceOperand() { return GetStackSlot(kInstanceOffset); } 761cb0ef41Sopenharmony_ci 771cb0ef41Sopenharmony_ciinline Operand GetOSRTargetSlot() { return GetStackSlot(kOSRTargetOffset); } 781cb0ef41Sopenharmony_ci 791cb0ef41Sopenharmony_ciinline Operand GetMemOp(LiftoffAssembler* assm, Register addr, Register offset, 801cb0ef41Sopenharmony_ci uintptr_t offset_imm) { 811cb0ef41Sopenharmony_ci if (is_uint31(offset_imm)) { 821cb0ef41Sopenharmony_ci int32_t offset_imm32 = static_cast<int32_t>(offset_imm); 831cb0ef41Sopenharmony_ci return offset == no_reg ? Operand(addr, offset_imm32) 841cb0ef41Sopenharmony_ci : Operand(addr, offset, times_1, offset_imm32); 851cb0ef41Sopenharmony_ci } 861cb0ef41Sopenharmony_ci // Offset immediate does not fit in 31 bits. 871cb0ef41Sopenharmony_ci Register scratch = kScratchRegister; 881cb0ef41Sopenharmony_ci assm->TurboAssembler::Move(scratch, offset_imm); 891cb0ef41Sopenharmony_ci if (offset != no_reg) assm->addq(scratch, offset); 901cb0ef41Sopenharmony_ci return Operand(addr, scratch, times_1, 0); 911cb0ef41Sopenharmony_ci} 921cb0ef41Sopenharmony_ci 931cb0ef41Sopenharmony_ciinline void Load(LiftoffAssembler* assm, LiftoffRegister dst, Operand src, 941cb0ef41Sopenharmony_ci ValueKind kind) { 951cb0ef41Sopenharmony_ci switch (kind) { 961cb0ef41Sopenharmony_ci case kI32: 971cb0ef41Sopenharmony_ci assm->movl(dst.gp(), src); 981cb0ef41Sopenharmony_ci break; 991cb0ef41Sopenharmony_ci case kI64: 1001cb0ef41Sopenharmony_ci case kOptRef: 1011cb0ef41Sopenharmony_ci case kRef: 1021cb0ef41Sopenharmony_ci case kRtt: 1031cb0ef41Sopenharmony_ci assm->movq(dst.gp(), src); 1041cb0ef41Sopenharmony_ci break; 1051cb0ef41Sopenharmony_ci case kF32: 1061cb0ef41Sopenharmony_ci assm->Movss(dst.fp(), src); 1071cb0ef41Sopenharmony_ci break; 1081cb0ef41Sopenharmony_ci case kF64: 1091cb0ef41Sopenharmony_ci assm->Movsd(dst.fp(), src); 1101cb0ef41Sopenharmony_ci break; 1111cb0ef41Sopenharmony_ci case kS128: 1121cb0ef41Sopenharmony_ci assm->Movdqu(dst.fp(), src); 1131cb0ef41Sopenharmony_ci break; 1141cb0ef41Sopenharmony_ci default: 1151cb0ef41Sopenharmony_ci UNREACHABLE(); 1161cb0ef41Sopenharmony_ci } 1171cb0ef41Sopenharmony_ci} 1181cb0ef41Sopenharmony_ci 1191cb0ef41Sopenharmony_ciinline void Store(LiftoffAssembler* assm, Operand dst, LiftoffRegister src, 1201cb0ef41Sopenharmony_ci ValueKind kind) { 1211cb0ef41Sopenharmony_ci switch (kind) { 1221cb0ef41Sopenharmony_ci case kI32: 1231cb0ef41Sopenharmony_ci assm->movl(dst, src.gp()); 1241cb0ef41Sopenharmony_ci break; 1251cb0ef41Sopenharmony_ci case kI64: 1261cb0ef41Sopenharmony_ci assm->movq(dst, src.gp()); 1271cb0ef41Sopenharmony_ci break; 1281cb0ef41Sopenharmony_ci case kOptRef: 1291cb0ef41Sopenharmony_ci case kRef: 1301cb0ef41Sopenharmony_ci case kRtt: 1311cb0ef41Sopenharmony_ci assm->StoreTaggedField(dst, src.gp()); 1321cb0ef41Sopenharmony_ci break; 1331cb0ef41Sopenharmony_ci case kF32: 1341cb0ef41Sopenharmony_ci assm->Movss(dst, src.fp()); 1351cb0ef41Sopenharmony_ci break; 1361cb0ef41Sopenharmony_ci case kF64: 1371cb0ef41Sopenharmony_ci assm->Movsd(dst, src.fp()); 1381cb0ef41Sopenharmony_ci break; 1391cb0ef41Sopenharmony_ci case kS128: 1401cb0ef41Sopenharmony_ci assm->Movdqu(dst, src.fp()); 1411cb0ef41Sopenharmony_ci break; 1421cb0ef41Sopenharmony_ci default: 1431cb0ef41Sopenharmony_ci UNREACHABLE(); 1441cb0ef41Sopenharmony_ci } 1451cb0ef41Sopenharmony_ci} 1461cb0ef41Sopenharmony_ci 1471cb0ef41Sopenharmony_ciinline void push(LiftoffAssembler* assm, LiftoffRegister reg, ValueKind kind, 1481cb0ef41Sopenharmony_ci int padding = 0) { 1491cb0ef41Sopenharmony_ci switch (kind) { 1501cb0ef41Sopenharmony_ci case kI32: 1511cb0ef41Sopenharmony_ci case kI64: 1521cb0ef41Sopenharmony_ci case kRef: 1531cb0ef41Sopenharmony_ci case kOptRef: 1541cb0ef41Sopenharmony_ci assm->AllocateStackSpace(padding); 1551cb0ef41Sopenharmony_ci assm->pushq(reg.gp()); 1561cb0ef41Sopenharmony_ci break; 1571cb0ef41Sopenharmony_ci case kF32: 1581cb0ef41Sopenharmony_ci assm->AllocateStackSpace(kSystemPointerSize + padding); 1591cb0ef41Sopenharmony_ci assm->Movss(Operand(rsp, 0), reg.fp()); 1601cb0ef41Sopenharmony_ci break; 1611cb0ef41Sopenharmony_ci case kF64: 1621cb0ef41Sopenharmony_ci assm->AllocateStackSpace(kSystemPointerSize + padding); 1631cb0ef41Sopenharmony_ci assm->Movsd(Operand(rsp, 0), reg.fp()); 1641cb0ef41Sopenharmony_ci break; 1651cb0ef41Sopenharmony_ci case kS128: 1661cb0ef41Sopenharmony_ci assm->AllocateStackSpace(kSystemPointerSize * 2 + padding); 1671cb0ef41Sopenharmony_ci assm->Movdqu(Operand(rsp, 0), reg.fp()); 1681cb0ef41Sopenharmony_ci break; 1691cb0ef41Sopenharmony_ci default: 1701cb0ef41Sopenharmony_ci UNREACHABLE(); 1711cb0ef41Sopenharmony_ci } 1721cb0ef41Sopenharmony_ci} 1731cb0ef41Sopenharmony_ci 1741cb0ef41Sopenharmony_ciconstexpr int kSubSpSize = 7; // 7 bytes for "subq rsp, <imm32>" 1751cb0ef41Sopenharmony_ci 1761cb0ef41Sopenharmony_ci} // namespace liftoff 1771cb0ef41Sopenharmony_ci 1781cb0ef41Sopenharmony_ciint LiftoffAssembler::PrepareStackFrame() { 1791cb0ef41Sopenharmony_ci int offset = pc_offset(); 1801cb0ef41Sopenharmony_ci // Next we reserve the memory for the whole stack frame. We do not know yet 1811cb0ef41Sopenharmony_ci // how big the stack frame will be so we just emit a placeholder instruction. 1821cb0ef41Sopenharmony_ci // PatchPrepareStackFrame will patch this in order to increase the stack 1831cb0ef41Sopenharmony_ci // appropriately. 1841cb0ef41Sopenharmony_ci sub_sp_32(0); 1851cb0ef41Sopenharmony_ci DCHECK_EQ(liftoff::kSubSpSize, pc_offset() - offset); 1861cb0ef41Sopenharmony_ci return offset; 1871cb0ef41Sopenharmony_ci} 1881cb0ef41Sopenharmony_ci 1891cb0ef41Sopenharmony_civoid LiftoffAssembler::PrepareTailCall(int num_callee_stack_params, 1901cb0ef41Sopenharmony_ci int stack_param_delta) { 1911cb0ef41Sopenharmony_ci // Push the return address and frame pointer to complete the stack frame. 1921cb0ef41Sopenharmony_ci pushq(Operand(rbp, 8)); 1931cb0ef41Sopenharmony_ci pushq(Operand(rbp, 0)); 1941cb0ef41Sopenharmony_ci 1951cb0ef41Sopenharmony_ci // Shift the whole frame upwards. 1961cb0ef41Sopenharmony_ci const int slot_count = num_callee_stack_params + 2; 1971cb0ef41Sopenharmony_ci for (int i = slot_count - 1; i >= 0; --i) { 1981cb0ef41Sopenharmony_ci movq(kScratchRegister, Operand(rsp, i * 8)); 1991cb0ef41Sopenharmony_ci movq(Operand(rbp, (i - stack_param_delta) * 8), kScratchRegister); 2001cb0ef41Sopenharmony_ci } 2011cb0ef41Sopenharmony_ci 2021cb0ef41Sopenharmony_ci // Set the new stack and frame pointer. 2031cb0ef41Sopenharmony_ci leaq(rsp, Operand(rbp, -stack_param_delta * 8)); 2041cb0ef41Sopenharmony_ci popq(rbp); 2051cb0ef41Sopenharmony_ci} 2061cb0ef41Sopenharmony_ci 2071cb0ef41Sopenharmony_civoid LiftoffAssembler::AlignFrameSize() { 2081cb0ef41Sopenharmony_ci max_used_spill_offset_ = RoundUp(max_used_spill_offset_, kSystemPointerSize); 2091cb0ef41Sopenharmony_ci} 2101cb0ef41Sopenharmony_ci 2111cb0ef41Sopenharmony_civoid LiftoffAssembler::PatchPrepareStackFrame( 2121cb0ef41Sopenharmony_ci int offset, SafepointTableBuilder* safepoint_table_builder) { 2131cb0ef41Sopenharmony_ci // The frame_size includes the frame marker and the instance slot. Both are 2141cb0ef41Sopenharmony_ci // pushed as part of frame construction, so we don't need to allocate memory 2151cb0ef41Sopenharmony_ci // for them anymore. 2161cb0ef41Sopenharmony_ci int frame_size = GetTotalFrameSize() - 2 * kSystemPointerSize; 2171cb0ef41Sopenharmony_ci DCHECK_EQ(0, frame_size % kSystemPointerSize); 2181cb0ef41Sopenharmony_ci 2191cb0ef41Sopenharmony_ci // We can't run out of space when patching, just pass anything big enough to 2201cb0ef41Sopenharmony_ci // not cause the assembler to try to grow the buffer. 2211cb0ef41Sopenharmony_ci constexpr int kAvailableSpace = 64; 2221cb0ef41Sopenharmony_ci Assembler patching_assembler( 2231cb0ef41Sopenharmony_ci AssemblerOptions{}, 2241cb0ef41Sopenharmony_ci ExternalAssemblerBuffer(buffer_start_ + offset, kAvailableSpace)); 2251cb0ef41Sopenharmony_ci 2261cb0ef41Sopenharmony_ci if (V8_LIKELY(frame_size < 4 * KB)) { 2271cb0ef41Sopenharmony_ci // This is the standard case for small frames: just subtract from SP and be 2281cb0ef41Sopenharmony_ci // done with it. 2291cb0ef41Sopenharmony_ci patching_assembler.sub_sp_32(frame_size); 2301cb0ef41Sopenharmony_ci DCHECK_EQ(liftoff::kSubSpSize, patching_assembler.pc_offset()); 2311cb0ef41Sopenharmony_ci return; 2321cb0ef41Sopenharmony_ci } 2331cb0ef41Sopenharmony_ci 2341cb0ef41Sopenharmony_ci // The frame size is bigger than 4KB, so we might overflow the available stack 2351cb0ef41Sopenharmony_ci // space if we first allocate the frame and then do the stack check (we will 2361cb0ef41Sopenharmony_ci // need some remaining stack space for throwing the exception). That's why we 2371cb0ef41Sopenharmony_ci // check the available stack space before we allocate the frame. To do this we 2381cb0ef41Sopenharmony_ci // replace the {__ sub(sp, framesize)} with a jump to OOL code that does this 2391cb0ef41Sopenharmony_ci // "extended stack check". 2401cb0ef41Sopenharmony_ci // 2411cb0ef41Sopenharmony_ci // The OOL code can simply be generated here with the normal assembler, 2421cb0ef41Sopenharmony_ci // because all other code generation, including OOL code, has already finished 2431cb0ef41Sopenharmony_ci // when {PatchPrepareStackFrame} is called. The function prologue then jumps 2441cb0ef41Sopenharmony_ci // to the current {pc_offset()} to execute the OOL code for allocating the 2451cb0ef41Sopenharmony_ci // large frame. 2461cb0ef41Sopenharmony_ci 2471cb0ef41Sopenharmony_ci // Emit the unconditional branch in the function prologue (from {offset} to 2481cb0ef41Sopenharmony_ci // {pc_offset()}). 2491cb0ef41Sopenharmony_ci patching_assembler.jmp_rel(pc_offset() - offset); 2501cb0ef41Sopenharmony_ci DCHECK_GE(liftoff::kSubSpSize, patching_assembler.pc_offset()); 2511cb0ef41Sopenharmony_ci patching_assembler.Nop(liftoff::kSubSpSize - patching_assembler.pc_offset()); 2521cb0ef41Sopenharmony_ci 2531cb0ef41Sopenharmony_ci // If the frame is bigger than the stack, we throw the stack overflow 2541cb0ef41Sopenharmony_ci // exception unconditionally. Thereby we can avoid the integer overflow 2551cb0ef41Sopenharmony_ci // check in the condition code. 2561cb0ef41Sopenharmony_ci RecordComment("OOL: stack check for large frame"); 2571cb0ef41Sopenharmony_ci Label continuation; 2581cb0ef41Sopenharmony_ci if (frame_size < FLAG_stack_size * 1024) { 2591cb0ef41Sopenharmony_ci movq(kScratchRegister, 2601cb0ef41Sopenharmony_ci FieldOperand(kWasmInstanceRegister, 2611cb0ef41Sopenharmony_ci WasmInstanceObject::kRealStackLimitAddressOffset)); 2621cb0ef41Sopenharmony_ci movq(kScratchRegister, Operand(kScratchRegister, 0)); 2631cb0ef41Sopenharmony_ci addq(kScratchRegister, Immediate(frame_size)); 2641cb0ef41Sopenharmony_ci cmpq(rsp, kScratchRegister); 2651cb0ef41Sopenharmony_ci j(above_equal, &continuation, Label::kNear); 2661cb0ef41Sopenharmony_ci } 2671cb0ef41Sopenharmony_ci 2681cb0ef41Sopenharmony_ci near_call(wasm::WasmCode::kWasmStackOverflow, RelocInfo::WASM_STUB_CALL); 2691cb0ef41Sopenharmony_ci // The call will not return; just define an empty safepoint. 2701cb0ef41Sopenharmony_ci safepoint_table_builder->DefineSafepoint(this); 2711cb0ef41Sopenharmony_ci AssertUnreachable(AbortReason::kUnexpectedReturnFromWasmTrap); 2721cb0ef41Sopenharmony_ci 2731cb0ef41Sopenharmony_ci bind(&continuation); 2741cb0ef41Sopenharmony_ci 2751cb0ef41Sopenharmony_ci // Now allocate the stack space. Note that this might do more than just 2761cb0ef41Sopenharmony_ci // decrementing the SP; consult {TurboAssembler::AllocateStackSpace}. 2771cb0ef41Sopenharmony_ci AllocateStackSpace(frame_size); 2781cb0ef41Sopenharmony_ci 2791cb0ef41Sopenharmony_ci // Jump back to the start of the function, from {pc_offset()} to 2801cb0ef41Sopenharmony_ci // right after the reserved space for the {__ sub(sp, sp, framesize)} (which 2811cb0ef41Sopenharmony_ci // is a branch now). 2821cb0ef41Sopenharmony_ci int func_start_offset = offset + liftoff::kSubSpSize; 2831cb0ef41Sopenharmony_ci jmp_rel(func_start_offset - pc_offset()); 2841cb0ef41Sopenharmony_ci} 2851cb0ef41Sopenharmony_ci 2861cb0ef41Sopenharmony_civoid LiftoffAssembler::FinishCode() {} 2871cb0ef41Sopenharmony_ci 2881cb0ef41Sopenharmony_civoid LiftoffAssembler::AbortCompilation() {} 2891cb0ef41Sopenharmony_ci 2901cb0ef41Sopenharmony_ci// static 2911cb0ef41Sopenharmony_ciconstexpr int LiftoffAssembler::StaticStackFrameSize() { 2921cb0ef41Sopenharmony_ci return kOSRTargetOffset; 2931cb0ef41Sopenharmony_ci} 2941cb0ef41Sopenharmony_ci 2951cb0ef41Sopenharmony_ciint LiftoffAssembler::SlotSizeForType(ValueKind kind) { 2961cb0ef41Sopenharmony_ci return value_kind_full_size(kind); 2971cb0ef41Sopenharmony_ci} 2981cb0ef41Sopenharmony_ci 2991cb0ef41Sopenharmony_cibool LiftoffAssembler::NeedsAlignment(ValueKind kind) { 3001cb0ef41Sopenharmony_ci return is_reference(kind); 3011cb0ef41Sopenharmony_ci} 3021cb0ef41Sopenharmony_ci 3031cb0ef41Sopenharmony_civoid LiftoffAssembler::LoadConstant(LiftoffRegister reg, WasmValue value, 3041cb0ef41Sopenharmony_ci RelocInfo::Mode rmode) { 3051cb0ef41Sopenharmony_ci switch (value.type().kind()) { 3061cb0ef41Sopenharmony_ci case kI32: 3071cb0ef41Sopenharmony_ci if (value.to_i32() == 0 && RelocInfo::IsNoInfo(rmode)) { 3081cb0ef41Sopenharmony_ci xorl(reg.gp(), reg.gp()); 3091cb0ef41Sopenharmony_ci } else { 3101cb0ef41Sopenharmony_ci movl(reg.gp(), Immediate(value.to_i32(), rmode)); 3111cb0ef41Sopenharmony_ci } 3121cb0ef41Sopenharmony_ci break; 3131cb0ef41Sopenharmony_ci case kI64: 3141cb0ef41Sopenharmony_ci if (RelocInfo::IsNoInfo(rmode)) { 3151cb0ef41Sopenharmony_ci TurboAssembler::Move(reg.gp(), value.to_i64()); 3161cb0ef41Sopenharmony_ci } else { 3171cb0ef41Sopenharmony_ci movq(reg.gp(), Immediate64(value.to_i64(), rmode)); 3181cb0ef41Sopenharmony_ci } 3191cb0ef41Sopenharmony_ci break; 3201cb0ef41Sopenharmony_ci case kF32: 3211cb0ef41Sopenharmony_ci TurboAssembler::Move(reg.fp(), value.to_f32_boxed().get_bits()); 3221cb0ef41Sopenharmony_ci break; 3231cb0ef41Sopenharmony_ci case kF64: 3241cb0ef41Sopenharmony_ci TurboAssembler::Move(reg.fp(), value.to_f64_boxed().get_bits()); 3251cb0ef41Sopenharmony_ci break; 3261cb0ef41Sopenharmony_ci default: 3271cb0ef41Sopenharmony_ci UNREACHABLE(); 3281cb0ef41Sopenharmony_ci } 3291cb0ef41Sopenharmony_ci} 3301cb0ef41Sopenharmony_ci 3311cb0ef41Sopenharmony_civoid LiftoffAssembler::LoadInstanceFromFrame(Register dst) { 3321cb0ef41Sopenharmony_ci movq(dst, liftoff::GetInstanceOperand()); 3331cb0ef41Sopenharmony_ci} 3341cb0ef41Sopenharmony_ci 3351cb0ef41Sopenharmony_civoid LiftoffAssembler::LoadFromInstance(Register dst, Register instance, 3361cb0ef41Sopenharmony_ci int offset, int size) { 3371cb0ef41Sopenharmony_ci DCHECK_LE(0, offset); 3381cb0ef41Sopenharmony_ci Operand src{instance, offset}; 3391cb0ef41Sopenharmony_ci switch (size) { 3401cb0ef41Sopenharmony_ci case 1: 3411cb0ef41Sopenharmony_ci movzxbl(dst, src); 3421cb0ef41Sopenharmony_ci break; 3431cb0ef41Sopenharmony_ci case 4: 3441cb0ef41Sopenharmony_ci movl(dst, src); 3451cb0ef41Sopenharmony_ci break; 3461cb0ef41Sopenharmony_ci case 8: 3471cb0ef41Sopenharmony_ci movq(dst, src); 3481cb0ef41Sopenharmony_ci break; 3491cb0ef41Sopenharmony_ci default: 3501cb0ef41Sopenharmony_ci UNIMPLEMENTED(); 3511cb0ef41Sopenharmony_ci } 3521cb0ef41Sopenharmony_ci} 3531cb0ef41Sopenharmony_ci 3541cb0ef41Sopenharmony_civoid LiftoffAssembler::LoadTaggedPointerFromInstance(Register dst, 3551cb0ef41Sopenharmony_ci Register instance, 3561cb0ef41Sopenharmony_ci int offset) { 3571cb0ef41Sopenharmony_ci DCHECK_LE(0, offset); 3581cb0ef41Sopenharmony_ci LoadTaggedPointerField(dst, Operand(instance, offset)); 3591cb0ef41Sopenharmony_ci} 3601cb0ef41Sopenharmony_ci 3611cb0ef41Sopenharmony_civoid LiftoffAssembler::LoadExternalPointer(Register dst, Register instance, 3621cb0ef41Sopenharmony_ci int offset, ExternalPointerTag tag, 3631cb0ef41Sopenharmony_ci Register isolate_root) { 3641cb0ef41Sopenharmony_ci LoadExternalPointerField(dst, FieldOperand(instance, offset), tag, 3651cb0ef41Sopenharmony_ci isolate_root, 3661cb0ef41Sopenharmony_ci IsolateRootLocation::kInScratchRegister); 3671cb0ef41Sopenharmony_ci} 3681cb0ef41Sopenharmony_ci 3691cb0ef41Sopenharmony_civoid LiftoffAssembler::SpillInstance(Register instance) { 3701cb0ef41Sopenharmony_ci movq(liftoff::GetInstanceOperand(), instance); 3711cb0ef41Sopenharmony_ci} 3721cb0ef41Sopenharmony_ci 3731cb0ef41Sopenharmony_civoid LiftoffAssembler::ResetOSRTarget() { 3741cb0ef41Sopenharmony_ci movq(liftoff::GetOSRTargetSlot(), Immediate(0)); 3751cb0ef41Sopenharmony_ci} 3761cb0ef41Sopenharmony_ci 3771cb0ef41Sopenharmony_civoid LiftoffAssembler::LoadTaggedPointer(Register dst, Register src_addr, 3781cb0ef41Sopenharmony_ci Register offset_reg, 3791cb0ef41Sopenharmony_ci int32_t offset_imm, 3801cb0ef41Sopenharmony_ci LiftoffRegList pinned) { 3811cb0ef41Sopenharmony_ci DCHECK_GE(offset_imm, 0); 3821cb0ef41Sopenharmony_ci if (FLAG_debug_code && offset_reg != no_reg) { 3831cb0ef41Sopenharmony_ci AssertZeroExtended(offset_reg); 3841cb0ef41Sopenharmony_ci } 3851cb0ef41Sopenharmony_ci Operand src_op = liftoff::GetMemOp(this, src_addr, offset_reg, 3861cb0ef41Sopenharmony_ci static_cast<uint32_t>(offset_imm)); 3871cb0ef41Sopenharmony_ci LoadTaggedPointerField(dst, src_op); 3881cb0ef41Sopenharmony_ci} 3891cb0ef41Sopenharmony_ci 3901cb0ef41Sopenharmony_civoid LiftoffAssembler::LoadFullPointer(Register dst, Register src_addr, 3911cb0ef41Sopenharmony_ci int32_t offset_imm) { 3921cb0ef41Sopenharmony_ci Operand src_op = liftoff::GetMemOp(this, src_addr, no_reg, 3931cb0ef41Sopenharmony_ci static_cast<uint32_t>(offset_imm)); 3941cb0ef41Sopenharmony_ci movq(dst, src_op); 3951cb0ef41Sopenharmony_ci} 3961cb0ef41Sopenharmony_ci 3971cb0ef41Sopenharmony_civoid LiftoffAssembler::StoreTaggedPointer(Register dst_addr, 3981cb0ef41Sopenharmony_ci Register offset_reg, 3991cb0ef41Sopenharmony_ci int32_t offset_imm, 4001cb0ef41Sopenharmony_ci LiftoffRegister src, 4011cb0ef41Sopenharmony_ci LiftoffRegList pinned, 4021cb0ef41Sopenharmony_ci SkipWriteBarrier skip_write_barrier) { 4031cb0ef41Sopenharmony_ci DCHECK_GE(offset_imm, 0); 4041cb0ef41Sopenharmony_ci Operand dst_op = liftoff::GetMemOp(this, dst_addr, offset_reg, 4051cb0ef41Sopenharmony_ci static_cast<uint32_t>(offset_imm)); 4061cb0ef41Sopenharmony_ci StoreTaggedField(dst_op, src.gp()); 4071cb0ef41Sopenharmony_ci 4081cb0ef41Sopenharmony_ci if (skip_write_barrier || FLAG_disable_write_barriers) return; 4091cb0ef41Sopenharmony_ci 4101cb0ef41Sopenharmony_ci Register scratch = pinned.set(GetUnusedRegister(kGpReg, pinned)).gp(); 4111cb0ef41Sopenharmony_ci Label write_barrier; 4121cb0ef41Sopenharmony_ci Label exit; 4131cb0ef41Sopenharmony_ci CheckPageFlag(dst_addr, scratch, 4141cb0ef41Sopenharmony_ci MemoryChunk::kPointersFromHereAreInterestingMask, not_zero, 4151cb0ef41Sopenharmony_ci &write_barrier, Label::kNear); 4161cb0ef41Sopenharmony_ci jmp(&exit, Label::kNear); 4171cb0ef41Sopenharmony_ci bind(&write_barrier); 4181cb0ef41Sopenharmony_ci JumpIfSmi(src.gp(), &exit, Label::kNear); 4191cb0ef41Sopenharmony_ci if (COMPRESS_POINTERS_BOOL) { 4201cb0ef41Sopenharmony_ci DecompressTaggedPointer(src.gp(), src.gp()); 4211cb0ef41Sopenharmony_ci } 4221cb0ef41Sopenharmony_ci CheckPageFlag(src.gp(), scratch, 4231cb0ef41Sopenharmony_ci MemoryChunk::kPointersToHereAreInterestingMask, zero, &exit, 4241cb0ef41Sopenharmony_ci Label::kNear); 4251cb0ef41Sopenharmony_ci leaq(scratch, dst_op); 4261cb0ef41Sopenharmony_ci 4271cb0ef41Sopenharmony_ci CallRecordWriteStubSaveRegisters( 4281cb0ef41Sopenharmony_ci dst_addr, scratch, RememberedSetAction::kEmit, SaveFPRegsMode::kSave, 4291cb0ef41Sopenharmony_ci StubCallMode::kCallWasmRuntimeStub); 4301cb0ef41Sopenharmony_ci bind(&exit); 4311cb0ef41Sopenharmony_ci} 4321cb0ef41Sopenharmony_ci 4331cb0ef41Sopenharmony_civoid LiftoffAssembler::AtomicLoad(LiftoffRegister dst, Register src_addr, 4341cb0ef41Sopenharmony_ci Register offset_reg, uintptr_t offset_imm, 4351cb0ef41Sopenharmony_ci LoadType type, LiftoffRegList pinned) { 4361cb0ef41Sopenharmony_ci Load(dst, src_addr, offset_reg, offset_imm, type, pinned, nullptr, true); 4371cb0ef41Sopenharmony_ci} 4381cb0ef41Sopenharmony_ci 4391cb0ef41Sopenharmony_civoid LiftoffAssembler::Load(LiftoffRegister dst, Register src_addr, 4401cb0ef41Sopenharmony_ci Register offset_reg, uintptr_t offset_imm, 4411cb0ef41Sopenharmony_ci LoadType type, LiftoffRegList pinned, 4421cb0ef41Sopenharmony_ci uint32_t* protected_load_pc, bool is_load_mem, 4431cb0ef41Sopenharmony_ci bool i64_offset) { 4441cb0ef41Sopenharmony_ci if (offset_reg != no_reg && !i64_offset) { 4451cb0ef41Sopenharmony_ci AssertZeroExtended(offset_reg); 4461cb0ef41Sopenharmony_ci } 4471cb0ef41Sopenharmony_ci Operand src_op = liftoff::GetMemOp(this, src_addr, offset_reg, offset_imm); 4481cb0ef41Sopenharmony_ci if (protected_load_pc) *protected_load_pc = pc_offset(); 4491cb0ef41Sopenharmony_ci switch (type.value()) { 4501cb0ef41Sopenharmony_ci case LoadType::kI32Load8U: 4511cb0ef41Sopenharmony_ci case LoadType::kI64Load8U: 4521cb0ef41Sopenharmony_ci movzxbl(dst.gp(), src_op); 4531cb0ef41Sopenharmony_ci break; 4541cb0ef41Sopenharmony_ci case LoadType::kI32Load8S: 4551cb0ef41Sopenharmony_ci movsxbl(dst.gp(), src_op); 4561cb0ef41Sopenharmony_ci break; 4571cb0ef41Sopenharmony_ci case LoadType::kI64Load8S: 4581cb0ef41Sopenharmony_ci movsxbq(dst.gp(), src_op); 4591cb0ef41Sopenharmony_ci break; 4601cb0ef41Sopenharmony_ci case LoadType::kI32Load16U: 4611cb0ef41Sopenharmony_ci case LoadType::kI64Load16U: 4621cb0ef41Sopenharmony_ci movzxwl(dst.gp(), src_op); 4631cb0ef41Sopenharmony_ci break; 4641cb0ef41Sopenharmony_ci case LoadType::kI32Load16S: 4651cb0ef41Sopenharmony_ci movsxwl(dst.gp(), src_op); 4661cb0ef41Sopenharmony_ci break; 4671cb0ef41Sopenharmony_ci case LoadType::kI64Load16S: 4681cb0ef41Sopenharmony_ci movsxwq(dst.gp(), src_op); 4691cb0ef41Sopenharmony_ci break; 4701cb0ef41Sopenharmony_ci case LoadType::kI32Load: 4711cb0ef41Sopenharmony_ci case LoadType::kI64Load32U: 4721cb0ef41Sopenharmony_ci movl(dst.gp(), src_op); 4731cb0ef41Sopenharmony_ci break; 4741cb0ef41Sopenharmony_ci case LoadType::kI64Load32S: 4751cb0ef41Sopenharmony_ci movsxlq(dst.gp(), src_op); 4761cb0ef41Sopenharmony_ci break; 4771cb0ef41Sopenharmony_ci case LoadType::kI64Load: 4781cb0ef41Sopenharmony_ci movq(dst.gp(), src_op); 4791cb0ef41Sopenharmony_ci break; 4801cb0ef41Sopenharmony_ci case LoadType::kF32Load: 4811cb0ef41Sopenharmony_ci Movss(dst.fp(), src_op); 4821cb0ef41Sopenharmony_ci break; 4831cb0ef41Sopenharmony_ci case LoadType::kF64Load: 4841cb0ef41Sopenharmony_ci Movsd(dst.fp(), src_op); 4851cb0ef41Sopenharmony_ci break; 4861cb0ef41Sopenharmony_ci case LoadType::kS128Load: 4871cb0ef41Sopenharmony_ci Movdqu(dst.fp(), src_op); 4881cb0ef41Sopenharmony_ci break; 4891cb0ef41Sopenharmony_ci } 4901cb0ef41Sopenharmony_ci} 4911cb0ef41Sopenharmony_ci 4921cb0ef41Sopenharmony_civoid LiftoffAssembler::Store(Register dst_addr, Register offset_reg, 4931cb0ef41Sopenharmony_ci uintptr_t offset_imm, LiftoffRegister src, 4941cb0ef41Sopenharmony_ci StoreType type, LiftoffRegList /* pinned */, 4951cb0ef41Sopenharmony_ci uint32_t* protected_store_pc, bool is_store_mem) { 4961cb0ef41Sopenharmony_ci Operand dst_op = liftoff::GetMemOp(this, dst_addr, offset_reg, offset_imm); 4971cb0ef41Sopenharmony_ci if (protected_store_pc) *protected_store_pc = pc_offset(); 4981cb0ef41Sopenharmony_ci switch (type.value()) { 4991cb0ef41Sopenharmony_ci case StoreType::kI32Store8: 5001cb0ef41Sopenharmony_ci case StoreType::kI64Store8: 5011cb0ef41Sopenharmony_ci movb(dst_op, src.gp()); 5021cb0ef41Sopenharmony_ci break; 5031cb0ef41Sopenharmony_ci case StoreType::kI32Store16: 5041cb0ef41Sopenharmony_ci case StoreType::kI64Store16: 5051cb0ef41Sopenharmony_ci movw(dst_op, src.gp()); 5061cb0ef41Sopenharmony_ci break; 5071cb0ef41Sopenharmony_ci case StoreType::kI32Store: 5081cb0ef41Sopenharmony_ci case StoreType::kI64Store32: 5091cb0ef41Sopenharmony_ci movl(dst_op, src.gp()); 5101cb0ef41Sopenharmony_ci break; 5111cb0ef41Sopenharmony_ci case StoreType::kI64Store: 5121cb0ef41Sopenharmony_ci movq(dst_op, src.gp()); 5131cb0ef41Sopenharmony_ci break; 5141cb0ef41Sopenharmony_ci case StoreType::kF32Store: 5151cb0ef41Sopenharmony_ci Movss(dst_op, src.fp()); 5161cb0ef41Sopenharmony_ci break; 5171cb0ef41Sopenharmony_ci case StoreType::kF64Store: 5181cb0ef41Sopenharmony_ci Movsd(dst_op, src.fp()); 5191cb0ef41Sopenharmony_ci break; 5201cb0ef41Sopenharmony_ci case StoreType::kS128Store: 5211cb0ef41Sopenharmony_ci Movdqu(dst_op, src.fp()); 5221cb0ef41Sopenharmony_ci break; 5231cb0ef41Sopenharmony_ci } 5241cb0ef41Sopenharmony_ci} 5251cb0ef41Sopenharmony_ci 5261cb0ef41Sopenharmony_civoid LiftoffAssembler::AtomicStore(Register dst_addr, Register offset_reg, 5271cb0ef41Sopenharmony_ci uintptr_t offset_imm, LiftoffRegister src, 5281cb0ef41Sopenharmony_ci StoreType type, LiftoffRegList pinned) { 5291cb0ef41Sopenharmony_ci Operand dst_op = liftoff::GetMemOp(this, dst_addr, offset_reg, offset_imm); 5301cb0ef41Sopenharmony_ci Register src_reg = src.gp(); 5311cb0ef41Sopenharmony_ci if (cache_state()->is_used(src)) { 5321cb0ef41Sopenharmony_ci movq(kScratchRegister, src_reg); 5331cb0ef41Sopenharmony_ci src_reg = kScratchRegister; 5341cb0ef41Sopenharmony_ci } 5351cb0ef41Sopenharmony_ci switch (type.value()) { 5361cb0ef41Sopenharmony_ci case StoreType::kI32Store8: 5371cb0ef41Sopenharmony_ci case StoreType::kI64Store8: 5381cb0ef41Sopenharmony_ci xchgb(src_reg, dst_op); 5391cb0ef41Sopenharmony_ci break; 5401cb0ef41Sopenharmony_ci case StoreType::kI32Store16: 5411cb0ef41Sopenharmony_ci case StoreType::kI64Store16: 5421cb0ef41Sopenharmony_ci xchgw(src_reg, dst_op); 5431cb0ef41Sopenharmony_ci break; 5441cb0ef41Sopenharmony_ci case StoreType::kI32Store: 5451cb0ef41Sopenharmony_ci case StoreType::kI64Store32: 5461cb0ef41Sopenharmony_ci xchgl(src_reg, dst_op); 5471cb0ef41Sopenharmony_ci break; 5481cb0ef41Sopenharmony_ci case StoreType::kI64Store: 5491cb0ef41Sopenharmony_ci xchgq(src_reg, dst_op); 5501cb0ef41Sopenharmony_ci break; 5511cb0ef41Sopenharmony_ci default: 5521cb0ef41Sopenharmony_ci UNREACHABLE(); 5531cb0ef41Sopenharmony_ci } 5541cb0ef41Sopenharmony_ci} 5551cb0ef41Sopenharmony_ci 5561cb0ef41Sopenharmony_civoid LiftoffAssembler::AtomicAdd(Register dst_addr, Register offset_reg, 5571cb0ef41Sopenharmony_ci uintptr_t offset_imm, LiftoffRegister value, 5581cb0ef41Sopenharmony_ci LiftoffRegister result, StoreType type) { 5591cb0ef41Sopenharmony_ci DCHECK(!cache_state()->is_used(result)); 5601cb0ef41Sopenharmony_ci if (cache_state()->is_used(value)) { 5611cb0ef41Sopenharmony_ci // We cannot overwrite {value}, but the {value} register is changed in the 5621cb0ef41Sopenharmony_ci // code we generate. Therefore we copy {value} to {result} and use the 5631cb0ef41Sopenharmony_ci // {result} register in the code below. 5641cb0ef41Sopenharmony_ci movq(result.gp(), value.gp()); 5651cb0ef41Sopenharmony_ci value = result; 5661cb0ef41Sopenharmony_ci } 5671cb0ef41Sopenharmony_ci Operand dst_op = liftoff::GetMemOp(this, dst_addr, offset_reg, offset_imm); 5681cb0ef41Sopenharmony_ci lock(); 5691cb0ef41Sopenharmony_ci switch (type.value()) { 5701cb0ef41Sopenharmony_ci case StoreType::kI32Store8: 5711cb0ef41Sopenharmony_ci case StoreType::kI64Store8: 5721cb0ef41Sopenharmony_ci xaddb(dst_op, value.gp()); 5731cb0ef41Sopenharmony_ci movzxbq(result.gp(), value.gp()); 5741cb0ef41Sopenharmony_ci break; 5751cb0ef41Sopenharmony_ci case StoreType::kI32Store16: 5761cb0ef41Sopenharmony_ci case StoreType::kI64Store16: 5771cb0ef41Sopenharmony_ci xaddw(dst_op, value.gp()); 5781cb0ef41Sopenharmony_ci movzxwq(result.gp(), value.gp()); 5791cb0ef41Sopenharmony_ci break; 5801cb0ef41Sopenharmony_ci case StoreType::kI32Store: 5811cb0ef41Sopenharmony_ci case StoreType::kI64Store32: 5821cb0ef41Sopenharmony_ci xaddl(dst_op, value.gp()); 5831cb0ef41Sopenharmony_ci if (value != result) { 5841cb0ef41Sopenharmony_ci movq(result.gp(), value.gp()); 5851cb0ef41Sopenharmony_ci } 5861cb0ef41Sopenharmony_ci break; 5871cb0ef41Sopenharmony_ci case StoreType::kI64Store: 5881cb0ef41Sopenharmony_ci xaddq(dst_op, value.gp()); 5891cb0ef41Sopenharmony_ci if (value != result) { 5901cb0ef41Sopenharmony_ci movq(result.gp(), value.gp()); 5911cb0ef41Sopenharmony_ci } 5921cb0ef41Sopenharmony_ci break; 5931cb0ef41Sopenharmony_ci default: 5941cb0ef41Sopenharmony_ci UNREACHABLE(); 5951cb0ef41Sopenharmony_ci } 5961cb0ef41Sopenharmony_ci} 5971cb0ef41Sopenharmony_ci 5981cb0ef41Sopenharmony_civoid LiftoffAssembler::AtomicSub(Register dst_addr, Register offset_reg, 5991cb0ef41Sopenharmony_ci uintptr_t offset_imm, LiftoffRegister value, 6001cb0ef41Sopenharmony_ci LiftoffRegister result, StoreType type) { 6011cb0ef41Sopenharmony_ci LiftoffRegList dont_overwrite = 6021cb0ef41Sopenharmony_ci cache_state()->used_registers | LiftoffRegList{dst_addr, offset_reg}; 6031cb0ef41Sopenharmony_ci DCHECK(!dont_overwrite.has(result)); 6041cb0ef41Sopenharmony_ci if (dont_overwrite.has(value)) { 6051cb0ef41Sopenharmony_ci // We cannot overwrite {value}, but the {value} register is changed in the 6061cb0ef41Sopenharmony_ci // code we generate. Therefore we copy {value} to {result} and use the 6071cb0ef41Sopenharmony_ci // {result} register in the code below. 6081cb0ef41Sopenharmony_ci movq(result.gp(), value.gp()); 6091cb0ef41Sopenharmony_ci value = result; 6101cb0ef41Sopenharmony_ci } 6111cb0ef41Sopenharmony_ci Operand dst_op = liftoff::GetMemOp(this, dst_addr, offset_reg, offset_imm); 6121cb0ef41Sopenharmony_ci switch (type.value()) { 6131cb0ef41Sopenharmony_ci case StoreType::kI32Store8: 6141cb0ef41Sopenharmony_ci case StoreType::kI64Store8: 6151cb0ef41Sopenharmony_ci negb(value.gp()); 6161cb0ef41Sopenharmony_ci lock(); 6171cb0ef41Sopenharmony_ci xaddb(dst_op, value.gp()); 6181cb0ef41Sopenharmony_ci movzxbq(result.gp(), value.gp()); 6191cb0ef41Sopenharmony_ci break; 6201cb0ef41Sopenharmony_ci case StoreType::kI32Store16: 6211cb0ef41Sopenharmony_ci case StoreType::kI64Store16: 6221cb0ef41Sopenharmony_ci negw(value.gp()); 6231cb0ef41Sopenharmony_ci lock(); 6241cb0ef41Sopenharmony_ci xaddw(dst_op, value.gp()); 6251cb0ef41Sopenharmony_ci movzxwq(result.gp(), value.gp()); 6261cb0ef41Sopenharmony_ci break; 6271cb0ef41Sopenharmony_ci case StoreType::kI32Store: 6281cb0ef41Sopenharmony_ci case StoreType::kI64Store32: 6291cb0ef41Sopenharmony_ci negl(value.gp()); 6301cb0ef41Sopenharmony_ci lock(); 6311cb0ef41Sopenharmony_ci xaddl(dst_op, value.gp()); 6321cb0ef41Sopenharmony_ci if (value != result) { 6331cb0ef41Sopenharmony_ci movq(result.gp(), value.gp()); 6341cb0ef41Sopenharmony_ci } 6351cb0ef41Sopenharmony_ci break; 6361cb0ef41Sopenharmony_ci case StoreType::kI64Store: 6371cb0ef41Sopenharmony_ci negq(value.gp()); 6381cb0ef41Sopenharmony_ci lock(); 6391cb0ef41Sopenharmony_ci xaddq(dst_op, value.gp()); 6401cb0ef41Sopenharmony_ci if (value != result) { 6411cb0ef41Sopenharmony_ci movq(result.gp(), value.gp()); 6421cb0ef41Sopenharmony_ci } 6431cb0ef41Sopenharmony_ci break; 6441cb0ef41Sopenharmony_ci default: 6451cb0ef41Sopenharmony_ci UNREACHABLE(); 6461cb0ef41Sopenharmony_ci } 6471cb0ef41Sopenharmony_ci} 6481cb0ef41Sopenharmony_ci 6491cb0ef41Sopenharmony_cinamespace liftoff { 6501cb0ef41Sopenharmony_ci#define __ lasm-> 6511cb0ef41Sopenharmony_ci 6521cb0ef41Sopenharmony_ciinline void AtomicBinop(LiftoffAssembler* lasm, 6531cb0ef41Sopenharmony_ci void (Assembler::*opl)(Register, Register), 6541cb0ef41Sopenharmony_ci void (Assembler::*opq)(Register, Register), 6551cb0ef41Sopenharmony_ci Register dst_addr, Register offset_reg, 6561cb0ef41Sopenharmony_ci uintptr_t offset_imm, LiftoffRegister value, 6571cb0ef41Sopenharmony_ci LiftoffRegister result, StoreType type) { 6581cb0ef41Sopenharmony_ci DCHECK(!__ cache_state()->is_used(result)); 6591cb0ef41Sopenharmony_ci Register value_reg = value.gp(); 6601cb0ef41Sopenharmony_ci // The cmpxchg instruction uses rax to store the old value of the 6611cb0ef41Sopenharmony_ci // compare-exchange primitive. Therefore we have to spill the register and 6621cb0ef41Sopenharmony_ci // move any use to another register. 6631cb0ef41Sopenharmony_ci LiftoffRegList pinned = LiftoffRegList{dst_addr, offset_reg, value_reg}; 6641cb0ef41Sopenharmony_ci __ ClearRegister(rax, {&dst_addr, &offset_reg, &value_reg}, pinned); 6651cb0ef41Sopenharmony_ci Operand dst_op = liftoff::GetMemOp(lasm, dst_addr, offset_reg, offset_imm); 6661cb0ef41Sopenharmony_ci 6671cb0ef41Sopenharmony_ci switch (type.value()) { 6681cb0ef41Sopenharmony_ci case StoreType::kI32Store8: 6691cb0ef41Sopenharmony_ci case StoreType::kI64Store8: { 6701cb0ef41Sopenharmony_ci Label binop; 6711cb0ef41Sopenharmony_ci __ xorq(rax, rax); 6721cb0ef41Sopenharmony_ci __ movb(rax, dst_op); 6731cb0ef41Sopenharmony_ci __ bind(&binop); 6741cb0ef41Sopenharmony_ci __ movl(kScratchRegister, rax); 6751cb0ef41Sopenharmony_ci (lasm->*opl)(kScratchRegister, value_reg); 6761cb0ef41Sopenharmony_ci __ lock(); 6771cb0ef41Sopenharmony_ci __ cmpxchgb(dst_op, kScratchRegister); 6781cb0ef41Sopenharmony_ci __ j(not_equal, &binop); 6791cb0ef41Sopenharmony_ci break; 6801cb0ef41Sopenharmony_ci } 6811cb0ef41Sopenharmony_ci case StoreType::kI32Store16: 6821cb0ef41Sopenharmony_ci case StoreType::kI64Store16: { 6831cb0ef41Sopenharmony_ci Label binop; 6841cb0ef41Sopenharmony_ci __ xorq(rax, rax); 6851cb0ef41Sopenharmony_ci __ movw(rax, dst_op); 6861cb0ef41Sopenharmony_ci __ bind(&binop); 6871cb0ef41Sopenharmony_ci __ movl(kScratchRegister, rax); 6881cb0ef41Sopenharmony_ci (lasm->*opl)(kScratchRegister, value_reg); 6891cb0ef41Sopenharmony_ci __ lock(); 6901cb0ef41Sopenharmony_ci __ cmpxchgw(dst_op, kScratchRegister); 6911cb0ef41Sopenharmony_ci __ j(not_equal, &binop); 6921cb0ef41Sopenharmony_ci break; 6931cb0ef41Sopenharmony_ci } 6941cb0ef41Sopenharmony_ci case StoreType::kI32Store: 6951cb0ef41Sopenharmony_ci case StoreType::kI64Store32: { 6961cb0ef41Sopenharmony_ci Label binop; 6971cb0ef41Sopenharmony_ci __ movl(rax, dst_op); 6981cb0ef41Sopenharmony_ci __ bind(&binop); 6991cb0ef41Sopenharmony_ci __ movl(kScratchRegister, rax); 7001cb0ef41Sopenharmony_ci (lasm->*opl)(kScratchRegister, value_reg); 7011cb0ef41Sopenharmony_ci __ lock(); 7021cb0ef41Sopenharmony_ci __ cmpxchgl(dst_op, kScratchRegister); 7031cb0ef41Sopenharmony_ci __ j(not_equal, &binop); 7041cb0ef41Sopenharmony_ci break; 7051cb0ef41Sopenharmony_ci } 7061cb0ef41Sopenharmony_ci case StoreType::kI64Store: { 7071cb0ef41Sopenharmony_ci Label binop; 7081cb0ef41Sopenharmony_ci __ movq(rax, dst_op); 7091cb0ef41Sopenharmony_ci __ bind(&binop); 7101cb0ef41Sopenharmony_ci __ movq(kScratchRegister, rax); 7111cb0ef41Sopenharmony_ci (lasm->*opq)(kScratchRegister, value_reg); 7121cb0ef41Sopenharmony_ci __ lock(); 7131cb0ef41Sopenharmony_ci __ cmpxchgq(dst_op, kScratchRegister); 7141cb0ef41Sopenharmony_ci __ j(not_equal, &binop); 7151cb0ef41Sopenharmony_ci break; 7161cb0ef41Sopenharmony_ci } 7171cb0ef41Sopenharmony_ci default: 7181cb0ef41Sopenharmony_ci UNREACHABLE(); 7191cb0ef41Sopenharmony_ci } 7201cb0ef41Sopenharmony_ci 7211cb0ef41Sopenharmony_ci if (result.gp() != rax) { 7221cb0ef41Sopenharmony_ci __ movq(result.gp(), rax); 7231cb0ef41Sopenharmony_ci } 7241cb0ef41Sopenharmony_ci} 7251cb0ef41Sopenharmony_ci#undef __ 7261cb0ef41Sopenharmony_ci} // namespace liftoff 7271cb0ef41Sopenharmony_ci 7281cb0ef41Sopenharmony_civoid LiftoffAssembler::AtomicAnd(Register dst_addr, Register offset_reg, 7291cb0ef41Sopenharmony_ci uintptr_t offset_imm, LiftoffRegister value, 7301cb0ef41Sopenharmony_ci LiftoffRegister result, StoreType type) { 7311cb0ef41Sopenharmony_ci liftoff::AtomicBinop(this, &Assembler::andl, &Assembler::andq, dst_addr, 7321cb0ef41Sopenharmony_ci offset_reg, offset_imm, value, result, type); 7331cb0ef41Sopenharmony_ci} 7341cb0ef41Sopenharmony_ci 7351cb0ef41Sopenharmony_civoid LiftoffAssembler::AtomicOr(Register dst_addr, Register offset_reg, 7361cb0ef41Sopenharmony_ci uintptr_t offset_imm, LiftoffRegister value, 7371cb0ef41Sopenharmony_ci LiftoffRegister result, StoreType type) { 7381cb0ef41Sopenharmony_ci liftoff::AtomicBinop(this, &Assembler::orl, &Assembler::orq, dst_addr, 7391cb0ef41Sopenharmony_ci offset_reg, offset_imm, value, result, type); 7401cb0ef41Sopenharmony_ci} 7411cb0ef41Sopenharmony_ci 7421cb0ef41Sopenharmony_civoid LiftoffAssembler::AtomicXor(Register dst_addr, Register offset_reg, 7431cb0ef41Sopenharmony_ci uintptr_t offset_imm, LiftoffRegister value, 7441cb0ef41Sopenharmony_ci LiftoffRegister result, StoreType type) { 7451cb0ef41Sopenharmony_ci liftoff::AtomicBinop(this, &Assembler::xorl, &Assembler::xorq, dst_addr, 7461cb0ef41Sopenharmony_ci offset_reg, offset_imm, value, result, type); 7471cb0ef41Sopenharmony_ci} 7481cb0ef41Sopenharmony_ci 7491cb0ef41Sopenharmony_civoid LiftoffAssembler::AtomicExchange(Register dst_addr, Register offset_reg, 7501cb0ef41Sopenharmony_ci uintptr_t offset_imm, 7511cb0ef41Sopenharmony_ci LiftoffRegister value, 7521cb0ef41Sopenharmony_ci LiftoffRegister result, StoreType type) { 7531cb0ef41Sopenharmony_ci DCHECK(!cache_state()->is_used(result)); 7541cb0ef41Sopenharmony_ci if (cache_state()->is_used(value)) { 7551cb0ef41Sopenharmony_ci // We cannot overwrite {value}, but the {value} register is changed in the 7561cb0ef41Sopenharmony_ci // code we generate. Therefore we copy {value} to {result} and use the 7571cb0ef41Sopenharmony_ci // {result} register in the code below. 7581cb0ef41Sopenharmony_ci movq(result.gp(), value.gp()); 7591cb0ef41Sopenharmony_ci value = result; 7601cb0ef41Sopenharmony_ci } 7611cb0ef41Sopenharmony_ci Operand dst_op = liftoff::GetMemOp(this, dst_addr, offset_reg, offset_imm); 7621cb0ef41Sopenharmony_ci switch (type.value()) { 7631cb0ef41Sopenharmony_ci case StoreType::kI32Store8: 7641cb0ef41Sopenharmony_ci case StoreType::kI64Store8: 7651cb0ef41Sopenharmony_ci xchgb(value.gp(), dst_op); 7661cb0ef41Sopenharmony_ci movzxbq(result.gp(), value.gp()); 7671cb0ef41Sopenharmony_ci break; 7681cb0ef41Sopenharmony_ci case StoreType::kI32Store16: 7691cb0ef41Sopenharmony_ci case StoreType::kI64Store16: 7701cb0ef41Sopenharmony_ci xchgw(value.gp(), dst_op); 7711cb0ef41Sopenharmony_ci movzxwq(result.gp(), value.gp()); 7721cb0ef41Sopenharmony_ci break; 7731cb0ef41Sopenharmony_ci case StoreType::kI32Store: 7741cb0ef41Sopenharmony_ci case StoreType::kI64Store32: 7751cb0ef41Sopenharmony_ci xchgl(value.gp(), dst_op); 7761cb0ef41Sopenharmony_ci if (value != result) { 7771cb0ef41Sopenharmony_ci movq(result.gp(), value.gp()); 7781cb0ef41Sopenharmony_ci } 7791cb0ef41Sopenharmony_ci break; 7801cb0ef41Sopenharmony_ci case StoreType::kI64Store: 7811cb0ef41Sopenharmony_ci xchgq(value.gp(), dst_op); 7821cb0ef41Sopenharmony_ci if (value != result) { 7831cb0ef41Sopenharmony_ci movq(result.gp(), value.gp()); 7841cb0ef41Sopenharmony_ci } 7851cb0ef41Sopenharmony_ci break; 7861cb0ef41Sopenharmony_ci default: 7871cb0ef41Sopenharmony_ci UNREACHABLE(); 7881cb0ef41Sopenharmony_ci } 7891cb0ef41Sopenharmony_ci} 7901cb0ef41Sopenharmony_ci 7911cb0ef41Sopenharmony_civoid LiftoffAssembler::AtomicCompareExchange( 7921cb0ef41Sopenharmony_ci Register dst_addr, Register offset_reg, uintptr_t offset_imm, 7931cb0ef41Sopenharmony_ci LiftoffRegister expected, LiftoffRegister new_value, LiftoffRegister result, 7941cb0ef41Sopenharmony_ci StoreType type) { 7951cb0ef41Sopenharmony_ci Register value_reg = new_value.gp(); 7961cb0ef41Sopenharmony_ci // The cmpxchg instruction uses rax to store the old value of the 7971cb0ef41Sopenharmony_ci // compare-exchange primitive. Therefore we have to spill the register and 7981cb0ef41Sopenharmony_ci // move any use to another register. 7991cb0ef41Sopenharmony_ci LiftoffRegList pinned = 8001cb0ef41Sopenharmony_ci LiftoffRegList{dst_addr, offset_reg, expected, value_reg}; 8011cb0ef41Sopenharmony_ci ClearRegister(rax, {&dst_addr, &offset_reg, &value_reg}, pinned); 8021cb0ef41Sopenharmony_ci if (expected.gp() != rax) { 8031cb0ef41Sopenharmony_ci movq(rax, expected.gp()); 8041cb0ef41Sopenharmony_ci } 8051cb0ef41Sopenharmony_ci 8061cb0ef41Sopenharmony_ci Operand dst_op = liftoff::GetMemOp(this, dst_addr, offset_reg, offset_imm); 8071cb0ef41Sopenharmony_ci 8081cb0ef41Sopenharmony_ci lock(); 8091cb0ef41Sopenharmony_ci switch (type.value()) { 8101cb0ef41Sopenharmony_ci case StoreType::kI32Store8: 8111cb0ef41Sopenharmony_ci case StoreType::kI64Store8: { 8121cb0ef41Sopenharmony_ci cmpxchgb(dst_op, value_reg); 8131cb0ef41Sopenharmony_ci movzxbq(result.gp(), rax); 8141cb0ef41Sopenharmony_ci break; 8151cb0ef41Sopenharmony_ci } 8161cb0ef41Sopenharmony_ci case StoreType::kI32Store16: 8171cb0ef41Sopenharmony_ci case StoreType::kI64Store16: { 8181cb0ef41Sopenharmony_ci cmpxchgw(dst_op, value_reg); 8191cb0ef41Sopenharmony_ci movzxwq(result.gp(), rax); 8201cb0ef41Sopenharmony_ci break; 8211cb0ef41Sopenharmony_ci } 8221cb0ef41Sopenharmony_ci case StoreType::kI32Store: { 8231cb0ef41Sopenharmony_ci cmpxchgl(dst_op, value_reg); 8241cb0ef41Sopenharmony_ci if (result.gp() != rax) { 8251cb0ef41Sopenharmony_ci movl(result.gp(), rax); 8261cb0ef41Sopenharmony_ci } 8271cb0ef41Sopenharmony_ci break; 8281cb0ef41Sopenharmony_ci } 8291cb0ef41Sopenharmony_ci case StoreType::kI64Store32: { 8301cb0ef41Sopenharmony_ci cmpxchgl(dst_op, value_reg); 8311cb0ef41Sopenharmony_ci // Zero extension. 8321cb0ef41Sopenharmony_ci movl(result.gp(), rax); 8331cb0ef41Sopenharmony_ci break; 8341cb0ef41Sopenharmony_ci } 8351cb0ef41Sopenharmony_ci case StoreType::kI64Store: { 8361cb0ef41Sopenharmony_ci cmpxchgq(dst_op, value_reg); 8371cb0ef41Sopenharmony_ci if (result.gp() != rax) { 8381cb0ef41Sopenharmony_ci movq(result.gp(), rax); 8391cb0ef41Sopenharmony_ci } 8401cb0ef41Sopenharmony_ci break; 8411cb0ef41Sopenharmony_ci } 8421cb0ef41Sopenharmony_ci default: 8431cb0ef41Sopenharmony_ci UNREACHABLE(); 8441cb0ef41Sopenharmony_ci } 8451cb0ef41Sopenharmony_ci} 8461cb0ef41Sopenharmony_ci 8471cb0ef41Sopenharmony_civoid LiftoffAssembler::AtomicFence() { mfence(); } 8481cb0ef41Sopenharmony_ci 8491cb0ef41Sopenharmony_civoid LiftoffAssembler::LoadCallerFrameSlot(LiftoffRegister dst, 8501cb0ef41Sopenharmony_ci uint32_t caller_slot_idx, 8511cb0ef41Sopenharmony_ci ValueKind kind) { 8521cb0ef41Sopenharmony_ci Operand src(rbp, kSystemPointerSize * (caller_slot_idx + 1)); 8531cb0ef41Sopenharmony_ci liftoff::Load(this, dst, src, kind); 8541cb0ef41Sopenharmony_ci} 8551cb0ef41Sopenharmony_ci 8561cb0ef41Sopenharmony_civoid LiftoffAssembler::StoreCallerFrameSlot(LiftoffRegister src, 8571cb0ef41Sopenharmony_ci uint32_t caller_slot_idx, 8581cb0ef41Sopenharmony_ci ValueKind kind) { 8591cb0ef41Sopenharmony_ci Operand dst(rbp, kSystemPointerSize * (caller_slot_idx + 1)); 8601cb0ef41Sopenharmony_ci liftoff::Store(this, dst, src, kind); 8611cb0ef41Sopenharmony_ci} 8621cb0ef41Sopenharmony_ci 8631cb0ef41Sopenharmony_civoid LiftoffAssembler::LoadReturnStackSlot(LiftoffRegister reg, int offset, 8641cb0ef41Sopenharmony_ci ValueKind kind) { 8651cb0ef41Sopenharmony_ci Operand src(rsp, offset); 8661cb0ef41Sopenharmony_ci liftoff::Load(this, reg, src, kind); 8671cb0ef41Sopenharmony_ci} 8681cb0ef41Sopenharmony_ci 8691cb0ef41Sopenharmony_civoid LiftoffAssembler::MoveStackValue(uint32_t dst_offset, uint32_t src_offset, 8701cb0ef41Sopenharmony_ci ValueKind kind) { 8711cb0ef41Sopenharmony_ci DCHECK_NE(dst_offset, src_offset); 8721cb0ef41Sopenharmony_ci Operand dst = liftoff::GetStackSlot(dst_offset); 8731cb0ef41Sopenharmony_ci Operand src = liftoff::GetStackSlot(src_offset); 8741cb0ef41Sopenharmony_ci switch (SlotSizeForType(kind)) { 8751cb0ef41Sopenharmony_ci case 4: 8761cb0ef41Sopenharmony_ci movl(kScratchRegister, src); 8771cb0ef41Sopenharmony_ci movl(dst, kScratchRegister); 8781cb0ef41Sopenharmony_ci break; 8791cb0ef41Sopenharmony_ci case 8: 8801cb0ef41Sopenharmony_ci movq(kScratchRegister, src); 8811cb0ef41Sopenharmony_ci movq(dst, kScratchRegister); 8821cb0ef41Sopenharmony_ci break; 8831cb0ef41Sopenharmony_ci case 16: 8841cb0ef41Sopenharmony_ci Movdqu(kScratchDoubleReg, src); 8851cb0ef41Sopenharmony_ci Movdqu(dst, kScratchDoubleReg); 8861cb0ef41Sopenharmony_ci break; 8871cb0ef41Sopenharmony_ci default: 8881cb0ef41Sopenharmony_ci UNREACHABLE(); 8891cb0ef41Sopenharmony_ci } 8901cb0ef41Sopenharmony_ci} 8911cb0ef41Sopenharmony_ci 8921cb0ef41Sopenharmony_civoid LiftoffAssembler::Move(Register dst, Register src, ValueKind kind) { 8931cb0ef41Sopenharmony_ci DCHECK_NE(dst, src); 8941cb0ef41Sopenharmony_ci if (kind == kI32) { 8951cb0ef41Sopenharmony_ci movl(dst, src); 8961cb0ef41Sopenharmony_ci } else { 8971cb0ef41Sopenharmony_ci DCHECK(kI64 == kind || is_reference(kind)); 8981cb0ef41Sopenharmony_ci movq(dst, src); 8991cb0ef41Sopenharmony_ci } 9001cb0ef41Sopenharmony_ci} 9011cb0ef41Sopenharmony_ci 9021cb0ef41Sopenharmony_civoid LiftoffAssembler::Move(DoubleRegister dst, DoubleRegister src, 9031cb0ef41Sopenharmony_ci ValueKind kind) { 9041cb0ef41Sopenharmony_ci DCHECK_NE(dst, src); 9051cb0ef41Sopenharmony_ci if (kind == kF32) { 9061cb0ef41Sopenharmony_ci Movss(dst, src); 9071cb0ef41Sopenharmony_ci } else if (kind == kF64) { 9081cb0ef41Sopenharmony_ci Movsd(dst, src); 9091cb0ef41Sopenharmony_ci } else { 9101cb0ef41Sopenharmony_ci DCHECK_EQ(kS128, kind); 9111cb0ef41Sopenharmony_ci Movapd(dst, src); 9121cb0ef41Sopenharmony_ci } 9131cb0ef41Sopenharmony_ci} 9141cb0ef41Sopenharmony_ci 9151cb0ef41Sopenharmony_civoid LiftoffAssembler::Spill(int offset, LiftoffRegister reg, ValueKind kind) { 9161cb0ef41Sopenharmony_ci RecordUsedSpillOffset(offset); 9171cb0ef41Sopenharmony_ci Operand dst = liftoff::GetStackSlot(offset); 9181cb0ef41Sopenharmony_ci switch (kind) { 9191cb0ef41Sopenharmony_ci case kI32: 9201cb0ef41Sopenharmony_ci movl(dst, reg.gp()); 9211cb0ef41Sopenharmony_ci break; 9221cb0ef41Sopenharmony_ci case kI64: 9231cb0ef41Sopenharmony_ci case kOptRef: 9241cb0ef41Sopenharmony_ci case kRef: 9251cb0ef41Sopenharmony_ci case kRtt: 9261cb0ef41Sopenharmony_ci movq(dst, reg.gp()); 9271cb0ef41Sopenharmony_ci break; 9281cb0ef41Sopenharmony_ci case kF32: 9291cb0ef41Sopenharmony_ci Movss(dst, reg.fp()); 9301cb0ef41Sopenharmony_ci break; 9311cb0ef41Sopenharmony_ci case kF64: 9321cb0ef41Sopenharmony_ci Movsd(dst, reg.fp()); 9331cb0ef41Sopenharmony_ci break; 9341cb0ef41Sopenharmony_ci case kS128: 9351cb0ef41Sopenharmony_ci Movdqu(dst, reg.fp()); 9361cb0ef41Sopenharmony_ci break; 9371cb0ef41Sopenharmony_ci default: 9381cb0ef41Sopenharmony_ci UNREACHABLE(); 9391cb0ef41Sopenharmony_ci } 9401cb0ef41Sopenharmony_ci} 9411cb0ef41Sopenharmony_ci 9421cb0ef41Sopenharmony_civoid LiftoffAssembler::Spill(int offset, WasmValue value) { 9431cb0ef41Sopenharmony_ci RecordUsedSpillOffset(offset); 9441cb0ef41Sopenharmony_ci Operand dst = liftoff::GetStackSlot(offset); 9451cb0ef41Sopenharmony_ci switch (value.type().kind()) { 9461cb0ef41Sopenharmony_ci case kI32: 9471cb0ef41Sopenharmony_ci movl(dst, Immediate(value.to_i32())); 9481cb0ef41Sopenharmony_ci break; 9491cb0ef41Sopenharmony_ci case kI64: { 9501cb0ef41Sopenharmony_ci if (is_int32(value.to_i64())) { 9511cb0ef41Sopenharmony_ci // Sign extend low word. 9521cb0ef41Sopenharmony_ci movq(dst, Immediate(static_cast<int32_t>(value.to_i64()))); 9531cb0ef41Sopenharmony_ci } else if (is_uint32(value.to_i64())) { 9541cb0ef41Sopenharmony_ci // Zero extend low word. 9551cb0ef41Sopenharmony_ci movl(kScratchRegister, Immediate(static_cast<int32_t>(value.to_i64()))); 9561cb0ef41Sopenharmony_ci movq(dst, kScratchRegister); 9571cb0ef41Sopenharmony_ci } else { 9581cb0ef41Sopenharmony_ci movq(kScratchRegister, value.to_i64()); 9591cb0ef41Sopenharmony_ci movq(dst, kScratchRegister); 9601cb0ef41Sopenharmony_ci } 9611cb0ef41Sopenharmony_ci break; 9621cb0ef41Sopenharmony_ci } 9631cb0ef41Sopenharmony_ci default: 9641cb0ef41Sopenharmony_ci // We do not track f32 and f64 constants, hence they are unreachable. 9651cb0ef41Sopenharmony_ci UNREACHABLE(); 9661cb0ef41Sopenharmony_ci } 9671cb0ef41Sopenharmony_ci} 9681cb0ef41Sopenharmony_ci 9691cb0ef41Sopenharmony_civoid LiftoffAssembler::Fill(LiftoffRegister reg, int offset, ValueKind kind) { 9701cb0ef41Sopenharmony_ci liftoff::Load(this, reg, liftoff::GetStackSlot(offset), kind); 9711cb0ef41Sopenharmony_ci} 9721cb0ef41Sopenharmony_ci 9731cb0ef41Sopenharmony_civoid LiftoffAssembler::FillI64Half(Register, int offset, RegPairHalf) { 9741cb0ef41Sopenharmony_ci UNREACHABLE(); 9751cb0ef41Sopenharmony_ci} 9761cb0ef41Sopenharmony_ci 9771cb0ef41Sopenharmony_civoid LiftoffAssembler::FillStackSlotsWithZero(int start, int size) { 9781cb0ef41Sopenharmony_ci DCHECK_LT(0, size); 9791cb0ef41Sopenharmony_ci RecordUsedSpillOffset(start + size); 9801cb0ef41Sopenharmony_ci 9811cb0ef41Sopenharmony_ci if (size <= 3 * kStackSlotSize) { 9821cb0ef41Sopenharmony_ci // Special straight-line code for up to three slots 9831cb0ef41Sopenharmony_ci // (7-10 bytes per slot: REX C7 <1-4 bytes op> <4 bytes imm>), 9841cb0ef41Sopenharmony_ci // And a movd (6-9 byte) when size % 8 != 0; 9851cb0ef41Sopenharmony_ci uint32_t remainder = size; 9861cb0ef41Sopenharmony_ci for (; remainder >= kStackSlotSize; remainder -= kStackSlotSize) { 9871cb0ef41Sopenharmony_ci movq(liftoff::GetStackSlot(start + remainder), Immediate(0)); 9881cb0ef41Sopenharmony_ci } 9891cb0ef41Sopenharmony_ci DCHECK(remainder == 4 || remainder == 0); 9901cb0ef41Sopenharmony_ci if (remainder) { 9911cb0ef41Sopenharmony_ci movl(liftoff::GetStackSlot(start + remainder), Immediate(0)); 9921cb0ef41Sopenharmony_ci } 9931cb0ef41Sopenharmony_ci } else { 9941cb0ef41Sopenharmony_ci // General case for bigger counts. 9951cb0ef41Sopenharmony_ci // This sequence takes 19-22 bytes (3 for pushes, 4-7 for lea, 2 for xor, 5 9961cb0ef41Sopenharmony_ci // for mov, 2 for repstosl, 3 for pops). 9971cb0ef41Sopenharmony_ci pushq(rax); 9981cb0ef41Sopenharmony_ci pushq(rcx); 9991cb0ef41Sopenharmony_ci pushq(rdi); 10001cb0ef41Sopenharmony_ci leaq(rdi, liftoff::GetStackSlot(start + size)); 10011cb0ef41Sopenharmony_ci xorl(rax, rax); 10021cb0ef41Sopenharmony_ci // Convert size (bytes) to doublewords (4-bytes). 10031cb0ef41Sopenharmony_ci movl(rcx, Immediate(size / 4)); 10041cb0ef41Sopenharmony_ci repstosl(); 10051cb0ef41Sopenharmony_ci popq(rdi); 10061cb0ef41Sopenharmony_ci popq(rcx); 10071cb0ef41Sopenharmony_ci popq(rax); 10081cb0ef41Sopenharmony_ci } 10091cb0ef41Sopenharmony_ci} 10101cb0ef41Sopenharmony_ci 10111cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32_add(Register dst, Register lhs, Register rhs) { 10121cb0ef41Sopenharmony_ci if (lhs != dst) { 10131cb0ef41Sopenharmony_ci leal(dst, Operand(lhs, rhs, times_1, 0)); 10141cb0ef41Sopenharmony_ci } else { 10151cb0ef41Sopenharmony_ci addl(dst, rhs); 10161cb0ef41Sopenharmony_ci } 10171cb0ef41Sopenharmony_ci} 10181cb0ef41Sopenharmony_ci 10191cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32_addi(Register dst, Register lhs, int32_t imm) { 10201cb0ef41Sopenharmony_ci if (lhs != dst) { 10211cb0ef41Sopenharmony_ci leal(dst, Operand(lhs, imm)); 10221cb0ef41Sopenharmony_ci } else { 10231cb0ef41Sopenharmony_ci addl(dst, Immediate(imm)); 10241cb0ef41Sopenharmony_ci } 10251cb0ef41Sopenharmony_ci} 10261cb0ef41Sopenharmony_ci 10271cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32_sub(Register dst, Register lhs, Register rhs) { 10281cb0ef41Sopenharmony_ci if (dst != rhs) { 10291cb0ef41Sopenharmony_ci // Default path. 10301cb0ef41Sopenharmony_ci if (dst != lhs) movl(dst, lhs); 10311cb0ef41Sopenharmony_ci subl(dst, rhs); 10321cb0ef41Sopenharmony_ci } else if (lhs == rhs) { 10331cb0ef41Sopenharmony_ci // Degenerate case. 10341cb0ef41Sopenharmony_ci xorl(dst, dst); 10351cb0ef41Sopenharmony_ci } else { 10361cb0ef41Sopenharmony_ci // Emit {dst = lhs + -rhs} if dst == rhs. 10371cb0ef41Sopenharmony_ci negl(dst); 10381cb0ef41Sopenharmony_ci addl(dst, lhs); 10391cb0ef41Sopenharmony_ci } 10401cb0ef41Sopenharmony_ci} 10411cb0ef41Sopenharmony_ci 10421cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32_subi(Register dst, Register lhs, int32_t imm) { 10431cb0ef41Sopenharmony_ci if (dst != lhs) { 10441cb0ef41Sopenharmony_ci // We'll have to implement an UB-safe version if we need this corner case. 10451cb0ef41Sopenharmony_ci DCHECK_NE(imm, kMinInt); 10461cb0ef41Sopenharmony_ci leal(dst, Operand(lhs, -imm)); 10471cb0ef41Sopenharmony_ci } else { 10481cb0ef41Sopenharmony_ci subl(dst, Immediate(imm)); 10491cb0ef41Sopenharmony_ci } 10501cb0ef41Sopenharmony_ci} 10511cb0ef41Sopenharmony_ci 10521cb0ef41Sopenharmony_cinamespace liftoff { 10531cb0ef41Sopenharmony_citemplate <void (Assembler::*op)(Register, Register), 10541cb0ef41Sopenharmony_ci void (Assembler::*mov)(Register, Register)> 10551cb0ef41Sopenharmony_civoid EmitCommutativeBinOp(LiftoffAssembler* assm, Register dst, Register lhs, 10561cb0ef41Sopenharmony_ci Register rhs) { 10571cb0ef41Sopenharmony_ci if (dst == rhs) { 10581cb0ef41Sopenharmony_ci (assm->*op)(dst, lhs); 10591cb0ef41Sopenharmony_ci } else { 10601cb0ef41Sopenharmony_ci if (dst != lhs) (assm->*mov)(dst, lhs); 10611cb0ef41Sopenharmony_ci (assm->*op)(dst, rhs); 10621cb0ef41Sopenharmony_ci } 10631cb0ef41Sopenharmony_ci} 10641cb0ef41Sopenharmony_ci 10651cb0ef41Sopenharmony_citemplate <void (Assembler::*op)(Register, Immediate), 10661cb0ef41Sopenharmony_ci void (Assembler::*mov)(Register, Register)> 10671cb0ef41Sopenharmony_civoid EmitCommutativeBinOpImm(LiftoffAssembler* assm, Register dst, Register lhs, 10681cb0ef41Sopenharmony_ci int32_t imm) { 10691cb0ef41Sopenharmony_ci if (dst != lhs) (assm->*mov)(dst, lhs); 10701cb0ef41Sopenharmony_ci (assm->*op)(dst, Immediate(imm)); 10711cb0ef41Sopenharmony_ci} 10721cb0ef41Sopenharmony_ci 10731cb0ef41Sopenharmony_ci} // namespace liftoff 10741cb0ef41Sopenharmony_ci 10751cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32_mul(Register dst, Register lhs, Register rhs) { 10761cb0ef41Sopenharmony_ci liftoff::EmitCommutativeBinOp<&Assembler::imull, &Assembler::movl>(this, dst, 10771cb0ef41Sopenharmony_ci lhs, rhs); 10781cb0ef41Sopenharmony_ci} 10791cb0ef41Sopenharmony_ci 10801cb0ef41Sopenharmony_cinamespace liftoff { 10811cb0ef41Sopenharmony_cienum class DivOrRem : uint8_t { kDiv, kRem }; 10821cb0ef41Sopenharmony_citemplate <typename type, DivOrRem div_or_rem> 10831cb0ef41Sopenharmony_civoid EmitIntDivOrRem(LiftoffAssembler* assm, Register dst, Register lhs, 10841cb0ef41Sopenharmony_ci Register rhs, Label* trap_div_by_zero, 10851cb0ef41Sopenharmony_ci Label* trap_div_unrepresentable) { 10861cb0ef41Sopenharmony_ci constexpr bool needs_unrepresentable_check = 10871cb0ef41Sopenharmony_ci std::is_signed<type>::value && div_or_rem == DivOrRem::kDiv; 10881cb0ef41Sopenharmony_ci constexpr bool special_case_minus_1 = 10891cb0ef41Sopenharmony_ci std::is_signed<type>::value && div_or_rem == DivOrRem::kRem; 10901cb0ef41Sopenharmony_ci DCHECK_EQ(needs_unrepresentable_check, trap_div_unrepresentable != nullptr); 10911cb0ef41Sopenharmony_ci 10921cb0ef41Sopenharmony_ci#define iop(name, ...) \ 10931cb0ef41Sopenharmony_ci do { \ 10941cb0ef41Sopenharmony_ci if (sizeof(type) == 4) { \ 10951cb0ef41Sopenharmony_ci assm->name##l(__VA_ARGS__); \ 10961cb0ef41Sopenharmony_ci } else { \ 10971cb0ef41Sopenharmony_ci assm->name##q(__VA_ARGS__); \ 10981cb0ef41Sopenharmony_ci } \ 10991cb0ef41Sopenharmony_ci } while (false) 11001cb0ef41Sopenharmony_ci 11011cb0ef41Sopenharmony_ci // For division, the lhs is always taken from {edx:eax}. Thus, make sure that 11021cb0ef41Sopenharmony_ci // these registers are unused. If {rhs} is stored in one of them, move it to 11031cb0ef41Sopenharmony_ci // another temporary register. 11041cb0ef41Sopenharmony_ci // Do all this before any branch, such that the code is executed 11051cb0ef41Sopenharmony_ci // unconditionally, as the cache state will also be modified unconditionally. 11061cb0ef41Sopenharmony_ci assm->SpillRegisters(rdx, rax); 11071cb0ef41Sopenharmony_ci if (rhs == rax || rhs == rdx) { 11081cb0ef41Sopenharmony_ci iop(mov, kScratchRegister, rhs); 11091cb0ef41Sopenharmony_ci rhs = kScratchRegister; 11101cb0ef41Sopenharmony_ci } 11111cb0ef41Sopenharmony_ci 11121cb0ef41Sopenharmony_ci // Check for division by zero. 11131cb0ef41Sopenharmony_ci iop(test, rhs, rhs); 11141cb0ef41Sopenharmony_ci assm->j(zero, trap_div_by_zero); 11151cb0ef41Sopenharmony_ci 11161cb0ef41Sopenharmony_ci Label done; 11171cb0ef41Sopenharmony_ci if (needs_unrepresentable_check) { 11181cb0ef41Sopenharmony_ci // Check for {kMinInt / -1}. This is unrepresentable. 11191cb0ef41Sopenharmony_ci Label do_div; 11201cb0ef41Sopenharmony_ci iop(cmp, rhs, Immediate(-1)); 11211cb0ef41Sopenharmony_ci assm->j(not_equal, &do_div); 11221cb0ef41Sopenharmony_ci // {lhs} is min int if {lhs - 1} overflows. 11231cb0ef41Sopenharmony_ci iop(cmp, lhs, Immediate(1)); 11241cb0ef41Sopenharmony_ci assm->j(overflow, trap_div_unrepresentable); 11251cb0ef41Sopenharmony_ci assm->bind(&do_div); 11261cb0ef41Sopenharmony_ci } else if (special_case_minus_1) { 11271cb0ef41Sopenharmony_ci // {lhs % -1} is always 0 (needs to be special cased because {kMinInt / -1} 11281cb0ef41Sopenharmony_ci // cannot be computed). 11291cb0ef41Sopenharmony_ci Label do_rem; 11301cb0ef41Sopenharmony_ci iop(cmp, rhs, Immediate(-1)); 11311cb0ef41Sopenharmony_ci assm->j(not_equal, &do_rem); 11321cb0ef41Sopenharmony_ci // clang-format off 11331cb0ef41Sopenharmony_ci // (conflicts with presubmit checks because it is confused about "xor") 11341cb0ef41Sopenharmony_ci iop(xor, dst, dst); 11351cb0ef41Sopenharmony_ci // clang-format on 11361cb0ef41Sopenharmony_ci assm->jmp(&done); 11371cb0ef41Sopenharmony_ci assm->bind(&do_rem); 11381cb0ef41Sopenharmony_ci } 11391cb0ef41Sopenharmony_ci 11401cb0ef41Sopenharmony_ci // Now move {lhs} into {eax}, then zero-extend or sign-extend into {edx}, then 11411cb0ef41Sopenharmony_ci // do the division. 11421cb0ef41Sopenharmony_ci if (lhs != rax) iop(mov, rax, lhs); 11431cb0ef41Sopenharmony_ci if (std::is_same<int32_t, type>::value) { // i32 11441cb0ef41Sopenharmony_ci assm->cdq(); 11451cb0ef41Sopenharmony_ci assm->idivl(rhs); 11461cb0ef41Sopenharmony_ci } else if (std::is_same<uint32_t, type>::value) { // u32 11471cb0ef41Sopenharmony_ci assm->xorl(rdx, rdx); 11481cb0ef41Sopenharmony_ci assm->divl(rhs); 11491cb0ef41Sopenharmony_ci } else if (std::is_same<int64_t, type>::value) { // i64 11501cb0ef41Sopenharmony_ci assm->cqo(); 11511cb0ef41Sopenharmony_ci assm->idivq(rhs); 11521cb0ef41Sopenharmony_ci } else { // u64 11531cb0ef41Sopenharmony_ci assm->xorq(rdx, rdx); 11541cb0ef41Sopenharmony_ci assm->divq(rhs); 11551cb0ef41Sopenharmony_ci } 11561cb0ef41Sopenharmony_ci 11571cb0ef41Sopenharmony_ci // Move back the result (in {eax} or {edx}) into the {dst} register. 11581cb0ef41Sopenharmony_ci constexpr Register kResultReg = div_or_rem == DivOrRem::kDiv ? rax : rdx; 11591cb0ef41Sopenharmony_ci if (dst != kResultReg) { 11601cb0ef41Sopenharmony_ci iop(mov, dst, kResultReg); 11611cb0ef41Sopenharmony_ci } 11621cb0ef41Sopenharmony_ci if (special_case_minus_1) assm->bind(&done); 11631cb0ef41Sopenharmony_ci} 11641cb0ef41Sopenharmony_ci} // namespace liftoff 11651cb0ef41Sopenharmony_ci 11661cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32_divs(Register dst, Register lhs, Register rhs, 11671cb0ef41Sopenharmony_ci Label* trap_div_by_zero, 11681cb0ef41Sopenharmony_ci Label* trap_div_unrepresentable) { 11691cb0ef41Sopenharmony_ci liftoff::EmitIntDivOrRem<int32_t, liftoff::DivOrRem::kDiv>( 11701cb0ef41Sopenharmony_ci this, dst, lhs, rhs, trap_div_by_zero, trap_div_unrepresentable); 11711cb0ef41Sopenharmony_ci} 11721cb0ef41Sopenharmony_ci 11731cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32_divu(Register dst, Register lhs, Register rhs, 11741cb0ef41Sopenharmony_ci Label* trap_div_by_zero) { 11751cb0ef41Sopenharmony_ci liftoff::EmitIntDivOrRem<uint32_t, liftoff::DivOrRem::kDiv>( 11761cb0ef41Sopenharmony_ci this, dst, lhs, rhs, trap_div_by_zero, nullptr); 11771cb0ef41Sopenharmony_ci} 11781cb0ef41Sopenharmony_ci 11791cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32_rems(Register dst, Register lhs, Register rhs, 11801cb0ef41Sopenharmony_ci Label* trap_div_by_zero) { 11811cb0ef41Sopenharmony_ci liftoff::EmitIntDivOrRem<int32_t, liftoff::DivOrRem::kRem>( 11821cb0ef41Sopenharmony_ci this, dst, lhs, rhs, trap_div_by_zero, nullptr); 11831cb0ef41Sopenharmony_ci} 11841cb0ef41Sopenharmony_ci 11851cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32_remu(Register dst, Register lhs, Register rhs, 11861cb0ef41Sopenharmony_ci Label* trap_div_by_zero) { 11871cb0ef41Sopenharmony_ci liftoff::EmitIntDivOrRem<uint32_t, liftoff::DivOrRem::kRem>( 11881cb0ef41Sopenharmony_ci this, dst, lhs, rhs, trap_div_by_zero, nullptr); 11891cb0ef41Sopenharmony_ci} 11901cb0ef41Sopenharmony_ci 11911cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32_and(Register dst, Register lhs, Register rhs) { 11921cb0ef41Sopenharmony_ci liftoff::EmitCommutativeBinOp<&Assembler::andl, &Assembler::movl>(this, dst, 11931cb0ef41Sopenharmony_ci lhs, rhs); 11941cb0ef41Sopenharmony_ci} 11951cb0ef41Sopenharmony_ci 11961cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32_andi(Register dst, Register lhs, int32_t imm) { 11971cb0ef41Sopenharmony_ci liftoff::EmitCommutativeBinOpImm<&Assembler::andl, &Assembler::movl>( 11981cb0ef41Sopenharmony_ci this, dst, lhs, imm); 11991cb0ef41Sopenharmony_ci} 12001cb0ef41Sopenharmony_ci 12011cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32_or(Register dst, Register lhs, Register rhs) { 12021cb0ef41Sopenharmony_ci liftoff::EmitCommutativeBinOp<&Assembler::orl, &Assembler::movl>(this, dst, 12031cb0ef41Sopenharmony_ci lhs, rhs); 12041cb0ef41Sopenharmony_ci} 12051cb0ef41Sopenharmony_ci 12061cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32_ori(Register dst, Register lhs, int32_t imm) { 12071cb0ef41Sopenharmony_ci liftoff::EmitCommutativeBinOpImm<&Assembler::orl, &Assembler::movl>(this, dst, 12081cb0ef41Sopenharmony_ci lhs, imm); 12091cb0ef41Sopenharmony_ci} 12101cb0ef41Sopenharmony_ci 12111cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32_xor(Register dst, Register lhs, Register rhs) { 12121cb0ef41Sopenharmony_ci liftoff::EmitCommutativeBinOp<&Assembler::xorl, &Assembler::movl>(this, dst, 12131cb0ef41Sopenharmony_ci lhs, rhs); 12141cb0ef41Sopenharmony_ci} 12151cb0ef41Sopenharmony_ci 12161cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32_xori(Register dst, Register lhs, int32_t imm) { 12171cb0ef41Sopenharmony_ci liftoff::EmitCommutativeBinOpImm<&Assembler::xorl, &Assembler::movl>( 12181cb0ef41Sopenharmony_ci this, dst, lhs, imm); 12191cb0ef41Sopenharmony_ci} 12201cb0ef41Sopenharmony_ci 12211cb0ef41Sopenharmony_cinamespace liftoff { 12221cb0ef41Sopenharmony_citemplate <ValueKind kind> 12231cb0ef41Sopenharmony_ciinline void EmitShiftOperation(LiftoffAssembler* assm, Register dst, 12241cb0ef41Sopenharmony_ci Register src, Register amount, 12251cb0ef41Sopenharmony_ci void (Assembler::*emit_shift)(Register)) { 12261cb0ef41Sopenharmony_ci // If dst is rcx, compute into the scratch register first, then move to rcx. 12271cb0ef41Sopenharmony_ci if (dst == rcx) { 12281cb0ef41Sopenharmony_ci assm->Move(kScratchRegister, src, kind); 12291cb0ef41Sopenharmony_ci if (amount != rcx) assm->Move(rcx, amount, kind); 12301cb0ef41Sopenharmony_ci (assm->*emit_shift)(kScratchRegister); 12311cb0ef41Sopenharmony_ci assm->Move(rcx, kScratchRegister, kind); 12321cb0ef41Sopenharmony_ci return; 12331cb0ef41Sopenharmony_ci } 12341cb0ef41Sopenharmony_ci 12351cb0ef41Sopenharmony_ci // Move amount into rcx. If rcx is in use, move its content into the scratch 12361cb0ef41Sopenharmony_ci // register. If src is rcx, src is now the scratch register. 12371cb0ef41Sopenharmony_ci bool use_scratch = false; 12381cb0ef41Sopenharmony_ci if (amount != rcx) { 12391cb0ef41Sopenharmony_ci use_scratch = 12401cb0ef41Sopenharmony_ci src == rcx || assm->cache_state()->is_used(LiftoffRegister(rcx)); 12411cb0ef41Sopenharmony_ci if (use_scratch) assm->movq(kScratchRegister, rcx); 12421cb0ef41Sopenharmony_ci if (src == rcx) src = kScratchRegister; 12431cb0ef41Sopenharmony_ci assm->Move(rcx, amount, kind); 12441cb0ef41Sopenharmony_ci } 12451cb0ef41Sopenharmony_ci 12461cb0ef41Sopenharmony_ci // Do the actual shift. 12471cb0ef41Sopenharmony_ci if (dst != src) assm->Move(dst, src, kind); 12481cb0ef41Sopenharmony_ci (assm->*emit_shift)(dst); 12491cb0ef41Sopenharmony_ci 12501cb0ef41Sopenharmony_ci // Restore rcx if needed. 12511cb0ef41Sopenharmony_ci if (use_scratch) assm->movq(rcx, kScratchRegister); 12521cb0ef41Sopenharmony_ci} 12531cb0ef41Sopenharmony_ci} // namespace liftoff 12541cb0ef41Sopenharmony_ci 12551cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32_shl(Register dst, Register src, 12561cb0ef41Sopenharmony_ci Register amount) { 12571cb0ef41Sopenharmony_ci liftoff::EmitShiftOperation<kI32>(this, dst, src, amount, 12581cb0ef41Sopenharmony_ci &Assembler::shll_cl); 12591cb0ef41Sopenharmony_ci} 12601cb0ef41Sopenharmony_ci 12611cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32_shli(Register dst, Register src, 12621cb0ef41Sopenharmony_ci int32_t amount) { 12631cb0ef41Sopenharmony_ci if (dst != src) movl(dst, src); 12641cb0ef41Sopenharmony_ci shll(dst, Immediate(amount & 31)); 12651cb0ef41Sopenharmony_ci} 12661cb0ef41Sopenharmony_ci 12671cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32_sar(Register dst, Register src, 12681cb0ef41Sopenharmony_ci Register amount) { 12691cb0ef41Sopenharmony_ci liftoff::EmitShiftOperation<kI32>(this, dst, src, amount, 12701cb0ef41Sopenharmony_ci &Assembler::sarl_cl); 12711cb0ef41Sopenharmony_ci} 12721cb0ef41Sopenharmony_ci 12731cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32_sari(Register dst, Register src, 12741cb0ef41Sopenharmony_ci int32_t amount) { 12751cb0ef41Sopenharmony_ci if (dst != src) movl(dst, src); 12761cb0ef41Sopenharmony_ci sarl(dst, Immediate(amount & 31)); 12771cb0ef41Sopenharmony_ci} 12781cb0ef41Sopenharmony_ci 12791cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32_shr(Register dst, Register src, 12801cb0ef41Sopenharmony_ci Register amount) { 12811cb0ef41Sopenharmony_ci liftoff::EmitShiftOperation<kI32>(this, dst, src, amount, 12821cb0ef41Sopenharmony_ci &Assembler::shrl_cl); 12831cb0ef41Sopenharmony_ci} 12841cb0ef41Sopenharmony_ci 12851cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32_shri(Register dst, Register src, 12861cb0ef41Sopenharmony_ci int32_t amount) { 12871cb0ef41Sopenharmony_ci if (dst != src) movl(dst, src); 12881cb0ef41Sopenharmony_ci shrl(dst, Immediate(amount & 31)); 12891cb0ef41Sopenharmony_ci} 12901cb0ef41Sopenharmony_ci 12911cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32_clz(Register dst, Register src) { 12921cb0ef41Sopenharmony_ci Lzcntl(dst, src); 12931cb0ef41Sopenharmony_ci} 12941cb0ef41Sopenharmony_ci 12951cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32_ctz(Register dst, Register src) { 12961cb0ef41Sopenharmony_ci Tzcntl(dst, src); 12971cb0ef41Sopenharmony_ci} 12981cb0ef41Sopenharmony_ci 12991cb0ef41Sopenharmony_cibool LiftoffAssembler::emit_i32_popcnt(Register dst, Register src) { 13001cb0ef41Sopenharmony_ci if (!CpuFeatures::IsSupported(POPCNT)) return false; 13011cb0ef41Sopenharmony_ci CpuFeatureScope scope(this, POPCNT); 13021cb0ef41Sopenharmony_ci popcntl(dst, src); 13031cb0ef41Sopenharmony_ci return true; 13041cb0ef41Sopenharmony_ci} 13051cb0ef41Sopenharmony_ci 13061cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i64_add(LiftoffRegister dst, LiftoffRegister lhs, 13071cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 13081cb0ef41Sopenharmony_ci if (lhs.gp() != dst.gp()) { 13091cb0ef41Sopenharmony_ci leaq(dst.gp(), Operand(lhs.gp(), rhs.gp(), times_1, 0)); 13101cb0ef41Sopenharmony_ci } else { 13111cb0ef41Sopenharmony_ci addq(dst.gp(), rhs.gp()); 13121cb0ef41Sopenharmony_ci } 13131cb0ef41Sopenharmony_ci} 13141cb0ef41Sopenharmony_ci 13151cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i64_addi(LiftoffRegister dst, LiftoffRegister lhs, 13161cb0ef41Sopenharmony_ci int64_t imm) { 13171cb0ef41Sopenharmony_ci if (!is_int32(imm)) { 13181cb0ef41Sopenharmony_ci TurboAssembler::Move(kScratchRegister, imm); 13191cb0ef41Sopenharmony_ci if (lhs.gp() == dst.gp()) { 13201cb0ef41Sopenharmony_ci addq(dst.gp(), kScratchRegister); 13211cb0ef41Sopenharmony_ci } else { 13221cb0ef41Sopenharmony_ci leaq(dst.gp(), Operand(lhs.gp(), kScratchRegister, times_1, 0)); 13231cb0ef41Sopenharmony_ci } 13241cb0ef41Sopenharmony_ci } else if (lhs.gp() == dst.gp()) { 13251cb0ef41Sopenharmony_ci addq(dst.gp(), Immediate(static_cast<int32_t>(imm))); 13261cb0ef41Sopenharmony_ci } else { 13271cb0ef41Sopenharmony_ci leaq(dst.gp(), Operand(lhs.gp(), static_cast<int32_t>(imm))); 13281cb0ef41Sopenharmony_ci } 13291cb0ef41Sopenharmony_ci} 13301cb0ef41Sopenharmony_ci 13311cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i64_sub(LiftoffRegister dst, LiftoffRegister lhs, 13321cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 13331cb0ef41Sopenharmony_ci if (lhs.gp() == rhs.gp()) { 13341cb0ef41Sopenharmony_ci xorq(dst.gp(), dst.gp()); 13351cb0ef41Sopenharmony_ci } else if (dst.gp() == rhs.gp()) { 13361cb0ef41Sopenharmony_ci negq(dst.gp()); 13371cb0ef41Sopenharmony_ci addq(dst.gp(), lhs.gp()); 13381cb0ef41Sopenharmony_ci } else { 13391cb0ef41Sopenharmony_ci if (dst.gp() != lhs.gp()) movq(dst.gp(), lhs.gp()); 13401cb0ef41Sopenharmony_ci subq(dst.gp(), rhs.gp()); 13411cb0ef41Sopenharmony_ci } 13421cb0ef41Sopenharmony_ci} 13431cb0ef41Sopenharmony_ci 13441cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i64_mul(LiftoffRegister dst, LiftoffRegister lhs, 13451cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 13461cb0ef41Sopenharmony_ci liftoff::EmitCommutativeBinOp<&Assembler::imulq, &Assembler::movq>( 13471cb0ef41Sopenharmony_ci this, dst.gp(), lhs.gp(), rhs.gp()); 13481cb0ef41Sopenharmony_ci} 13491cb0ef41Sopenharmony_ci 13501cb0ef41Sopenharmony_cibool LiftoffAssembler::emit_i64_divs(LiftoffRegister dst, LiftoffRegister lhs, 13511cb0ef41Sopenharmony_ci LiftoffRegister rhs, 13521cb0ef41Sopenharmony_ci Label* trap_div_by_zero, 13531cb0ef41Sopenharmony_ci Label* trap_div_unrepresentable) { 13541cb0ef41Sopenharmony_ci liftoff::EmitIntDivOrRem<int64_t, liftoff::DivOrRem::kDiv>( 13551cb0ef41Sopenharmony_ci this, dst.gp(), lhs.gp(), rhs.gp(), trap_div_by_zero, 13561cb0ef41Sopenharmony_ci trap_div_unrepresentable); 13571cb0ef41Sopenharmony_ci return true; 13581cb0ef41Sopenharmony_ci} 13591cb0ef41Sopenharmony_ci 13601cb0ef41Sopenharmony_cibool LiftoffAssembler::emit_i64_divu(LiftoffRegister dst, LiftoffRegister lhs, 13611cb0ef41Sopenharmony_ci LiftoffRegister rhs, 13621cb0ef41Sopenharmony_ci Label* trap_div_by_zero) { 13631cb0ef41Sopenharmony_ci liftoff::EmitIntDivOrRem<uint64_t, liftoff::DivOrRem::kDiv>( 13641cb0ef41Sopenharmony_ci this, dst.gp(), lhs.gp(), rhs.gp(), trap_div_by_zero, nullptr); 13651cb0ef41Sopenharmony_ci return true; 13661cb0ef41Sopenharmony_ci} 13671cb0ef41Sopenharmony_ci 13681cb0ef41Sopenharmony_cibool LiftoffAssembler::emit_i64_rems(LiftoffRegister dst, LiftoffRegister lhs, 13691cb0ef41Sopenharmony_ci LiftoffRegister rhs, 13701cb0ef41Sopenharmony_ci Label* trap_div_by_zero) { 13711cb0ef41Sopenharmony_ci liftoff::EmitIntDivOrRem<int64_t, liftoff::DivOrRem::kRem>( 13721cb0ef41Sopenharmony_ci this, dst.gp(), lhs.gp(), rhs.gp(), trap_div_by_zero, nullptr); 13731cb0ef41Sopenharmony_ci return true; 13741cb0ef41Sopenharmony_ci} 13751cb0ef41Sopenharmony_ci 13761cb0ef41Sopenharmony_cibool LiftoffAssembler::emit_i64_remu(LiftoffRegister dst, LiftoffRegister lhs, 13771cb0ef41Sopenharmony_ci LiftoffRegister rhs, 13781cb0ef41Sopenharmony_ci Label* trap_div_by_zero) { 13791cb0ef41Sopenharmony_ci liftoff::EmitIntDivOrRem<uint64_t, liftoff::DivOrRem::kRem>( 13801cb0ef41Sopenharmony_ci this, dst.gp(), lhs.gp(), rhs.gp(), trap_div_by_zero, nullptr); 13811cb0ef41Sopenharmony_ci return true; 13821cb0ef41Sopenharmony_ci} 13831cb0ef41Sopenharmony_ci 13841cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i64_and(LiftoffRegister dst, LiftoffRegister lhs, 13851cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 13861cb0ef41Sopenharmony_ci liftoff::EmitCommutativeBinOp<&Assembler::andq, &Assembler::movq>( 13871cb0ef41Sopenharmony_ci this, dst.gp(), lhs.gp(), rhs.gp()); 13881cb0ef41Sopenharmony_ci} 13891cb0ef41Sopenharmony_ci 13901cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i64_andi(LiftoffRegister dst, LiftoffRegister lhs, 13911cb0ef41Sopenharmony_ci int32_t imm) { 13921cb0ef41Sopenharmony_ci liftoff::EmitCommutativeBinOpImm<&Assembler::andq, &Assembler::movq>( 13931cb0ef41Sopenharmony_ci this, dst.gp(), lhs.gp(), imm); 13941cb0ef41Sopenharmony_ci} 13951cb0ef41Sopenharmony_ci 13961cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i64_or(LiftoffRegister dst, LiftoffRegister lhs, 13971cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 13981cb0ef41Sopenharmony_ci liftoff::EmitCommutativeBinOp<&Assembler::orq, &Assembler::movq>( 13991cb0ef41Sopenharmony_ci this, dst.gp(), lhs.gp(), rhs.gp()); 14001cb0ef41Sopenharmony_ci} 14011cb0ef41Sopenharmony_ci 14021cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i64_ori(LiftoffRegister dst, LiftoffRegister lhs, 14031cb0ef41Sopenharmony_ci int32_t imm) { 14041cb0ef41Sopenharmony_ci liftoff::EmitCommutativeBinOpImm<&Assembler::orq, &Assembler::movq>( 14051cb0ef41Sopenharmony_ci this, dst.gp(), lhs.gp(), imm); 14061cb0ef41Sopenharmony_ci} 14071cb0ef41Sopenharmony_ci 14081cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i64_xor(LiftoffRegister dst, LiftoffRegister lhs, 14091cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 14101cb0ef41Sopenharmony_ci liftoff::EmitCommutativeBinOp<&Assembler::xorq, &Assembler::movq>( 14111cb0ef41Sopenharmony_ci this, dst.gp(), lhs.gp(), rhs.gp()); 14121cb0ef41Sopenharmony_ci} 14131cb0ef41Sopenharmony_ci 14141cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i64_xori(LiftoffRegister dst, LiftoffRegister lhs, 14151cb0ef41Sopenharmony_ci int32_t imm) { 14161cb0ef41Sopenharmony_ci liftoff::EmitCommutativeBinOpImm<&Assembler::xorq, &Assembler::movq>( 14171cb0ef41Sopenharmony_ci this, dst.gp(), lhs.gp(), imm); 14181cb0ef41Sopenharmony_ci} 14191cb0ef41Sopenharmony_ci 14201cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i64_shl(LiftoffRegister dst, LiftoffRegister src, 14211cb0ef41Sopenharmony_ci Register amount) { 14221cb0ef41Sopenharmony_ci liftoff::EmitShiftOperation<kI64>(this, dst.gp(), src.gp(), amount, 14231cb0ef41Sopenharmony_ci &Assembler::shlq_cl); 14241cb0ef41Sopenharmony_ci} 14251cb0ef41Sopenharmony_ci 14261cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i64_shli(LiftoffRegister dst, LiftoffRegister src, 14271cb0ef41Sopenharmony_ci int32_t amount) { 14281cb0ef41Sopenharmony_ci if (dst.gp() != src.gp()) movq(dst.gp(), src.gp()); 14291cb0ef41Sopenharmony_ci shlq(dst.gp(), Immediate(amount & 63)); 14301cb0ef41Sopenharmony_ci} 14311cb0ef41Sopenharmony_ci 14321cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i64_sar(LiftoffRegister dst, LiftoffRegister src, 14331cb0ef41Sopenharmony_ci Register amount) { 14341cb0ef41Sopenharmony_ci liftoff::EmitShiftOperation<kI64>(this, dst.gp(), src.gp(), amount, 14351cb0ef41Sopenharmony_ci &Assembler::sarq_cl); 14361cb0ef41Sopenharmony_ci} 14371cb0ef41Sopenharmony_ci 14381cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i64_sari(LiftoffRegister dst, LiftoffRegister src, 14391cb0ef41Sopenharmony_ci int32_t amount) { 14401cb0ef41Sopenharmony_ci if (dst.gp() != src.gp()) movq(dst.gp(), src.gp()); 14411cb0ef41Sopenharmony_ci sarq(dst.gp(), Immediate(amount & 63)); 14421cb0ef41Sopenharmony_ci} 14431cb0ef41Sopenharmony_ci 14441cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i64_shr(LiftoffRegister dst, LiftoffRegister src, 14451cb0ef41Sopenharmony_ci Register amount) { 14461cb0ef41Sopenharmony_ci liftoff::EmitShiftOperation<kI64>(this, dst.gp(), src.gp(), amount, 14471cb0ef41Sopenharmony_ci &Assembler::shrq_cl); 14481cb0ef41Sopenharmony_ci} 14491cb0ef41Sopenharmony_ci 14501cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i64_shri(LiftoffRegister dst, LiftoffRegister src, 14511cb0ef41Sopenharmony_ci int32_t amount) { 14521cb0ef41Sopenharmony_ci if (dst != src) movq(dst.gp(), src.gp()); 14531cb0ef41Sopenharmony_ci shrq(dst.gp(), Immediate(amount & 63)); 14541cb0ef41Sopenharmony_ci} 14551cb0ef41Sopenharmony_ci 14561cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i64_clz(LiftoffRegister dst, LiftoffRegister src) { 14571cb0ef41Sopenharmony_ci Lzcntq(dst.gp(), src.gp()); 14581cb0ef41Sopenharmony_ci} 14591cb0ef41Sopenharmony_ci 14601cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i64_ctz(LiftoffRegister dst, LiftoffRegister src) { 14611cb0ef41Sopenharmony_ci Tzcntq(dst.gp(), src.gp()); 14621cb0ef41Sopenharmony_ci} 14631cb0ef41Sopenharmony_ci 14641cb0ef41Sopenharmony_cibool LiftoffAssembler::emit_i64_popcnt(LiftoffRegister dst, 14651cb0ef41Sopenharmony_ci LiftoffRegister src) { 14661cb0ef41Sopenharmony_ci if (!CpuFeatures::IsSupported(POPCNT)) return false; 14671cb0ef41Sopenharmony_ci CpuFeatureScope scope(this, POPCNT); 14681cb0ef41Sopenharmony_ci popcntq(dst.gp(), src.gp()); 14691cb0ef41Sopenharmony_ci return true; 14701cb0ef41Sopenharmony_ci} 14711cb0ef41Sopenharmony_ci 14721cb0ef41Sopenharmony_civoid LiftoffAssembler::IncrementSmi(LiftoffRegister dst, int offset) { 14731cb0ef41Sopenharmony_ci SmiAddConstant(Operand(dst.gp(), offset), Smi::FromInt(1)); 14741cb0ef41Sopenharmony_ci} 14751cb0ef41Sopenharmony_ci 14761cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_u32_to_uintptr(Register dst, Register src) { 14771cb0ef41Sopenharmony_ci movl(dst, src); 14781cb0ef41Sopenharmony_ci} 14791cb0ef41Sopenharmony_ci 14801cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_f32_add(DoubleRegister dst, DoubleRegister lhs, 14811cb0ef41Sopenharmony_ci DoubleRegister rhs) { 14821cb0ef41Sopenharmony_ci if (CpuFeatures::IsSupported(AVX)) { 14831cb0ef41Sopenharmony_ci CpuFeatureScope scope(this, AVX); 14841cb0ef41Sopenharmony_ci vaddss(dst, lhs, rhs); 14851cb0ef41Sopenharmony_ci } else if (dst == rhs) { 14861cb0ef41Sopenharmony_ci addss(dst, lhs); 14871cb0ef41Sopenharmony_ci } else { 14881cb0ef41Sopenharmony_ci if (dst != lhs) movss(dst, lhs); 14891cb0ef41Sopenharmony_ci addss(dst, rhs); 14901cb0ef41Sopenharmony_ci } 14911cb0ef41Sopenharmony_ci} 14921cb0ef41Sopenharmony_ci 14931cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_f32_sub(DoubleRegister dst, DoubleRegister lhs, 14941cb0ef41Sopenharmony_ci DoubleRegister rhs) { 14951cb0ef41Sopenharmony_ci if (CpuFeatures::IsSupported(AVX)) { 14961cb0ef41Sopenharmony_ci CpuFeatureScope scope(this, AVX); 14971cb0ef41Sopenharmony_ci vsubss(dst, lhs, rhs); 14981cb0ef41Sopenharmony_ci } else if (dst == rhs) { 14991cb0ef41Sopenharmony_ci movss(kScratchDoubleReg, rhs); 15001cb0ef41Sopenharmony_ci movss(dst, lhs); 15011cb0ef41Sopenharmony_ci subss(dst, kScratchDoubleReg); 15021cb0ef41Sopenharmony_ci } else { 15031cb0ef41Sopenharmony_ci if (dst != lhs) movss(dst, lhs); 15041cb0ef41Sopenharmony_ci subss(dst, rhs); 15051cb0ef41Sopenharmony_ci } 15061cb0ef41Sopenharmony_ci} 15071cb0ef41Sopenharmony_ci 15081cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_f32_mul(DoubleRegister dst, DoubleRegister lhs, 15091cb0ef41Sopenharmony_ci DoubleRegister rhs) { 15101cb0ef41Sopenharmony_ci if (CpuFeatures::IsSupported(AVX)) { 15111cb0ef41Sopenharmony_ci CpuFeatureScope scope(this, AVX); 15121cb0ef41Sopenharmony_ci vmulss(dst, lhs, rhs); 15131cb0ef41Sopenharmony_ci } else if (dst == rhs) { 15141cb0ef41Sopenharmony_ci mulss(dst, lhs); 15151cb0ef41Sopenharmony_ci } else { 15161cb0ef41Sopenharmony_ci if (dst != lhs) movss(dst, lhs); 15171cb0ef41Sopenharmony_ci mulss(dst, rhs); 15181cb0ef41Sopenharmony_ci } 15191cb0ef41Sopenharmony_ci} 15201cb0ef41Sopenharmony_ci 15211cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_f32_div(DoubleRegister dst, DoubleRegister lhs, 15221cb0ef41Sopenharmony_ci DoubleRegister rhs) { 15231cb0ef41Sopenharmony_ci if (CpuFeatures::IsSupported(AVX)) { 15241cb0ef41Sopenharmony_ci CpuFeatureScope scope(this, AVX); 15251cb0ef41Sopenharmony_ci vdivss(dst, lhs, rhs); 15261cb0ef41Sopenharmony_ci } else if (dst == rhs) { 15271cb0ef41Sopenharmony_ci movss(kScratchDoubleReg, rhs); 15281cb0ef41Sopenharmony_ci movss(dst, lhs); 15291cb0ef41Sopenharmony_ci divss(dst, kScratchDoubleReg); 15301cb0ef41Sopenharmony_ci } else { 15311cb0ef41Sopenharmony_ci if (dst != lhs) movss(dst, lhs); 15321cb0ef41Sopenharmony_ci divss(dst, rhs); 15331cb0ef41Sopenharmony_ci } 15341cb0ef41Sopenharmony_ci} 15351cb0ef41Sopenharmony_ci 15361cb0ef41Sopenharmony_cinamespace liftoff { 15371cb0ef41Sopenharmony_cienum class MinOrMax : uint8_t { kMin, kMax }; 15381cb0ef41Sopenharmony_citemplate <typename type> 15391cb0ef41Sopenharmony_ciinline void EmitFloatMinOrMax(LiftoffAssembler* assm, DoubleRegister dst, 15401cb0ef41Sopenharmony_ci DoubleRegister lhs, DoubleRegister rhs, 15411cb0ef41Sopenharmony_ci MinOrMax min_or_max) { 15421cb0ef41Sopenharmony_ci Label is_nan; 15431cb0ef41Sopenharmony_ci Label lhs_below_rhs; 15441cb0ef41Sopenharmony_ci Label lhs_above_rhs; 15451cb0ef41Sopenharmony_ci Label done; 15461cb0ef41Sopenharmony_ci 15471cb0ef41Sopenharmony_ci#define dop(name, ...) \ 15481cb0ef41Sopenharmony_ci do { \ 15491cb0ef41Sopenharmony_ci if (sizeof(type) == 4) { \ 15501cb0ef41Sopenharmony_ci assm->name##s(__VA_ARGS__); \ 15511cb0ef41Sopenharmony_ci } else { \ 15521cb0ef41Sopenharmony_ci assm->name##d(__VA_ARGS__); \ 15531cb0ef41Sopenharmony_ci } \ 15541cb0ef41Sopenharmony_ci } while (false) 15551cb0ef41Sopenharmony_ci 15561cb0ef41Sopenharmony_ci // Check the easy cases first: nan (e.g. unordered), smaller and greater. 15571cb0ef41Sopenharmony_ci // NaN has to be checked first, because PF=1 implies CF=1. 15581cb0ef41Sopenharmony_ci dop(Ucomis, lhs, rhs); 15591cb0ef41Sopenharmony_ci assm->j(parity_even, &is_nan, Label::kNear); // PF=1 15601cb0ef41Sopenharmony_ci assm->j(below, &lhs_below_rhs, Label::kNear); // CF=1 15611cb0ef41Sopenharmony_ci assm->j(above, &lhs_above_rhs, Label::kNear); // CF=0 && ZF=0 15621cb0ef41Sopenharmony_ci 15631cb0ef41Sopenharmony_ci // If we get here, then either 15641cb0ef41Sopenharmony_ci // a) {lhs == rhs}, 15651cb0ef41Sopenharmony_ci // b) {lhs == -0.0} and {rhs == 0.0}, or 15661cb0ef41Sopenharmony_ci // c) {lhs == 0.0} and {rhs == -0.0}. 15671cb0ef41Sopenharmony_ci // For a), it does not matter whether we return {lhs} or {rhs}. Check the sign 15681cb0ef41Sopenharmony_ci // bit of {rhs} to differentiate b) and c). 15691cb0ef41Sopenharmony_ci dop(Movmskp, kScratchRegister, rhs); 15701cb0ef41Sopenharmony_ci assm->testl(kScratchRegister, Immediate(1)); 15711cb0ef41Sopenharmony_ci assm->j(zero, &lhs_below_rhs, Label::kNear); 15721cb0ef41Sopenharmony_ci assm->jmp(&lhs_above_rhs, Label::kNear); 15731cb0ef41Sopenharmony_ci 15741cb0ef41Sopenharmony_ci assm->bind(&is_nan); 15751cb0ef41Sopenharmony_ci // Create a NaN output. 15761cb0ef41Sopenharmony_ci dop(Xorp, dst, dst); 15771cb0ef41Sopenharmony_ci dop(Divs, dst, dst); 15781cb0ef41Sopenharmony_ci assm->jmp(&done, Label::kNear); 15791cb0ef41Sopenharmony_ci 15801cb0ef41Sopenharmony_ci assm->bind(&lhs_below_rhs); 15811cb0ef41Sopenharmony_ci DoubleRegister lhs_below_rhs_src = min_or_max == MinOrMax::kMin ? lhs : rhs; 15821cb0ef41Sopenharmony_ci if (dst != lhs_below_rhs_src) dop(Movs, dst, lhs_below_rhs_src); 15831cb0ef41Sopenharmony_ci assm->jmp(&done, Label::kNear); 15841cb0ef41Sopenharmony_ci 15851cb0ef41Sopenharmony_ci assm->bind(&lhs_above_rhs); 15861cb0ef41Sopenharmony_ci DoubleRegister lhs_above_rhs_src = min_or_max == MinOrMax::kMin ? rhs : lhs; 15871cb0ef41Sopenharmony_ci if (dst != lhs_above_rhs_src) dop(Movs, dst, lhs_above_rhs_src); 15881cb0ef41Sopenharmony_ci 15891cb0ef41Sopenharmony_ci assm->bind(&done); 15901cb0ef41Sopenharmony_ci} 15911cb0ef41Sopenharmony_ci} // namespace liftoff 15921cb0ef41Sopenharmony_ci 15931cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_f32_min(DoubleRegister dst, DoubleRegister lhs, 15941cb0ef41Sopenharmony_ci DoubleRegister rhs) { 15951cb0ef41Sopenharmony_ci liftoff::EmitFloatMinOrMax<float>(this, dst, lhs, rhs, 15961cb0ef41Sopenharmony_ci liftoff::MinOrMax::kMin); 15971cb0ef41Sopenharmony_ci} 15981cb0ef41Sopenharmony_ci 15991cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_f32_max(DoubleRegister dst, DoubleRegister lhs, 16001cb0ef41Sopenharmony_ci DoubleRegister rhs) { 16011cb0ef41Sopenharmony_ci liftoff::EmitFloatMinOrMax<float>(this, dst, lhs, rhs, 16021cb0ef41Sopenharmony_ci liftoff::MinOrMax::kMax); 16031cb0ef41Sopenharmony_ci} 16041cb0ef41Sopenharmony_ci 16051cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_f32_copysign(DoubleRegister dst, DoubleRegister lhs, 16061cb0ef41Sopenharmony_ci DoubleRegister rhs) { 16071cb0ef41Sopenharmony_ci static constexpr int kF32SignBit = 1 << 31; 16081cb0ef41Sopenharmony_ci Movd(kScratchRegister, lhs); 16091cb0ef41Sopenharmony_ci andl(kScratchRegister, Immediate(~kF32SignBit)); 16101cb0ef41Sopenharmony_ci Movd(liftoff::kScratchRegister2, rhs); 16111cb0ef41Sopenharmony_ci andl(liftoff::kScratchRegister2, Immediate(kF32SignBit)); 16121cb0ef41Sopenharmony_ci orl(kScratchRegister, liftoff::kScratchRegister2); 16131cb0ef41Sopenharmony_ci Movd(dst, kScratchRegister); 16141cb0ef41Sopenharmony_ci} 16151cb0ef41Sopenharmony_ci 16161cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_f32_abs(DoubleRegister dst, DoubleRegister src) { 16171cb0ef41Sopenharmony_ci static constexpr uint32_t kSignBit = uint32_t{1} << 31; 16181cb0ef41Sopenharmony_ci if (dst == src) { 16191cb0ef41Sopenharmony_ci TurboAssembler::Move(kScratchDoubleReg, kSignBit - 1); 16201cb0ef41Sopenharmony_ci Andps(dst, kScratchDoubleReg); 16211cb0ef41Sopenharmony_ci } else { 16221cb0ef41Sopenharmony_ci TurboAssembler::Move(dst, kSignBit - 1); 16231cb0ef41Sopenharmony_ci Andps(dst, src); 16241cb0ef41Sopenharmony_ci } 16251cb0ef41Sopenharmony_ci} 16261cb0ef41Sopenharmony_ci 16271cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_f32_neg(DoubleRegister dst, DoubleRegister src) { 16281cb0ef41Sopenharmony_ci static constexpr uint32_t kSignBit = uint32_t{1} << 31; 16291cb0ef41Sopenharmony_ci if (dst == src) { 16301cb0ef41Sopenharmony_ci TurboAssembler::Move(kScratchDoubleReg, kSignBit); 16311cb0ef41Sopenharmony_ci Xorps(dst, kScratchDoubleReg); 16321cb0ef41Sopenharmony_ci } else { 16331cb0ef41Sopenharmony_ci TurboAssembler::Move(dst, kSignBit); 16341cb0ef41Sopenharmony_ci Xorps(dst, src); 16351cb0ef41Sopenharmony_ci } 16361cb0ef41Sopenharmony_ci} 16371cb0ef41Sopenharmony_ci 16381cb0ef41Sopenharmony_cibool LiftoffAssembler::emit_f32_ceil(DoubleRegister dst, DoubleRegister src) { 16391cb0ef41Sopenharmony_ci RETURN_FALSE_IF_MISSING_CPU_FEATURE(SSE4_1); 16401cb0ef41Sopenharmony_ci Roundss(dst, src, kRoundUp); 16411cb0ef41Sopenharmony_ci return true; 16421cb0ef41Sopenharmony_ci} 16431cb0ef41Sopenharmony_ci 16441cb0ef41Sopenharmony_cibool LiftoffAssembler::emit_f32_floor(DoubleRegister dst, DoubleRegister src) { 16451cb0ef41Sopenharmony_ci RETURN_FALSE_IF_MISSING_CPU_FEATURE(SSE4_1); 16461cb0ef41Sopenharmony_ci Roundss(dst, src, kRoundDown); 16471cb0ef41Sopenharmony_ci return true; 16481cb0ef41Sopenharmony_ci} 16491cb0ef41Sopenharmony_ci 16501cb0ef41Sopenharmony_cibool LiftoffAssembler::emit_f32_trunc(DoubleRegister dst, DoubleRegister src) { 16511cb0ef41Sopenharmony_ci RETURN_FALSE_IF_MISSING_CPU_FEATURE(SSE4_1); 16521cb0ef41Sopenharmony_ci Roundss(dst, src, kRoundToZero); 16531cb0ef41Sopenharmony_ci return true; 16541cb0ef41Sopenharmony_ci} 16551cb0ef41Sopenharmony_ci 16561cb0ef41Sopenharmony_cibool LiftoffAssembler::emit_f32_nearest_int(DoubleRegister dst, 16571cb0ef41Sopenharmony_ci DoubleRegister src) { 16581cb0ef41Sopenharmony_ci RETURN_FALSE_IF_MISSING_CPU_FEATURE(SSE4_1); 16591cb0ef41Sopenharmony_ci Roundss(dst, src, kRoundToNearest); 16601cb0ef41Sopenharmony_ci return true; 16611cb0ef41Sopenharmony_ci} 16621cb0ef41Sopenharmony_ci 16631cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_f32_sqrt(DoubleRegister dst, DoubleRegister src) { 16641cb0ef41Sopenharmony_ci Sqrtss(dst, src); 16651cb0ef41Sopenharmony_ci} 16661cb0ef41Sopenharmony_ci 16671cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_f64_add(DoubleRegister dst, DoubleRegister lhs, 16681cb0ef41Sopenharmony_ci DoubleRegister rhs) { 16691cb0ef41Sopenharmony_ci if (CpuFeatures::IsSupported(AVX)) { 16701cb0ef41Sopenharmony_ci CpuFeatureScope scope(this, AVX); 16711cb0ef41Sopenharmony_ci vaddsd(dst, lhs, rhs); 16721cb0ef41Sopenharmony_ci } else if (dst == rhs) { 16731cb0ef41Sopenharmony_ci addsd(dst, lhs); 16741cb0ef41Sopenharmony_ci } else { 16751cb0ef41Sopenharmony_ci if (dst != lhs) movsd(dst, lhs); 16761cb0ef41Sopenharmony_ci addsd(dst, rhs); 16771cb0ef41Sopenharmony_ci } 16781cb0ef41Sopenharmony_ci} 16791cb0ef41Sopenharmony_ci 16801cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_f64_sub(DoubleRegister dst, DoubleRegister lhs, 16811cb0ef41Sopenharmony_ci DoubleRegister rhs) { 16821cb0ef41Sopenharmony_ci if (CpuFeatures::IsSupported(AVX)) { 16831cb0ef41Sopenharmony_ci CpuFeatureScope scope(this, AVX); 16841cb0ef41Sopenharmony_ci vsubsd(dst, lhs, rhs); 16851cb0ef41Sopenharmony_ci } else if (dst == rhs) { 16861cb0ef41Sopenharmony_ci movsd(kScratchDoubleReg, rhs); 16871cb0ef41Sopenharmony_ci movsd(dst, lhs); 16881cb0ef41Sopenharmony_ci subsd(dst, kScratchDoubleReg); 16891cb0ef41Sopenharmony_ci } else { 16901cb0ef41Sopenharmony_ci if (dst != lhs) movsd(dst, lhs); 16911cb0ef41Sopenharmony_ci subsd(dst, rhs); 16921cb0ef41Sopenharmony_ci } 16931cb0ef41Sopenharmony_ci} 16941cb0ef41Sopenharmony_ci 16951cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_f64_mul(DoubleRegister dst, DoubleRegister lhs, 16961cb0ef41Sopenharmony_ci DoubleRegister rhs) { 16971cb0ef41Sopenharmony_ci if (CpuFeatures::IsSupported(AVX)) { 16981cb0ef41Sopenharmony_ci CpuFeatureScope scope(this, AVX); 16991cb0ef41Sopenharmony_ci vmulsd(dst, lhs, rhs); 17001cb0ef41Sopenharmony_ci } else if (dst == rhs) { 17011cb0ef41Sopenharmony_ci mulsd(dst, lhs); 17021cb0ef41Sopenharmony_ci } else { 17031cb0ef41Sopenharmony_ci if (dst != lhs) movsd(dst, lhs); 17041cb0ef41Sopenharmony_ci mulsd(dst, rhs); 17051cb0ef41Sopenharmony_ci } 17061cb0ef41Sopenharmony_ci} 17071cb0ef41Sopenharmony_ci 17081cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_f64_div(DoubleRegister dst, DoubleRegister lhs, 17091cb0ef41Sopenharmony_ci DoubleRegister rhs) { 17101cb0ef41Sopenharmony_ci if (CpuFeatures::IsSupported(AVX)) { 17111cb0ef41Sopenharmony_ci CpuFeatureScope scope(this, AVX); 17121cb0ef41Sopenharmony_ci vdivsd(dst, lhs, rhs); 17131cb0ef41Sopenharmony_ci } else if (dst == rhs) { 17141cb0ef41Sopenharmony_ci movsd(kScratchDoubleReg, rhs); 17151cb0ef41Sopenharmony_ci movsd(dst, lhs); 17161cb0ef41Sopenharmony_ci divsd(dst, kScratchDoubleReg); 17171cb0ef41Sopenharmony_ci } else { 17181cb0ef41Sopenharmony_ci if (dst != lhs) movsd(dst, lhs); 17191cb0ef41Sopenharmony_ci divsd(dst, rhs); 17201cb0ef41Sopenharmony_ci } 17211cb0ef41Sopenharmony_ci} 17221cb0ef41Sopenharmony_ci 17231cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_f64_min(DoubleRegister dst, DoubleRegister lhs, 17241cb0ef41Sopenharmony_ci DoubleRegister rhs) { 17251cb0ef41Sopenharmony_ci liftoff::EmitFloatMinOrMax<double>(this, dst, lhs, rhs, 17261cb0ef41Sopenharmony_ci liftoff::MinOrMax::kMin); 17271cb0ef41Sopenharmony_ci} 17281cb0ef41Sopenharmony_ci 17291cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_f64_copysign(DoubleRegister dst, DoubleRegister lhs, 17301cb0ef41Sopenharmony_ci DoubleRegister rhs) { 17311cb0ef41Sopenharmony_ci // Extract sign bit from {rhs} into {kScratchRegister2}. 17321cb0ef41Sopenharmony_ci Movq(liftoff::kScratchRegister2, rhs); 17331cb0ef41Sopenharmony_ci shrq(liftoff::kScratchRegister2, Immediate(63)); 17341cb0ef41Sopenharmony_ci shlq(liftoff::kScratchRegister2, Immediate(63)); 17351cb0ef41Sopenharmony_ci // Reset sign bit of {lhs} (in {kScratchRegister}). 17361cb0ef41Sopenharmony_ci Movq(kScratchRegister, lhs); 17371cb0ef41Sopenharmony_ci btrq(kScratchRegister, Immediate(63)); 17381cb0ef41Sopenharmony_ci // Combine both values into {kScratchRegister} and move into {dst}. 17391cb0ef41Sopenharmony_ci orq(kScratchRegister, liftoff::kScratchRegister2); 17401cb0ef41Sopenharmony_ci Movq(dst, kScratchRegister); 17411cb0ef41Sopenharmony_ci} 17421cb0ef41Sopenharmony_ci 17431cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_f64_max(DoubleRegister dst, DoubleRegister lhs, 17441cb0ef41Sopenharmony_ci DoubleRegister rhs) { 17451cb0ef41Sopenharmony_ci liftoff::EmitFloatMinOrMax<double>(this, dst, lhs, rhs, 17461cb0ef41Sopenharmony_ci liftoff::MinOrMax::kMax); 17471cb0ef41Sopenharmony_ci} 17481cb0ef41Sopenharmony_ci 17491cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_f64_abs(DoubleRegister dst, DoubleRegister src) { 17501cb0ef41Sopenharmony_ci static constexpr uint64_t kSignBit = uint64_t{1} << 63; 17511cb0ef41Sopenharmony_ci if (dst == src) { 17521cb0ef41Sopenharmony_ci TurboAssembler::Move(kScratchDoubleReg, kSignBit - 1); 17531cb0ef41Sopenharmony_ci Andpd(dst, kScratchDoubleReg); 17541cb0ef41Sopenharmony_ci } else { 17551cb0ef41Sopenharmony_ci TurboAssembler::Move(dst, kSignBit - 1); 17561cb0ef41Sopenharmony_ci Andpd(dst, src); 17571cb0ef41Sopenharmony_ci } 17581cb0ef41Sopenharmony_ci} 17591cb0ef41Sopenharmony_ci 17601cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_f64_neg(DoubleRegister dst, DoubleRegister src) { 17611cb0ef41Sopenharmony_ci static constexpr uint64_t kSignBit = uint64_t{1} << 63; 17621cb0ef41Sopenharmony_ci if (dst == src) { 17631cb0ef41Sopenharmony_ci TurboAssembler::Move(kScratchDoubleReg, kSignBit); 17641cb0ef41Sopenharmony_ci Xorpd(dst, kScratchDoubleReg); 17651cb0ef41Sopenharmony_ci } else { 17661cb0ef41Sopenharmony_ci TurboAssembler::Move(dst, kSignBit); 17671cb0ef41Sopenharmony_ci Xorpd(dst, src); 17681cb0ef41Sopenharmony_ci } 17691cb0ef41Sopenharmony_ci} 17701cb0ef41Sopenharmony_ci 17711cb0ef41Sopenharmony_cibool LiftoffAssembler::emit_f64_ceil(DoubleRegister dst, DoubleRegister src) { 17721cb0ef41Sopenharmony_ci RETURN_FALSE_IF_MISSING_CPU_FEATURE(SSE4_1); 17731cb0ef41Sopenharmony_ci Roundsd(dst, src, kRoundUp); 17741cb0ef41Sopenharmony_ci return true; 17751cb0ef41Sopenharmony_ci} 17761cb0ef41Sopenharmony_ci 17771cb0ef41Sopenharmony_cibool LiftoffAssembler::emit_f64_floor(DoubleRegister dst, DoubleRegister src) { 17781cb0ef41Sopenharmony_ci RETURN_FALSE_IF_MISSING_CPU_FEATURE(SSE4_1); 17791cb0ef41Sopenharmony_ci Roundsd(dst, src, kRoundDown); 17801cb0ef41Sopenharmony_ci return true; 17811cb0ef41Sopenharmony_ci} 17821cb0ef41Sopenharmony_ci 17831cb0ef41Sopenharmony_cibool LiftoffAssembler::emit_f64_trunc(DoubleRegister dst, DoubleRegister src) { 17841cb0ef41Sopenharmony_ci RETURN_FALSE_IF_MISSING_CPU_FEATURE(SSE4_1); 17851cb0ef41Sopenharmony_ci Roundsd(dst, src, kRoundToZero); 17861cb0ef41Sopenharmony_ci return true; 17871cb0ef41Sopenharmony_ci} 17881cb0ef41Sopenharmony_ci 17891cb0ef41Sopenharmony_cibool LiftoffAssembler::emit_f64_nearest_int(DoubleRegister dst, 17901cb0ef41Sopenharmony_ci DoubleRegister src) { 17911cb0ef41Sopenharmony_ci RETURN_FALSE_IF_MISSING_CPU_FEATURE(SSE4_1); 17921cb0ef41Sopenharmony_ci Roundsd(dst, src, kRoundToNearest); 17931cb0ef41Sopenharmony_ci return true; 17941cb0ef41Sopenharmony_ci} 17951cb0ef41Sopenharmony_ci 17961cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_f64_sqrt(DoubleRegister dst, DoubleRegister src) { 17971cb0ef41Sopenharmony_ci Sqrtsd(dst, src); 17981cb0ef41Sopenharmony_ci} 17991cb0ef41Sopenharmony_ci 18001cb0ef41Sopenharmony_cinamespace liftoff { 18011cb0ef41Sopenharmony_ci#define __ assm-> 18021cb0ef41Sopenharmony_ci// Used for float to int conversions. If the value in {converted_back} equals 18031cb0ef41Sopenharmony_ci// {src} afterwards, the conversion succeeded. 18041cb0ef41Sopenharmony_citemplate <typename dst_type, typename src_type> 18051cb0ef41Sopenharmony_ciinline void ConvertFloatToIntAndBack(LiftoffAssembler* assm, Register dst, 18061cb0ef41Sopenharmony_ci DoubleRegister src, 18071cb0ef41Sopenharmony_ci DoubleRegister converted_back) { 18081cb0ef41Sopenharmony_ci if (std::is_same<double, src_type>::value) { // f64 18091cb0ef41Sopenharmony_ci if (std::is_same<int32_t, dst_type>::value) { // f64 -> i32 18101cb0ef41Sopenharmony_ci __ Cvttsd2si(dst, src); 18111cb0ef41Sopenharmony_ci __ Cvtlsi2sd(converted_back, dst); 18121cb0ef41Sopenharmony_ci } else if (std::is_same<uint32_t, dst_type>::value) { // f64 -> u32 18131cb0ef41Sopenharmony_ci __ Cvttsd2siq(dst, src); 18141cb0ef41Sopenharmony_ci __ movl(dst, dst); 18151cb0ef41Sopenharmony_ci __ Cvtqsi2sd(converted_back, dst); 18161cb0ef41Sopenharmony_ci } else if (std::is_same<int64_t, dst_type>::value) { // f64 -> i64 18171cb0ef41Sopenharmony_ci __ Cvttsd2siq(dst, src); 18181cb0ef41Sopenharmony_ci __ Cvtqsi2sd(converted_back, dst); 18191cb0ef41Sopenharmony_ci } else { 18201cb0ef41Sopenharmony_ci UNREACHABLE(); 18211cb0ef41Sopenharmony_ci } 18221cb0ef41Sopenharmony_ci } else { // f32 18231cb0ef41Sopenharmony_ci if (std::is_same<int32_t, dst_type>::value) { // f32 -> i32 18241cb0ef41Sopenharmony_ci __ Cvttss2si(dst, src); 18251cb0ef41Sopenharmony_ci __ Cvtlsi2ss(converted_back, dst); 18261cb0ef41Sopenharmony_ci } else if (std::is_same<uint32_t, dst_type>::value) { // f32 -> u32 18271cb0ef41Sopenharmony_ci __ Cvttss2siq(dst, src); 18281cb0ef41Sopenharmony_ci __ movl(dst, dst); 18291cb0ef41Sopenharmony_ci __ Cvtqsi2ss(converted_back, dst); 18301cb0ef41Sopenharmony_ci } else if (std::is_same<int64_t, dst_type>::value) { // f32 -> i64 18311cb0ef41Sopenharmony_ci __ Cvttss2siq(dst, src); 18321cb0ef41Sopenharmony_ci __ Cvtqsi2ss(converted_back, dst); 18331cb0ef41Sopenharmony_ci } else { 18341cb0ef41Sopenharmony_ci UNREACHABLE(); 18351cb0ef41Sopenharmony_ci } 18361cb0ef41Sopenharmony_ci } 18371cb0ef41Sopenharmony_ci} 18381cb0ef41Sopenharmony_ci 18391cb0ef41Sopenharmony_citemplate <typename dst_type, typename src_type> 18401cb0ef41Sopenharmony_ciinline bool EmitTruncateFloatToInt(LiftoffAssembler* assm, Register dst, 18411cb0ef41Sopenharmony_ci DoubleRegister src, Label* trap) { 18421cb0ef41Sopenharmony_ci if (!CpuFeatures::IsSupported(SSE4_1)) { 18431cb0ef41Sopenharmony_ci __ bailout(kMissingCPUFeature, "no SSE4.1"); 18441cb0ef41Sopenharmony_ci return true; 18451cb0ef41Sopenharmony_ci } 18461cb0ef41Sopenharmony_ci CpuFeatureScope feature(assm, SSE4_1); 18471cb0ef41Sopenharmony_ci 18481cb0ef41Sopenharmony_ci DoubleRegister rounded = kScratchDoubleReg; 18491cb0ef41Sopenharmony_ci DoubleRegister converted_back = kScratchDoubleReg2; 18501cb0ef41Sopenharmony_ci 18511cb0ef41Sopenharmony_ci if (std::is_same<double, src_type>::value) { // f64 18521cb0ef41Sopenharmony_ci __ Roundsd(rounded, src, kRoundToZero); 18531cb0ef41Sopenharmony_ci } else { // f32 18541cb0ef41Sopenharmony_ci __ Roundss(rounded, src, kRoundToZero); 18551cb0ef41Sopenharmony_ci } 18561cb0ef41Sopenharmony_ci ConvertFloatToIntAndBack<dst_type, src_type>(assm, dst, rounded, 18571cb0ef41Sopenharmony_ci converted_back); 18581cb0ef41Sopenharmony_ci if (std::is_same<double, src_type>::value) { // f64 18591cb0ef41Sopenharmony_ci __ Ucomisd(converted_back, rounded); 18601cb0ef41Sopenharmony_ci } else { // f32 18611cb0ef41Sopenharmony_ci __ Ucomiss(converted_back, rounded); 18621cb0ef41Sopenharmony_ci } 18631cb0ef41Sopenharmony_ci 18641cb0ef41Sopenharmony_ci // Jump to trap if PF is 0 (one of the operands was NaN) or they are not 18651cb0ef41Sopenharmony_ci // equal. 18661cb0ef41Sopenharmony_ci __ j(parity_even, trap); 18671cb0ef41Sopenharmony_ci __ j(not_equal, trap); 18681cb0ef41Sopenharmony_ci return true; 18691cb0ef41Sopenharmony_ci} 18701cb0ef41Sopenharmony_ci 18711cb0ef41Sopenharmony_citemplate <typename dst_type, typename src_type> 18721cb0ef41Sopenharmony_ciinline bool EmitSatTruncateFloatToInt(LiftoffAssembler* assm, Register dst, 18731cb0ef41Sopenharmony_ci DoubleRegister src) { 18741cb0ef41Sopenharmony_ci if (!CpuFeatures::IsSupported(SSE4_1)) { 18751cb0ef41Sopenharmony_ci __ bailout(kMissingCPUFeature, "no SSE4.1"); 18761cb0ef41Sopenharmony_ci return true; 18771cb0ef41Sopenharmony_ci } 18781cb0ef41Sopenharmony_ci CpuFeatureScope feature(assm, SSE4_1); 18791cb0ef41Sopenharmony_ci 18801cb0ef41Sopenharmony_ci Label done; 18811cb0ef41Sopenharmony_ci Label not_nan; 18821cb0ef41Sopenharmony_ci Label src_positive; 18831cb0ef41Sopenharmony_ci 18841cb0ef41Sopenharmony_ci DoubleRegister rounded = kScratchDoubleReg; 18851cb0ef41Sopenharmony_ci DoubleRegister converted_back = kScratchDoubleReg2; 18861cb0ef41Sopenharmony_ci DoubleRegister zero_reg = kScratchDoubleReg; 18871cb0ef41Sopenharmony_ci 18881cb0ef41Sopenharmony_ci if (std::is_same<double, src_type>::value) { // f64 18891cb0ef41Sopenharmony_ci __ Roundsd(rounded, src, kRoundToZero); 18901cb0ef41Sopenharmony_ci } else { // f32 18911cb0ef41Sopenharmony_ci __ Roundss(rounded, src, kRoundToZero); 18921cb0ef41Sopenharmony_ci } 18931cb0ef41Sopenharmony_ci 18941cb0ef41Sopenharmony_ci ConvertFloatToIntAndBack<dst_type, src_type>(assm, dst, rounded, 18951cb0ef41Sopenharmony_ci converted_back); 18961cb0ef41Sopenharmony_ci if (std::is_same<double, src_type>::value) { // f64 18971cb0ef41Sopenharmony_ci __ Ucomisd(converted_back, rounded); 18981cb0ef41Sopenharmony_ci } else { // f32 18991cb0ef41Sopenharmony_ci __ Ucomiss(converted_back, rounded); 19001cb0ef41Sopenharmony_ci } 19011cb0ef41Sopenharmony_ci 19021cb0ef41Sopenharmony_ci // Return 0 if PF is 0 (one of the operands was NaN) 19031cb0ef41Sopenharmony_ci __ j(parity_odd, ¬_nan); 19041cb0ef41Sopenharmony_ci __ xorl(dst, dst); 19051cb0ef41Sopenharmony_ci __ jmp(&done); 19061cb0ef41Sopenharmony_ci 19071cb0ef41Sopenharmony_ci __ bind(¬_nan); 19081cb0ef41Sopenharmony_ci // If rounding is as expected, return result 19091cb0ef41Sopenharmony_ci __ j(equal, &done); 19101cb0ef41Sopenharmony_ci 19111cb0ef41Sopenharmony_ci __ xorpd(zero_reg, zero_reg); 19121cb0ef41Sopenharmony_ci 19131cb0ef41Sopenharmony_ci // if out-of-bounds, check if src is positive 19141cb0ef41Sopenharmony_ci if (std::is_same<double, src_type>::value) { // f64 19151cb0ef41Sopenharmony_ci __ Ucomisd(src, zero_reg); 19161cb0ef41Sopenharmony_ci } else { // f32 19171cb0ef41Sopenharmony_ci __ Ucomiss(src, zero_reg); 19181cb0ef41Sopenharmony_ci } 19191cb0ef41Sopenharmony_ci __ j(above, &src_positive); 19201cb0ef41Sopenharmony_ci if (std::is_same<int32_t, dst_type>::value || 19211cb0ef41Sopenharmony_ci std::is_same<uint32_t, dst_type>::value) { // i32 19221cb0ef41Sopenharmony_ci __ movl( 19231cb0ef41Sopenharmony_ci dst, 19241cb0ef41Sopenharmony_ci Immediate(static_cast<int32_t>(std::numeric_limits<dst_type>::min()))); 19251cb0ef41Sopenharmony_ci } else if (std::is_same<int64_t, dst_type>::value) { // i64s 19261cb0ef41Sopenharmony_ci __ movq(dst, Immediate64(std::numeric_limits<dst_type>::min())); 19271cb0ef41Sopenharmony_ci } else { 19281cb0ef41Sopenharmony_ci UNREACHABLE(); 19291cb0ef41Sopenharmony_ci } 19301cb0ef41Sopenharmony_ci __ jmp(&done); 19311cb0ef41Sopenharmony_ci 19321cb0ef41Sopenharmony_ci __ bind(&src_positive); 19331cb0ef41Sopenharmony_ci if (std::is_same<int32_t, dst_type>::value || 19341cb0ef41Sopenharmony_ci std::is_same<uint32_t, dst_type>::value) { // i32 19351cb0ef41Sopenharmony_ci __ movl( 19361cb0ef41Sopenharmony_ci dst, 19371cb0ef41Sopenharmony_ci Immediate(static_cast<int32_t>(std::numeric_limits<dst_type>::max()))); 19381cb0ef41Sopenharmony_ci } else if (std::is_same<int64_t, dst_type>::value) { // i64s 19391cb0ef41Sopenharmony_ci __ movq(dst, Immediate64(std::numeric_limits<dst_type>::max())); 19401cb0ef41Sopenharmony_ci } else { 19411cb0ef41Sopenharmony_ci UNREACHABLE(); 19421cb0ef41Sopenharmony_ci } 19431cb0ef41Sopenharmony_ci 19441cb0ef41Sopenharmony_ci __ bind(&done); 19451cb0ef41Sopenharmony_ci return true; 19461cb0ef41Sopenharmony_ci} 19471cb0ef41Sopenharmony_ci 19481cb0ef41Sopenharmony_citemplate <typename src_type> 19491cb0ef41Sopenharmony_ciinline bool EmitSatTruncateFloatToUInt64(LiftoffAssembler* assm, Register dst, 19501cb0ef41Sopenharmony_ci DoubleRegister src) { 19511cb0ef41Sopenharmony_ci if (!CpuFeatures::IsSupported(SSE4_1)) { 19521cb0ef41Sopenharmony_ci __ bailout(kMissingCPUFeature, "no SSE4.1"); 19531cb0ef41Sopenharmony_ci return true; 19541cb0ef41Sopenharmony_ci } 19551cb0ef41Sopenharmony_ci CpuFeatureScope feature(assm, SSE4_1); 19561cb0ef41Sopenharmony_ci 19571cb0ef41Sopenharmony_ci Label done; 19581cb0ef41Sopenharmony_ci Label neg_or_nan; 19591cb0ef41Sopenharmony_ci Label overflow; 19601cb0ef41Sopenharmony_ci 19611cb0ef41Sopenharmony_ci DoubleRegister zero_reg = kScratchDoubleReg; 19621cb0ef41Sopenharmony_ci 19631cb0ef41Sopenharmony_ci __ xorpd(zero_reg, zero_reg); 19641cb0ef41Sopenharmony_ci if (std::is_same<double, src_type>::value) { // f64 19651cb0ef41Sopenharmony_ci __ Ucomisd(src, zero_reg); 19661cb0ef41Sopenharmony_ci } else { // f32 19671cb0ef41Sopenharmony_ci __ Ucomiss(src, zero_reg); 19681cb0ef41Sopenharmony_ci } 19691cb0ef41Sopenharmony_ci // Check if NaN 19701cb0ef41Sopenharmony_ci __ j(parity_even, &neg_or_nan); 19711cb0ef41Sopenharmony_ci __ j(below, &neg_or_nan); 19721cb0ef41Sopenharmony_ci if (std::is_same<double, src_type>::value) { // f64 19731cb0ef41Sopenharmony_ci __ Cvttsd2uiq(dst, src, &overflow); 19741cb0ef41Sopenharmony_ci } else { // f32 19751cb0ef41Sopenharmony_ci __ Cvttss2uiq(dst, src, &overflow); 19761cb0ef41Sopenharmony_ci } 19771cb0ef41Sopenharmony_ci __ jmp(&done); 19781cb0ef41Sopenharmony_ci 19791cb0ef41Sopenharmony_ci __ bind(&neg_or_nan); 19801cb0ef41Sopenharmony_ci __ movq(dst, zero_reg); 19811cb0ef41Sopenharmony_ci __ jmp(&done); 19821cb0ef41Sopenharmony_ci 19831cb0ef41Sopenharmony_ci __ bind(&overflow); 19841cb0ef41Sopenharmony_ci __ movq(dst, Immediate64(std::numeric_limits<uint64_t>::max())); 19851cb0ef41Sopenharmony_ci __ bind(&done); 19861cb0ef41Sopenharmony_ci return true; 19871cb0ef41Sopenharmony_ci} 19881cb0ef41Sopenharmony_ci#undef __ 19891cb0ef41Sopenharmony_ci} // namespace liftoff 19901cb0ef41Sopenharmony_ci 19911cb0ef41Sopenharmony_cibool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode, 19921cb0ef41Sopenharmony_ci LiftoffRegister dst, 19931cb0ef41Sopenharmony_ci LiftoffRegister src, Label* trap) { 19941cb0ef41Sopenharmony_ci switch (opcode) { 19951cb0ef41Sopenharmony_ci case kExprI32ConvertI64: 19961cb0ef41Sopenharmony_ci movl(dst.gp(), src.gp()); 19971cb0ef41Sopenharmony_ci return true; 19981cb0ef41Sopenharmony_ci case kExprI32SConvertF32: 19991cb0ef41Sopenharmony_ci return liftoff::EmitTruncateFloatToInt<int32_t, float>(this, dst.gp(), 20001cb0ef41Sopenharmony_ci src.fp(), trap); 20011cb0ef41Sopenharmony_ci case kExprI32UConvertF32: 20021cb0ef41Sopenharmony_ci return liftoff::EmitTruncateFloatToInt<uint32_t, float>(this, dst.gp(), 20031cb0ef41Sopenharmony_ci src.fp(), trap); 20041cb0ef41Sopenharmony_ci case kExprI32SConvertF64: 20051cb0ef41Sopenharmony_ci return liftoff::EmitTruncateFloatToInt<int32_t, double>(this, dst.gp(), 20061cb0ef41Sopenharmony_ci src.fp(), trap); 20071cb0ef41Sopenharmony_ci case kExprI32UConvertF64: 20081cb0ef41Sopenharmony_ci return liftoff::EmitTruncateFloatToInt<uint32_t, double>(this, dst.gp(), 20091cb0ef41Sopenharmony_ci src.fp(), trap); 20101cb0ef41Sopenharmony_ci case kExprI32SConvertSatF32: 20111cb0ef41Sopenharmony_ci return liftoff::EmitSatTruncateFloatToInt<int32_t, float>(this, dst.gp(), 20121cb0ef41Sopenharmony_ci src.fp()); 20131cb0ef41Sopenharmony_ci case kExprI32UConvertSatF32: 20141cb0ef41Sopenharmony_ci return liftoff::EmitSatTruncateFloatToInt<uint32_t, float>(this, dst.gp(), 20151cb0ef41Sopenharmony_ci src.fp()); 20161cb0ef41Sopenharmony_ci case kExprI32SConvertSatF64: 20171cb0ef41Sopenharmony_ci return liftoff::EmitSatTruncateFloatToInt<int32_t, double>(this, dst.gp(), 20181cb0ef41Sopenharmony_ci src.fp()); 20191cb0ef41Sopenharmony_ci case kExprI32UConvertSatF64: 20201cb0ef41Sopenharmony_ci return liftoff::EmitSatTruncateFloatToInt<uint32_t, double>( 20211cb0ef41Sopenharmony_ci this, dst.gp(), src.fp()); 20221cb0ef41Sopenharmony_ci case kExprI32ReinterpretF32: 20231cb0ef41Sopenharmony_ci Movd(dst.gp(), src.fp()); 20241cb0ef41Sopenharmony_ci return true; 20251cb0ef41Sopenharmony_ci case kExprI64SConvertI32: 20261cb0ef41Sopenharmony_ci movsxlq(dst.gp(), src.gp()); 20271cb0ef41Sopenharmony_ci return true; 20281cb0ef41Sopenharmony_ci case kExprI64SConvertF32: 20291cb0ef41Sopenharmony_ci return liftoff::EmitTruncateFloatToInt<int64_t, float>(this, dst.gp(), 20301cb0ef41Sopenharmony_ci src.fp(), trap); 20311cb0ef41Sopenharmony_ci case kExprI64UConvertF32: { 20321cb0ef41Sopenharmony_ci RETURN_FALSE_IF_MISSING_CPU_FEATURE(SSE4_1); 20331cb0ef41Sopenharmony_ci Cvttss2uiq(dst.gp(), src.fp(), trap); 20341cb0ef41Sopenharmony_ci return true; 20351cb0ef41Sopenharmony_ci } 20361cb0ef41Sopenharmony_ci case kExprI64SConvertF64: 20371cb0ef41Sopenharmony_ci return liftoff::EmitTruncateFloatToInt<int64_t, double>(this, dst.gp(), 20381cb0ef41Sopenharmony_ci src.fp(), trap); 20391cb0ef41Sopenharmony_ci case kExprI64UConvertF64: { 20401cb0ef41Sopenharmony_ci RETURN_FALSE_IF_MISSING_CPU_FEATURE(SSE4_1); 20411cb0ef41Sopenharmony_ci Cvttsd2uiq(dst.gp(), src.fp(), trap); 20421cb0ef41Sopenharmony_ci return true; 20431cb0ef41Sopenharmony_ci } 20441cb0ef41Sopenharmony_ci case kExprI64SConvertSatF32: 20451cb0ef41Sopenharmony_ci return liftoff::EmitSatTruncateFloatToInt<int64_t, float>(this, dst.gp(), 20461cb0ef41Sopenharmony_ci src.fp()); 20471cb0ef41Sopenharmony_ci case kExprI64UConvertSatF32: { 20481cb0ef41Sopenharmony_ci return liftoff::EmitSatTruncateFloatToUInt64<float>(this, dst.gp(), 20491cb0ef41Sopenharmony_ci src.fp()); 20501cb0ef41Sopenharmony_ci } 20511cb0ef41Sopenharmony_ci case kExprI64SConvertSatF64: 20521cb0ef41Sopenharmony_ci return liftoff::EmitSatTruncateFloatToInt<int64_t, double>(this, dst.gp(), 20531cb0ef41Sopenharmony_ci src.fp()); 20541cb0ef41Sopenharmony_ci case kExprI64UConvertSatF64: { 20551cb0ef41Sopenharmony_ci return liftoff::EmitSatTruncateFloatToUInt64<double>(this, dst.gp(), 20561cb0ef41Sopenharmony_ci src.fp()); 20571cb0ef41Sopenharmony_ci } 20581cb0ef41Sopenharmony_ci case kExprI64UConvertI32: 20591cb0ef41Sopenharmony_ci AssertZeroExtended(src.gp()); 20601cb0ef41Sopenharmony_ci if (dst.gp() != src.gp()) movl(dst.gp(), src.gp()); 20611cb0ef41Sopenharmony_ci return true; 20621cb0ef41Sopenharmony_ci case kExprI64ReinterpretF64: 20631cb0ef41Sopenharmony_ci Movq(dst.gp(), src.fp()); 20641cb0ef41Sopenharmony_ci return true; 20651cb0ef41Sopenharmony_ci case kExprF32SConvertI32: 20661cb0ef41Sopenharmony_ci Cvtlsi2ss(dst.fp(), src.gp()); 20671cb0ef41Sopenharmony_ci return true; 20681cb0ef41Sopenharmony_ci case kExprF32UConvertI32: 20691cb0ef41Sopenharmony_ci movl(kScratchRegister, src.gp()); 20701cb0ef41Sopenharmony_ci Cvtqsi2ss(dst.fp(), kScratchRegister); 20711cb0ef41Sopenharmony_ci return true; 20721cb0ef41Sopenharmony_ci case kExprF32SConvertI64: 20731cb0ef41Sopenharmony_ci Cvtqsi2ss(dst.fp(), src.gp()); 20741cb0ef41Sopenharmony_ci return true; 20751cb0ef41Sopenharmony_ci case kExprF32UConvertI64: 20761cb0ef41Sopenharmony_ci Cvtqui2ss(dst.fp(), src.gp()); 20771cb0ef41Sopenharmony_ci return true; 20781cb0ef41Sopenharmony_ci case kExprF32ConvertF64: 20791cb0ef41Sopenharmony_ci Cvtsd2ss(dst.fp(), src.fp()); 20801cb0ef41Sopenharmony_ci return true; 20811cb0ef41Sopenharmony_ci case kExprF32ReinterpretI32: 20821cb0ef41Sopenharmony_ci Movd(dst.fp(), src.gp()); 20831cb0ef41Sopenharmony_ci return true; 20841cb0ef41Sopenharmony_ci case kExprF64SConvertI32: 20851cb0ef41Sopenharmony_ci Cvtlsi2sd(dst.fp(), src.gp()); 20861cb0ef41Sopenharmony_ci return true; 20871cb0ef41Sopenharmony_ci case kExprF64UConvertI32: 20881cb0ef41Sopenharmony_ci movl(kScratchRegister, src.gp()); 20891cb0ef41Sopenharmony_ci Cvtqsi2sd(dst.fp(), kScratchRegister); 20901cb0ef41Sopenharmony_ci return true; 20911cb0ef41Sopenharmony_ci case kExprF64SConvertI64: 20921cb0ef41Sopenharmony_ci Cvtqsi2sd(dst.fp(), src.gp()); 20931cb0ef41Sopenharmony_ci return true; 20941cb0ef41Sopenharmony_ci case kExprF64UConvertI64: 20951cb0ef41Sopenharmony_ci Cvtqui2sd(dst.fp(), src.gp()); 20961cb0ef41Sopenharmony_ci return true; 20971cb0ef41Sopenharmony_ci case kExprF64ConvertF32: 20981cb0ef41Sopenharmony_ci Cvtss2sd(dst.fp(), src.fp()); 20991cb0ef41Sopenharmony_ci return true; 21001cb0ef41Sopenharmony_ci case kExprF64ReinterpretI64: 21011cb0ef41Sopenharmony_ci Movq(dst.fp(), src.gp()); 21021cb0ef41Sopenharmony_ci return true; 21031cb0ef41Sopenharmony_ci default: 21041cb0ef41Sopenharmony_ci UNREACHABLE(); 21051cb0ef41Sopenharmony_ci } 21061cb0ef41Sopenharmony_ci} 21071cb0ef41Sopenharmony_ci 21081cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32_signextend_i8(Register dst, Register src) { 21091cb0ef41Sopenharmony_ci movsxbl(dst, src); 21101cb0ef41Sopenharmony_ci} 21111cb0ef41Sopenharmony_ci 21121cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32_signextend_i16(Register dst, Register src) { 21131cb0ef41Sopenharmony_ci movsxwl(dst, src); 21141cb0ef41Sopenharmony_ci} 21151cb0ef41Sopenharmony_ci 21161cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i64_signextend_i8(LiftoffRegister dst, 21171cb0ef41Sopenharmony_ci LiftoffRegister src) { 21181cb0ef41Sopenharmony_ci movsxbq(dst.gp(), src.gp()); 21191cb0ef41Sopenharmony_ci} 21201cb0ef41Sopenharmony_ci 21211cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i64_signextend_i16(LiftoffRegister dst, 21221cb0ef41Sopenharmony_ci LiftoffRegister src) { 21231cb0ef41Sopenharmony_ci movsxwq(dst.gp(), src.gp()); 21241cb0ef41Sopenharmony_ci} 21251cb0ef41Sopenharmony_ci 21261cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i64_signextend_i32(LiftoffRegister dst, 21271cb0ef41Sopenharmony_ci LiftoffRegister src) { 21281cb0ef41Sopenharmony_ci movsxlq(dst.gp(), src.gp()); 21291cb0ef41Sopenharmony_ci} 21301cb0ef41Sopenharmony_ci 21311cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_jump(Label* label) { jmp(label); } 21321cb0ef41Sopenharmony_ci 21331cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_jump(Register target) { jmp(target); } 21341cb0ef41Sopenharmony_ci 21351cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_cond_jump(LiftoffCondition liftoff_cond, 21361cb0ef41Sopenharmony_ci Label* label, ValueKind kind, 21371cb0ef41Sopenharmony_ci Register lhs, Register rhs) { 21381cb0ef41Sopenharmony_ci Condition cond = liftoff::ToCondition(liftoff_cond); 21391cb0ef41Sopenharmony_ci if (rhs != no_reg) { 21401cb0ef41Sopenharmony_ci switch (kind) { 21411cb0ef41Sopenharmony_ci case kI32: 21421cb0ef41Sopenharmony_ci cmpl(lhs, rhs); 21431cb0ef41Sopenharmony_ci break; 21441cb0ef41Sopenharmony_ci case kRef: 21451cb0ef41Sopenharmony_ci case kOptRef: 21461cb0ef41Sopenharmony_ci case kRtt: 21471cb0ef41Sopenharmony_ci DCHECK(liftoff_cond == kEqual || liftoff_cond == kUnequal); 21481cb0ef41Sopenharmony_ci V8_FALLTHROUGH; 21491cb0ef41Sopenharmony_ci case kI64: 21501cb0ef41Sopenharmony_ci cmpq(lhs, rhs); 21511cb0ef41Sopenharmony_ci break; 21521cb0ef41Sopenharmony_ci default: 21531cb0ef41Sopenharmony_ci UNREACHABLE(); 21541cb0ef41Sopenharmony_ci } 21551cb0ef41Sopenharmony_ci } else { 21561cb0ef41Sopenharmony_ci DCHECK_EQ(kind, kI32); 21571cb0ef41Sopenharmony_ci testl(lhs, lhs); 21581cb0ef41Sopenharmony_ci } 21591cb0ef41Sopenharmony_ci 21601cb0ef41Sopenharmony_ci j(cond, label); 21611cb0ef41Sopenharmony_ci} 21621cb0ef41Sopenharmony_ci 21631cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32_cond_jumpi(LiftoffCondition liftoff_cond, 21641cb0ef41Sopenharmony_ci Label* label, Register lhs, 21651cb0ef41Sopenharmony_ci int imm) { 21661cb0ef41Sopenharmony_ci Condition cond = liftoff::ToCondition(liftoff_cond); 21671cb0ef41Sopenharmony_ci cmpl(lhs, Immediate(imm)); 21681cb0ef41Sopenharmony_ci j(cond, label); 21691cb0ef41Sopenharmony_ci} 21701cb0ef41Sopenharmony_ci 21711cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32_subi_jump_negative(Register value, 21721cb0ef41Sopenharmony_ci int subtrahend, 21731cb0ef41Sopenharmony_ci Label* result_negative) { 21741cb0ef41Sopenharmony_ci subl(value, Immediate(subtrahend)); 21751cb0ef41Sopenharmony_ci j(negative, result_negative); 21761cb0ef41Sopenharmony_ci} 21771cb0ef41Sopenharmony_ci 21781cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32_eqz(Register dst, Register src) { 21791cb0ef41Sopenharmony_ci testl(src, src); 21801cb0ef41Sopenharmony_ci setcc(equal, dst); 21811cb0ef41Sopenharmony_ci movzxbl(dst, dst); 21821cb0ef41Sopenharmony_ci} 21831cb0ef41Sopenharmony_ci 21841cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32_set_cond(LiftoffCondition liftoff_cond, 21851cb0ef41Sopenharmony_ci Register dst, Register lhs, 21861cb0ef41Sopenharmony_ci Register rhs) { 21871cb0ef41Sopenharmony_ci Condition cond = liftoff::ToCondition(liftoff_cond); 21881cb0ef41Sopenharmony_ci cmpl(lhs, rhs); 21891cb0ef41Sopenharmony_ci setcc(cond, dst); 21901cb0ef41Sopenharmony_ci movzxbl(dst, dst); 21911cb0ef41Sopenharmony_ci} 21921cb0ef41Sopenharmony_ci 21931cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i64_eqz(Register dst, LiftoffRegister src) { 21941cb0ef41Sopenharmony_ci testq(src.gp(), src.gp()); 21951cb0ef41Sopenharmony_ci setcc(equal, dst); 21961cb0ef41Sopenharmony_ci movzxbl(dst, dst); 21971cb0ef41Sopenharmony_ci} 21981cb0ef41Sopenharmony_ci 21991cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i64_set_cond(LiftoffCondition liftoff_cond, 22001cb0ef41Sopenharmony_ci Register dst, LiftoffRegister lhs, 22011cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 22021cb0ef41Sopenharmony_ci Condition cond = liftoff::ToCondition(liftoff_cond); 22031cb0ef41Sopenharmony_ci cmpq(lhs.gp(), rhs.gp()); 22041cb0ef41Sopenharmony_ci setcc(cond, dst); 22051cb0ef41Sopenharmony_ci movzxbl(dst, dst); 22061cb0ef41Sopenharmony_ci} 22071cb0ef41Sopenharmony_ci 22081cb0ef41Sopenharmony_cinamespace liftoff { 22091cb0ef41Sopenharmony_citemplate <void (SharedTurboAssembler::*cmp_op)(DoubleRegister, DoubleRegister)> 22101cb0ef41Sopenharmony_civoid EmitFloatSetCond(LiftoffAssembler* assm, Condition cond, Register dst, 22111cb0ef41Sopenharmony_ci DoubleRegister lhs, DoubleRegister rhs) { 22121cb0ef41Sopenharmony_ci Label cont; 22131cb0ef41Sopenharmony_ci Label not_nan; 22141cb0ef41Sopenharmony_ci 22151cb0ef41Sopenharmony_ci (assm->*cmp_op)(lhs, rhs); 22161cb0ef41Sopenharmony_ci // If PF is one, one of the operands was NaN. This needs special handling. 22171cb0ef41Sopenharmony_ci assm->j(parity_odd, ¬_nan, Label::kNear); 22181cb0ef41Sopenharmony_ci // Return 1 for f32.ne, 0 for all other cases. 22191cb0ef41Sopenharmony_ci if (cond == not_equal) { 22201cb0ef41Sopenharmony_ci assm->movl(dst, Immediate(1)); 22211cb0ef41Sopenharmony_ci } else { 22221cb0ef41Sopenharmony_ci assm->xorl(dst, dst); 22231cb0ef41Sopenharmony_ci } 22241cb0ef41Sopenharmony_ci assm->jmp(&cont, Label::kNear); 22251cb0ef41Sopenharmony_ci assm->bind(¬_nan); 22261cb0ef41Sopenharmony_ci 22271cb0ef41Sopenharmony_ci assm->setcc(cond, dst); 22281cb0ef41Sopenharmony_ci assm->movzxbl(dst, dst); 22291cb0ef41Sopenharmony_ci assm->bind(&cont); 22301cb0ef41Sopenharmony_ci} 22311cb0ef41Sopenharmony_ci} // namespace liftoff 22321cb0ef41Sopenharmony_ci 22331cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_f32_set_cond(LiftoffCondition liftoff_cond, 22341cb0ef41Sopenharmony_ci Register dst, DoubleRegister lhs, 22351cb0ef41Sopenharmony_ci DoubleRegister rhs) { 22361cb0ef41Sopenharmony_ci Condition cond = liftoff::ToCondition(liftoff_cond); 22371cb0ef41Sopenharmony_ci liftoff::EmitFloatSetCond<&TurboAssembler::Ucomiss>(this, cond, dst, lhs, 22381cb0ef41Sopenharmony_ci rhs); 22391cb0ef41Sopenharmony_ci} 22401cb0ef41Sopenharmony_ci 22411cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_f64_set_cond(LiftoffCondition liftoff_cond, 22421cb0ef41Sopenharmony_ci Register dst, DoubleRegister lhs, 22431cb0ef41Sopenharmony_ci DoubleRegister rhs) { 22441cb0ef41Sopenharmony_ci Condition cond = liftoff::ToCondition(liftoff_cond); 22451cb0ef41Sopenharmony_ci liftoff::EmitFloatSetCond<&TurboAssembler::Ucomisd>(this, cond, dst, lhs, 22461cb0ef41Sopenharmony_ci rhs); 22471cb0ef41Sopenharmony_ci} 22481cb0ef41Sopenharmony_ci 22491cb0ef41Sopenharmony_cibool LiftoffAssembler::emit_select(LiftoffRegister dst, Register condition, 22501cb0ef41Sopenharmony_ci LiftoffRegister true_value, 22511cb0ef41Sopenharmony_ci LiftoffRegister false_value, 22521cb0ef41Sopenharmony_ci ValueKind kind) { 22531cb0ef41Sopenharmony_ci if (kind != kI32 && kind != kI64) return false; 22541cb0ef41Sopenharmony_ci 22551cb0ef41Sopenharmony_ci testl(condition, condition); 22561cb0ef41Sopenharmony_ci 22571cb0ef41Sopenharmony_ci if (kind == kI32) { 22581cb0ef41Sopenharmony_ci if (dst == false_value) { 22591cb0ef41Sopenharmony_ci cmovl(not_zero, dst.gp(), true_value.gp()); 22601cb0ef41Sopenharmony_ci } else { 22611cb0ef41Sopenharmony_ci if (dst != true_value) movl(dst.gp(), true_value.gp()); 22621cb0ef41Sopenharmony_ci cmovl(zero, dst.gp(), false_value.gp()); 22631cb0ef41Sopenharmony_ci } 22641cb0ef41Sopenharmony_ci } else { 22651cb0ef41Sopenharmony_ci if (dst == false_value) { 22661cb0ef41Sopenharmony_ci cmovq(not_zero, dst.gp(), true_value.gp()); 22671cb0ef41Sopenharmony_ci } else { 22681cb0ef41Sopenharmony_ci if (dst != true_value) movq(dst.gp(), true_value.gp()); 22691cb0ef41Sopenharmony_ci cmovq(zero, dst.gp(), false_value.gp()); 22701cb0ef41Sopenharmony_ci } 22711cb0ef41Sopenharmony_ci } 22721cb0ef41Sopenharmony_ci 22731cb0ef41Sopenharmony_ci return true; 22741cb0ef41Sopenharmony_ci} 22751cb0ef41Sopenharmony_ci 22761cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_smi_check(Register obj, Label* target, 22771cb0ef41Sopenharmony_ci SmiCheckMode mode) { 22781cb0ef41Sopenharmony_ci testb(obj, Immediate(kSmiTagMask)); 22791cb0ef41Sopenharmony_ci Condition condition = mode == kJumpOnSmi ? zero : not_zero; 22801cb0ef41Sopenharmony_ci j(condition, target); 22811cb0ef41Sopenharmony_ci} 22821cb0ef41Sopenharmony_ci 22831cb0ef41Sopenharmony_ci// TODO(fanchenk): Distinguish mov* if data bypass delay matter. 22841cb0ef41Sopenharmony_cinamespace liftoff { 22851cb0ef41Sopenharmony_citemplate <void (Assembler::*avx_op)(XMMRegister, XMMRegister, XMMRegister), 22861cb0ef41Sopenharmony_ci void (Assembler::*sse_op)(XMMRegister, XMMRegister)> 22871cb0ef41Sopenharmony_civoid EmitSimdCommutativeBinOp( 22881cb0ef41Sopenharmony_ci LiftoffAssembler* assm, LiftoffRegister dst, LiftoffRegister lhs, 22891cb0ef41Sopenharmony_ci LiftoffRegister rhs, base::Optional<CpuFeature> feature = base::nullopt) { 22901cb0ef41Sopenharmony_ci if (CpuFeatures::IsSupported(AVX)) { 22911cb0ef41Sopenharmony_ci CpuFeatureScope scope(assm, AVX); 22921cb0ef41Sopenharmony_ci (assm->*avx_op)(dst.fp(), lhs.fp(), rhs.fp()); 22931cb0ef41Sopenharmony_ci return; 22941cb0ef41Sopenharmony_ci } 22951cb0ef41Sopenharmony_ci 22961cb0ef41Sopenharmony_ci base::Optional<CpuFeatureScope> sse_scope; 22971cb0ef41Sopenharmony_ci if (feature.has_value()) sse_scope.emplace(assm, *feature); 22981cb0ef41Sopenharmony_ci 22991cb0ef41Sopenharmony_ci if (dst.fp() == rhs.fp()) { 23001cb0ef41Sopenharmony_ci (assm->*sse_op)(dst.fp(), lhs.fp()); 23011cb0ef41Sopenharmony_ci } else { 23021cb0ef41Sopenharmony_ci if (dst.fp() != lhs.fp()) (assm->movaps)(dst.fp(), lhs.fp()); 23031cb0ef41Sopenharmony_ci (assm->*sse_op)(dst.fp(), rhs.fp()); 23041cb0ef41Sopenharmony_ci } 23051cb0ef41Sopenharmony_ci} 23061cb0ef41Sopenharmony_ci 23071cb0ef41Sopenharmony_citemplate <void (Assembler::*avx_op)(XMMRegister, XMMRegister, XMMRegister), 23081cb0ef41Sopenharmony_ci void (Assembler::*sse_op)(XMMRegister, XMMRegister)> 23091cb0ef41Sopenharmony_civoid EmitSimdNonCommutativeBinOp( 23101cb0ef41Sopenharmony_ci LiftoffAssembler* assm, LiftoffRegister dst, LiftoffRegister lhs, 23111cb0ef41Sopenharmony_ci LiftoffRegister rhs, base::Optional<CpuFeature> feature = base::nullopt) { 23121cb0ef41Sopenharmony_ci if (CpuFeatures::IsSupported(AVX)) { 23131cb0ef41Sopenharmony_ci CpuFeatureScope scope(assm, AVX); 23141cb0ef41Sopenharmony_ci (assm->*avx_op)(dst.fp(), lhs.fp(), rhs.fp()); 23151cb0ef41Sopenharmony_ci return; 23161cb0ef41Sopenharmony_ci } 23171cb0ef41Sopenharmony_ci 23181cb0ef41Sopenharmony_ci base::Optional<CpuFeatureScope> sse_scope; 23191cb0ef41Sopenharmony_ci if (feature.has_value()) sse_scope.emplace(assm, *feature); 23201cb0ef41Sopenharmony_ci 23211cb0ef41Sopenharmony_ci if (dst.fp() == rhs.fp()) { 23221cb0ef41Sopenharmony_ci assm->movaps(kScratchDoubleReg, rhs.fp()); 23231cb0ef41Sopenharmony_ci assm->movaps(dst.fp(), lhs.fp()); 23241cb0ef41Sopenharmony_ci (assm->*sse_op)(dst.fp(), kScratchDoubleReg); 23251cb0ef41Sopenharmony_ci } else { 23261cb0ef41Sopenharmony_ci if (dst.fp() != lhs.fp()) assm->movaps(dst.fp(), lhs.fp()); 23271cb0ef41Sopenharmony_ci (assm->*sse_op)(dst.fp(), rhs.fp()); 23281cb0ef41Sopenharmony_ci } 23291cb0ef41Sopenharmony_ci} 23301cb0ef41Sopenharmony_ci 23311cb0ef41Sopenharmony_citemplate <void (Assembler::*avx_op)(XMMRegister, XMMRegister, XMMRegister), 23321cb0ef41Sopenharmony_ci void (Assembler::*sse_op)(XMMRegister, XMMRegister), uint8_t width> 23331cb0ef41Sopenharmony_civoid EmitSimdShiftOp(LiftoffAssembler* assm, LiftoffRegister dst, 23341cb0ef41Sopenharmony_ci LiftoffRegister operand, LiftoffRegister count) { 23351cb0ef41Sopenharmony_ci constexpr int mask = (1 << width) - 1; 23361cb0ef41Sopenharmony_ci assm->movq(kScratchRegister, count.gp()); 23371cb0ef41Sopenharmony_ci assm->andq(kScratchRegister, Immediate(mask)); 23381cb0ef41Sopenharmony_ci assm->Movq(kScratchDoubleReg, kScratchRegister); 23391cb0ef41Sopenharmony_ci if (CpuFeatures::IsSupported(AVX)) { 23401cb0ef41Sopenharmony_ci CpuFeatureScope scope(assm, AVX); 23411cb0ef41Sopenharmony_ci (assm->*avx_op)(dst.fp(), operand.fp(), kScratchDoubleReg); 23421cb0ef41Sopenharmony_ci } else { 23431cb0ef41Sopenharmony_ci if (dst.fp() != operand.fp()) assm->movaps(dst.fp(), operand.fp()); 23441cb0ef41Sopenharmony_ci (assm->*sse_op)(dst.fp(), kScratchDoubleReg); 23451cb0ef41Sopenharmony_ci } 23461cb0ef41Sopenharmony_ci} 23471cb0ef41Sopenharmony_ci 23481cb0ef41Sopenharmony_citemplate <void (Assembler::*avx_op)(XMMRegister, XMMRegister, byte), 23491cb0ef41Sopenharmony_ci void (Assembler::*sse_op)(XMMRegister, byte), uint8_t width> 23501cb0ef41Sopenharmony_civoid EmitSimdShiftOpImm(LiftoffAssembler* assm, LiftoffRegister dst, 23511cb0ef41Sopenharmony_ci LiftoffRegister operand, int32_t count) { 23521cb0ef41Sopenharmony_ci constexpr int mask = (1 << width) - 1; 23531cb0ef41Sopenharmony_ci byte shift = static_cast<byte>(count & mask); 23541cb0ef41Sopenharmony_ci if (CpuFeatures::IsSupported(AVX)) { 23551cb0ef41Sopenharmony_ci CpuFeatureScope scope(assm, AVX); 23561cb0ef41Sopenharmony_ci (assm->*avx_op)(dst.fp(), operand.fp(), shift); 23571cb0ef41Sopenharmony_ci } else { 23581cb0ef41Sopenharmony_ci if (dst.fp() != operand.fp()) assm->movaps(dst.fp(), operand.fp()); 23591cb0ef41Sopenharmony_ci (assm->*sse_op)(dst.fp(), shift); 23601cb0ef41Sopenharmony_ci } 23611cb0ef41Sopenharmony_ci} 23621cb0ef41Sopenharmony_ci 23631cb0ef41Sopenharmony_ciinline void EmitAnyTrue(LiftoffAssembler* assm, LiftoffRegister dst, 23641cb0ef41Sopenharmony_ci LiftoffRegister src) { 23651cb0ef41Sopenharmony_ci assm->xorq(dst.gp(), dst.gp()); 23661cb0ef41Sopenharmony_ci assm->Ptest(src.fp(), src.fp()); 23671cb0ef41Sopenharmony_ci assm->setcc(not_equal, dst.gp()); 23681cb0ef41Sopenharmony_ci} 23691cb0ef41Sopenharmony_ci 23701cb0ef41Sopenharmony_citemplate <void (SharedTurboAssembler::*pcmp)(XMMRegister, XMMRegister)> 23711cb0ef41Sopenharmony_ciinline void EmitAllTrue(LiftoffAssembler* assm, LiftoffRegister dst, 23721cb0ef41Sopenharmony_ci LiftoffRegister src, 23731cb0ef41Sopenharmony_ci base::Optional<CpuFeature> feature = base::nullopt) { 23741cb0ef41Sopenharmony_ci base::Optional<CpuFeatureScope> sse_scope; 23751cb0ef41Sopenharmony_ci if (feature.has_value()) sse_scope.emplace(assm, *feature); 23761cb0ef41Sopenharmony_ci 23771cb0ef41Sopenharmony_ci XMMRegister tmp = kScratchDoubleReg; 23781cb0ef41Sopenharmony_ci assm->xorq(dst.gp(), dst.gp()); 23791cb0ef41Sopenharmony_ci assm->Pxor(tmp, tmp); 23801cb0ef41Sopenharmony_ci (assm->*pcmp)(tmp, src.fp()); 23811cb0ef41Sopenharmony_ci assm->Ptest(tmp, tmp); 23821cb0ef41Sopenharmony_ci assm->setcc(equal, dst.gp()); 23831cb0ef41Sopenharmony_ci} 23841cb0ef41Sopenharmony_ci 23851cb0ef41Sopenharmony_ci} // namespace liftoff 23861cb0ef41Sopenharmony_ci 23871cb0ef41Sopenharmony_civoid LiftoffAssembler::LoadTransform(LiftoffRegister dst, Register src_addr, 23881cb0ef41Sopenharmony_ci Register offset_reg, uintptr_t offset_imm, 23891cb0ef41Sopenharmony_ci LoadType type, 23901cb0ef41Sopenharmony_ci LoadTransformationKind transform, 23911cb0ef41Sopenharmony_ci uint32_t* protected_load_pc) { 23921cb0ef41Sopenharmony_ci Operand src_op = liftoff::GetMemOp(this, src_addr, offset_reg, offset_imm); 23931cb0ef41Sopenharmony_ci *protected_load_pc = pc_offset(); 23941cb0ef41Sopenharmony_ci MachineType memtype = type.mem_type(); 23951cb0ef41Sopenharmony_ci if (transform == LoadTransformationKind::kExtend) { 23961cb0ef41Sopenharmony_ci if (memtype == MachineType::Int8()) { 23971cb0ef41Sopenharmony_ci Pmovsxbw(dst.fp(), src_op); 23981cb0ef41Sopenharmony_ci } else if (memtype == MachineType::Uint8()) { 23991cb0ef41Sopenharmony_ci Pmovzxbw(dst.fp(), src_op); 24001cb0ef41Sopenharmony_ci } else if (memtype == MachineType::Int16()) { 24011cb0ef41Sopenharmony_ci Pmovsxwd(dst.fp(), src_op); 24021cb0ef41Sopenharmony_ci } else if (memtype == MachineType::Uint16()) { 24031cb0ef41Sopenharmony_ci Pmovzxwd(dst.fp(), src_op); 24041cb0ef41Sopenharmony_ci } else if (memtype == MachineType::Int32()) { 24051cb0ef41Sopenharmony_ci Pmovsxdq(dst.fp(), src_op); 24061cb0ef41Sopenharmony_ci } else if (memtype == MachineType::Uint32()) { 24071cb0ef41Sopenharmony_ci Pmovzxdq(dst.fp(), src_op); 24081cb0ef41Sopenharmony_ci } 24091cb0ef41Sopenharmony_ci } else if (transform == LoadTransformationKind::kZeroExtend) { 24101cb0ef41Sopenharmony_ci if (memtype == MachineType::Int32()) { 24111cb0ef41Sopenharmony_ci Movss(dst.fp(), src_op); 24121cb0ef41Sopenharmony_ci } else { 24131cb0ef41Sopenharmony_ci DCHECK_EQ(MachineType::Int64(), memtype); 24141cb0ef41Sopenharmony_ci Movsd(dst.fp(), src_op); 24151cb0ef41Sopenharmony_ci } 24161cb0ef41Sopenharmony_ci } else { 24171cb0ef41Sopenharmony_ci DCHECK_EQ(LoadTransformationKind::kSplat, transform); 24181cb0ef41Sopenharmony_ci if (memtype == MachineType::Int8()) { 24191cb0ef41Sopenharmony_ci S128Load8Splat(dst.fp(), src_op, kScratchDoubleReg); 24201cb0ef41Sopenharmony_ci } else if (memtype == MachineType::Int16()) { 24211cb0ef41Sopenharmony_ci S128Load16Splat(dst.fp(), src_op, kScratchDoubleReg); 24221cb0ef41Sopenharmony_ci } else if (memtype == MachineType::Int32()) { 24231cb0ef41Sopenharmony_ci S128Load32Splat(dst.fp(), src_op); 24241cb0ef41Sopenharmony_ci } else if (memtype == MachineType::Int64()) { 24251cb0ef41Sopenharmony_ci Movddup(dst.fp(), src_op); 24261cb0ef41Sopenharmony_ci } 24271cb0ef41Sopenharmony_ci } 24281cb0ef41Sopenharmony_ci} 24291cb0ef41Sopenharmony_ci 24301cb0ef41Sopenharmony_civoid LiftoffAssembler::LoadLane(LiftoffRegister dst, LiftoffRegister src, 24311cb0ef41Sopenharmony_ci Register addr, Register offset_reg, 24321cb0ef41Sopenharmony_ci uintptr_t offset_imm, LoadType type, 24331cb0ef41Sopenharmony_ci uint8_t laneidx, uint32_t* protected_load_pc) { 24341cb0ef41Sopenharmony_ci Operand src_op = liftoff::GetMemOp(this, addr, offset_reg, offset_imm); 24351cb0ef41Sopenharmony_ci 24361cb0ef41Sopenharmony_ci MachineType mem_type = type.mem_type(); 24371cb0ef41Sopenharmony_ci if (mem_type == MachineType::Int8()) { 24381cb0ef41Sopenharmony_ci Pinsrb(dst.fp(), src.fp(), src_op, laneidx, protected_load_pc); 24391cb0ef41Sopenharmony_ci } else if (mem_type == MachineType::Int16()) { 24401cb0ef41Sopenharmony_ci Pinsrw(dst.fp(), src.fp(), src_op, laneidx, protected_load_pc); 24411cb0ef41Sopenharmony_ci } else if (mem_type == MachineType::Int32()) { 24421cb0ef41Sopenharmony_ci Pinsrd(dst.fp(), src.fp(), src_op, laneidx, protected_load_pc); 24431cb0ef41Sopenharmony_ci } else { 24441cb0ef41Sopenharmony_ci DCHECK_EQ(MachineType::Int64(), mem_type); 24451cb0ef41Sopenharmony_ci Pinsrq(dst.fp(), src.fp(), src_op, laneidx, protected_load_pc); 24461cb0ef41Sopenharmony_ci } 24471cb0ef41Sopenharmony_ci} 24481cb0ef41Sopenharmony_ci 24491cb0ef41Sopenharmony_civoid LiftoffAssembler::StoreLane(Register dst, Register offset, 24501cb0ef41Sopenharmony_ci uintptr_t offset_imm, LiftoffRegister src, 24511cb0ef41Sopenharmony_ci StoreType type, uint8_t lane, 24521cb0ef41Sopenharmony_ci uint32_t* protected_store_pc) { 24531cb0ef41Sopenharmony_ci Operand dst_op = liftoff::GetMemOp(this, dst, offset, offset_imm); 24541cb0ef41Sopenharmony_ci if (protected_store_pc) *protected_store_pc = pc_offset(); 24551cb0ef41Sopenharmony_ci MachineRepresentation rep = type.mem_rep(); 24561cb0ef41Sopenharmony_ci if (rep == MachineRepresentation::kWord8) { 24571cb0ef41Sopenharmony_ci Pextrb(dst_op, src.fp(), lane); 24581cb0ef41Sopenharmony_ci } else if (rep == MachineRepresentation::kWord16) { 24591cb0ef41Sopenharmony_ci Pextrw(dst_op, src.fp(), lane); 24601cb0ef41Sopenharmony_ci } else if (rep == MachineRepresentation::kWord32) { 24611cb0ef41Sopenharmony_ci S128Store32Lane(dst_op, src.fp(), lane); 24621cb0ef41Sopenharmony_ci } else { 24631cb0ef41Sopenharmony_ci DCHECK_EQ(MachineRepresentation::kWord64, rep); 24641cb0ef41Sopenharmony_ci S128Store64Lane(dst_op, src.fp(), lane); 24651cb0ef41Sopenharmony_ci } 24661cb0ef41Sopenharmony_ci} 24671cb0ef41Sopenharmony_ci 24681cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i8x16_shuffle(LiftoffRegister dst, 24691cb0ef41Sopenharmony_ci LiftoffRegister lhs, 24701cb0ef41Sopenharmony_ci LiftoffRegister rhs, 24711cb0ef41Sopenharmony_ci const uint8_t shuffle[16], 24721cb0ef41Sopenharmony_ci bool is_swizzle) { 24731cb0ef41Sopenharmony_ci if (is_swizzle) { 24741cb0ef41Sopenharmony_ci uint32_t imms[4]; 24751cb0ef41Sopenharmony_ci // Shuffles that use just 1 operand are called swizzles, rhs can be ignored. 24761cb0ef41Sopenharmony_ci wasm::SimdShuffle::Pack16Lanes(imms, shuffle); 24771cb0ef41Sopenharmony_ci TurboAssembler::Move(kScratchDoubleReg, make_uint64(imms[3], imms[2]), 24781cb0ef41Sopenharmony_ci make_uint64(imms[1], imms[0])); 24791cb0ef41Sopenharmony_ci Pshufb(dst.fp(), lhs.fp(), kScratchDoubleReg); 24801cb0ef41Sopenharmony_ci return; 24811cb0ef41Sopenharmony_ci } 24821cb0ef41Sopenharmony_ci 24831cb0ef41Sopenharmony_ci uint64_t mask1[2] = {}; 24841cb0ef41Sopenharmony_ci for (int i = 15; i >= 0; i--) { 24851cb0ef41Sopenharmony_ci uint8_t lane = shuffle[i]; 24861cb0ef41Sopenharmony_ci int j = i >> 3; 24871cb0ef41Sopenharmony_ci mask1[j] <<= 8; 24881cb0ef41Sopenharmony_ci mask1[j] |= lane < kSimd128Size ? lane : 0x80; 24891cb0ef41Sopenharmony_ci } 24901cb0ef41Sopenharmony_ci TurboAssembler::Move(liftoff::kScratchDoubleReg2, mask1[1], mask1[0]); 24911cb0ef41Sopenharmony_ci Pshufb(kScratchDoubleReg, lhs.fp(), liftoff::kScratchDoubleReg2); 24921cb0ef41Sopenharmony_ci 24931cb0ef41Sopenharmony_ci uint64_t mask2[2] = {}; 24941cb0ef41Sopenharmony_ci for (int i = 15; i >= 0; i--) { 24951cb0ef41Sopenharmony_ci uint8_t lane = shuffle[i]; 24961cb0ef41Sopenharmony_ci int j = i >> 3; 24971cb0ef41Sopenharmony_ci mask2[j] <<= 8; 24981cb0ef41Sopenharmony_ci mask2[j] |= lane >= kSimd128Size ? (lane & 0x0F) : 0x80; 24991cb0ef41Sopenharmony_ci } 25001cb0ef41Sopenharmony_ci TurboAssembler::Move(liftoff::kScratchDoubleReg2, mask2[1], mask2[0]); 25011cb0ef41Sopenharmony_ci 25021cb0ef41Sopenharmony_ci Pshufb(dst.fp(), rhs.fp(), liftoff::kScratchDoubleReg2); 25031cb0ef41Sopenharmony_ci Por(dst.fp(), kScratchDoubleReg); 25041cb0ef41Sopenharmony_ci} 25051cb0ef41Sopenharmony_ci 25061cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i8x16_swizzle(LiftoffRegister dst, 25071cb0ef41Sopenharmony_ci LiftoffRegister lhs, 25081cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 25091cb0ef41Sopenharmony_ci I8x16Swizzle(dst.fp(), lhs.fp(), rhs.fp(), kScratchDoubleReg, 25101cb0ef41Sopenharmony_ci kScratchRegister); 25111cb0ef41Sopenharmony_ci} 25121cb0ef41Sopenharmony_ci 25131cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i8x16_popcnt(LiftoffRegister dst, 25141cb0ef41Sopenharmony_ci LiftoffRegister src) { 25151cb0ef41Sopenharmony_ci I8x16Popcnt(dst.fp(), src.fp(), kScratchDoubleReg, 25161cb0ef41Sopenharmony_ci liftoff::kScratchDoubleReg2, kScratchRegister); 25171cb0ef41Sopenharmony_ci} 25181cb0ef41Sopenharmony_ci 25191cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i8x16_splat(LiftoffRegister dst, 25201cb0ef41Sopenharmony_ci LiftoffRegister src) { 25211cb0ef41Sopenharmony_ci I8x16Splat(dst.fp(), src.gp(), kScratchDoubleReg); 25221cb0ef41Sopenharmony_ci} 25231cb0ef41Sopenharmony_ci 25241cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i16x8_splat(LiftoffRegister dst, 25251cb0ef41Sopenharmony_ci LiftoffRegister src) { 25261cb0ef41Sopenharmony_ci I16x8Splat(dst.fp(), src.gp()); 25271cb0ef41Sopenharmony_ci} 25281cb0ef41Sopenharmony_ci 25291cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32x4_splat(LiftoffRegister dst, 25301cb0ef41Sopenharmony_ci LiftoffRegister src) { 25311cb0ef41Sopenharmony_ci Movd(dst.fp(), src.gp()); 25321cb0ef41Sopenharmony_ci Pshufd(dst.fp(), dst.fp(), static_cast<uint8_t>(0)); 25331cb0ef41Sopenharmony_ci} 25341cb0ef41Sopenharmony_ci 25351cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i64x2_splat(LiftoffRegister dst, 25361cb0ef41Sopenharmony_ci LiftoffRegister src) { 25371cb0ef41Sopenharmony_ci Movq(dst.fp(), src.gp()); 25381cb0ef41Sopenharmony_ci Movddup(dst.fp(), dst.fp()); 25391cb0ef41Sopenharmony_ci} 25401cb0ef41Sopenharmony_ci 25411cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_f32x4_splat(LiftoffRegister dst, 25421cb0ef41Sopenharmony_ci LiftoffRegister src) { 25431cb0ef41Sopenharmony_ci F32x4Splat(dst.fp(), src.fp()); 25441cb0ef41Sopenharmony_ci} 25451cb0ef41Sopenharmony_ci 25461cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_f64x2_splat(LiftoffRegister dst, 25471cb0ef41Sopenharmony_ci LiftoffRegister src) { 25481cb0ef41Sopenharmony_ci Movddup(dst.fp(), src.fp()); 25491cb0ef41Sopenharmony_ci} 25501cb0ef41Sopenharmony_ci 25511cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i8x16_eq(LiftoffRegister dst, LiftoffRegister lhs, 25521cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 25531cb0ef41Sopenharmony_ci liftoff::EmitSimdCommutativeBinOp<&Assembler::vpcmpeqb, &Assembler::pcmpeqb>( 25541cb0ef41Sopenharmony_ci this, dst, lhs, rhs); 25551cb0ef41Sopenharmony_ci} 25561cb0ef41Sopenharmony_ci 25571cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i8x16_ne(LiftoffRegister dst, LiftoffRegister lhs, 25581cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 25591cb0ef41Sopenharmony_ci liftoff::EmitSimdCommutativeBinOp<&Assembler::vpcmpeqb, &Assembler::pcmpeqb>( 25601cb0ef41Sopenharmony_ci this, dst, lhs, rhs); 25611cb0ef41Sopenharmony_ci Pcmpeqb(kScratchDoubleReg, kScratchDoubleReg); 25621cb0ef41Sopenharmony_ci Pxor(dst.fp(), kScratchDoubleReg); 25631cb0ef41Sopenharmony_ci} 25641cb0ef41Sopenharmony_ci 25651cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i8x16_gt_s(LiftoffRegister dst, LiftoffRegister lhs, 25661cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 25671cb0ef41Sopenharmony_ci liftoff::EmitSimdNonCommutativeBinOp<&Assembler::vpcmpgtb, 25681cb0ef41Sopenharmony_ci &Assembler::pcmpgtb>(this, dst, lhs, 25691cb0ef41Sopenharmony_ci rhs); 25701cb0ef41Sopenharmony_ci} 25711cb0ef41Sopenharmony_ci 25721cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i8x16_gt_u(LiftoffRegister dst, LiftoffRegister lhs, 25731cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 25741cb0ef41Sopenharmony_ci DoubleRegister ref = rhs.fp(); 25751cb0ef41Sopenharmony_ci if (dst == rhs) { 25761cb0ef41Sopenharmony_ci Movaps(kScratchDoubleReg, rhs.fp()); 25771cb0ef41Sopenharmony_ci ref = kScratchDoubleReg; 25781cb0ef41Sopenharmony_ci } 25791cb0ef41Sopenharmony_ci liftoff::EmitSimdCommutativeBinOp<&Assembler::vpmaxub, &Assembler::pmaxub>( 25801cb0ef41Sopenharmony_ci this, dst, lhs, rhs, SSE4_1); 25811cb0ef41Sopenharmony_ci Pcmpeqb(dst.fp(), ref); 25821cb0ef41Sopenharmony_ci Pcmpeqb(kScratchDoubleReg, kScratchDoubleReg); 25831cb0ef41Sopenharmony_ci Pxor(dst.fp(), kScratchDoubleReg); 25841cb0ef41Sopenharmony_ci} 25851cb0ef41Sopenharmony_ci 25861cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i8x16_ge_s(LiftoffRegister dst, LiftoffRegister lhs, 25871cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 25881cb0ef41Sopenharmony_ci DoubleRegister ref = rhs.fp(); 25891cb0ef41Sopenharmony_ci if (dst == rhs) { 25901cb0ef41Sopenharmony_ci Movaps(kScratchDoubleReg, rhs.fp()); 25911cb0ef41Sopenharmony_ci ref = kScratchDoubleReg; 25921cb0ef41Sopenharmony_ci } 25931cb0ef41Sopenharmony_ci liftoff::EmitSimdCommutativeBinOp<&Assembler::vpminsb, &Assembler::pminsb>( 25941cb0ef41Sopenharmony_ci this, dst, lhs, rhs, SSE4_1); 25951cb0ef41Sopenharmony_ci Pcmpeqb(dst.fp(), ref); 25961cb0ef41Sopenharmony_ci} 25971cb0ef41Sopenharmony_ci 25981cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i8x16_ge_u(LiftoffRegister dst, LiftoffRegister lhs, 25991cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 26001cb0ef41Sopenharmony_ci DoubleRegister ref = rhs.fp(); 26011cb0ef41Sopenharmony_ci if (dst == rhs) { 26021cb0ef41Sopenharmony_ci Movaps(kScratchDoubleReg, rhs.fp()); 26031cb0ef41Sopenharmony_ci ref = kScratchDoubleReg; 26041cb0ef41Sopenharmony_ci } 26051cb0ef41Sopenharmony_ci liftoff::EmitSimdCommutativeBinOp<&Assembler::vpminub, &Assembler::pminub>( 26061cb0ef41Sopenharmony_ci this, dst, lhs, rhs); 26071cb0ef41Sopenharmony_ci Pcmpeqb(dst.fp(), ref); 26081cb0ef41Sopenharmony_ci} 26091cb0ef41Sopenharmony_ci 26101cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i16x8_eq(LiftoffRegister dst, LiftoffRegister lhs, 26111cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 26121cb0ef41Sopenharmony_ci liftoff::EmitSimdCommutativeBinOp<&Assembler::vpcmpeqw, &Assembler::pcmpeqw>( 26131cb0ef41Sopenharmony_ci this, dst, lhs, rhs); 26141cb0ef41Sopenharmony_ci} 26151cb0ef41Sopenharmony_ci 26161cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i16x8_ne(LiftoffRegister dst, LiftoffRegister lhs, 26171cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 26181cb0ef41Sopenharmony_ci liftoff::EmitSimdCommutativeBinOp<&Assembler::vpcmpeqw, &Assembler::pcmpeqw>( 26191cb0ef41Sopenharmony_ci this, dst, lhs, rhs); 26201cb0ef41Sopenharmony_ci Pcmpeqw(kScratchDoubleReg, kScratchDoubleReg); 26211cb0ef41Sopenharmony_ci Pxor(dst.fp(), kScratchDoubleReg); 26221cb0ef41Sopenharmony_ci} 26231cb0ef41Sopenharmony_ci 26241cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i16x8_gt_s(LiftoffRegister dst, LiftoffRegister lhs, 26251cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 26261cb0ef41Sopenharmony_ci liftoff::EmitSimdNonCommutativeBinOp<&Assembler::vpcmpgtw, 26271cb0ef41Sopenharmony_ci &Assembler::pcmpgtw>(this, dst, lhs, 26281cb0ef41Sopenharmony_ci rhs); 26291cb0ef41Sopenharmony_ci} 26301cb0ef41Sopenharmony_ci 26311cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i16x8_gt_u(LiftoffRegister dst, LiftoffRegister lhs, 26321cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 26331cb0ef41Sopenharmony_ci DoubleRegister ref = rhs.fp(); 26341cb0ef41Sopenharmony_ci if (dst == rhs) { 26351cb0ef41Sopenharmony_ci Movaps(kScratchDoubleReg, rhs.fp()); 26361cb0ef41Sopenharmony_ci ref = kScratchDoubleReg; 26371cb0ef41Sopenharmony_ci } 26381cb0ef41Sopenharmony_ci liftoff::EmitSimdCommutativeBinOp<&Assembler::vpmaxuw, &Assembler::pmaxuw>( 26391cb0ef41Sopenharmony_ci this, dst, lhs, rhs); 26401cb0ef41Sopenharmony_ci Pcmpeqw(dst.fp(), ref); 26411cb0ef41Sopenharmony_ci Pcmpeqw(kScratchDoubleReg, kScratchDoubleReg); 26421cb0ef41Sopenharmony_ci Pxor(dst.fp(), kScratchDoubleReg); 26431cb0ef41Sopenharmony_ci} 26441cb0ef41Sopenharmony_ci 26451cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i16x8_ge_s(LiftoffRegister dst, LiftoffRegister lhs, 26461cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 26471cb0ef41Sopenharmony_ci DoubleRegister ref = rhs.fp(); 26481cb0ef41Sopenharmony_ci if (dst == rhs) { 26491cb0ef41Sopenharmony_ci Movaps(kScratchDoubleReg, rhs.fp()); 26501cb0ef41Sopenharmony_ci ref = kScratchDoubleReg; 26511cb0ef41Sopenharmony_ci } 26521cb0ef41Sopenharmony_ci liftoff::EmitSimdCommutativeBinOp<&Assembler::vpminsw, &Assembler::pminsw>( 26531cb0ef41Sopenharmony_ci this, dst, lhs, rhs); 26541cb0ef41Sopenharmony_ci Pcmpeqw(dst.fp(), ref); 26551cb0ef41Sopenharmony_ci} 26561cb0ef41Sopenharmony_ci 26571cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i16x8_ge_u(LiftoffRegister dst, LiftoffRegister lhs, 26581cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 26591cb0ef41Sopenharmony_ci DoubleRegister ref = rhs.fp(); 26601cb0ef41Sopenharmony_ci if (dst == rhs) { 26611cb0ef41Sopenharmony_ci Movaps(kScratchDoubleReg, rhs.fp()); 26621cb0ef41Sopenharmony_ci ref = kScratchDoubleReg; 26631cb0ef41Sopenharmony_ci } 26641cb0ef41Sopenharmony_ci liftoff::EmitSimdCommutativeBinOp<&Assembler::vpminuw, &Assembler::pminuw>( 26651cb0ef41Sopenharmony_ci this, dst, lhs, rhs, SSE4_1); 26661cb0ef41Sopenharmony_ci Pcmpeqw(dst.fp(), ref); 26671cb0ef41Sopenharmony_ci} 26681cb0ef41Sopenharmony_ci 26691cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32x4_eq(LiftoffRegister dst, LiftoffRegister lhs, 26701cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 26711cb0ef41Sopenharmony_ci liftoff::EmitSimdCommutativeBinOp<&Assembler::vpcmpeqd, &Assembler::pcmpeqd>( 26721cb0ef41Sopenharmony_ci this, dst, lhs, rhs); 26731cb0ef41Sopenharmony_ci} 26741cb0ef41Sopenharmony_ci 26751cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32x4_ne(LiftoffRegister dst, LiftoffRegister lhs, 26761cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 26771cb0ef41Sopenharmony_ci liftoff::EmitSimdCommutativeBinOp<&Assembler::vpcmpeqd, &Assembler::pcmpeqd>( 26781cb0ef41Sopenharmony_ci this, dst, lhs, rhs); 26791cb0ef41Sopenharmony_ci Pcmpeqd(kScratchDoubleReg, kScratchDoubleReg); 26801cb0ef41Sopenharmony_ci Pxor(dst.fp(), kScratchDoubleReg); 26811cb0ef41Sopenharmony_ci} 26821cb0ef41Sopenharmony_ci 26831cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32x4_gt_s(LiftoffRegister dst, LiftoffRegister lhs, 26841cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 26851cb0ef41Sopenharmony_ci liftoff::EmitSimdNonCommutativeBinOp<&Assembler::vpcmpgtd, 26861cb0ef41Sopenharmony_ci &Assembler::pcmpgtd>(this, dst, lhs, 26871cb0ef41Sopenharmony_ci rhs); 26881cb0ef41Sopenharmony_ci} 26891cb0ef41Sopenharmony_ci 26901cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32x4_gt_u(LiftoffRegister dst, LiftoffRegister lhs, 26911cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 26921cb0ef41Sopenharmony_ci DoubleRegister ref = rhs.fp(); 26931cb0ef41Sopenharmony_ci if (dst == rhs) { 26941cb0ef41Sopenharmony_ci Movaps(kScratchDoubleReg, rhs.fp()); 26951cb0ef41Sopenharmony_ci ref = kScratchDoubleReg; 26961cb0ef41Sopenharmony_ci } 26971cb0ef41Sopenharmony_ci liftoff::EmitSimdCommutativeBinOp<&Assembler::vpmaxud, &Assembler::pmaxud>( 26981cb0ef41Sopenharmony_ci this, dst, lhs, rhs, SSE4_1); 26991cb0ef41Sopenharmony_ci Pcmpeqd(dst.fp(), ref); 27001cb0ef41Sopenharmony_ci Pcmpeqd(kScratchDoubleReg, kScratchDoubleReg); 27011cb0ef41Sopenharmony_ci Pxor(dst.fp(), kScratchDoubleReg); 27021cb0ef41Sopenharmony_ci} 27031cb0ef41Sopenharmony_ci 27041cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32x4_ge_s(LiftoffRegister dst, LiftoffRegister lhs, 27051cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 27061cb0ef41Sopenharmony_ci DoubleRegister ref = rhs.fp(); 27071cb0ef41Sopenharmony_ci if (dst == rhs) { 27081cb0ef41Sopenharmony_ci Movaps(kScratchDoubleReg, rhs.fp()); 27091cb0ef41Sopenharmony_ci ref = kScratchDoubleReg; 27101cb0ef41Sopenharmony_ci } 27111cb0ef41Sopenharmony_ci liftoff::EmitSimdCommutativeBinOp<&Assembler::vpminsd, &Assembler::pminsd>( 27121cb0ef41Sopenharmony_ci this, dst, lhs, rhs, SSE4_1); 27131cb0ef41Sopenharmony_ci Pcmpeqd(dst.fp(), ref); 27141cb0ef41Sopenharmony_ci} 27151cb0ef41Sopenharmony_ci 27161cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32x4_ge_u(LiftoffRegister dst, LiftoffRegister lhs, 27171cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 27181cb0ef41Sopenharmony_ci DoubleRegister ref = rhs.fp(); 27191cb0ef41Sopenharmony_ci if (dst == rhs) { 27201cb0ef41Sopenharmony_ci Movaps(kScratchDoubleReg, rhs.fp()); 27211cb0ef41Sopenharmony_ci ref = kScratchDoubleReg; 27221cb0ef41Sopenharmony_ci } 27231cb0ef41Sopenharmony_ci liftoff::EmitSimdCommutativeBinOp<&Assembler::vpminud, &Assembler::pminud>( 27241cb0ef41Sopenharmony_ci this, dst, lhs, rhs, SSE4_1); 27251cb0ef41Sopenharmony_ci Pcmpeqd(dst.fp(), ref); 27261cb0ef41Sopenharmony_ci} 27271cb0ef41Sopenharmony_ci 27281cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i64x2_eq(LiftoffRegister dst, LiftoffRegister lhs, 27291cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 27301cb0ef41Sopenharmony_ci liftoff::EmitSimdCommutativeBinOp<&Assembler::vpcmpeqq, &Assembler::pcmpeqq>( 27311cb0ef41Sopenharmony_ci this, dst, lhs, rhs, SSE4_1); 27321cb0ef41Sopenharmony_ci} 27331cb0ef41Sopenharmony_ci 27341cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i64x2_ne(LiftoffRegister dst, LiftoffRegister lhs, 27351cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 27361cb0ef41Sopenharmony_ci liftoff::EmitSimdCommutativeBinOp<&Assembler::vpcmpeqq, &Assembler::pcmpeqq>( 27371cb0ef41Sopenharmony_ci this, dst, lhs, rhs, SSE4_1); 27381cb0ef41Sopenharmony_ci Pcmpeqq(kScratchDoubleReg, kScratchDoubleReg); 27391cb0ef41Sopenharmony_ci Pxor(dst.fp(), kScratchDoubleReg); 27401cb0ef41Sopenharmony_ci} 27411cb0ef41Sopenharmony_ci 27421cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i64x2_gt_s(LiftoffRegister dst, LiftoffRegister lhs, 27431cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 27441cb0ef41Sopenharmony_ci // Different register alias requirements depending on CpuFeatures supported: 27451cb0ef41Sopenharmony_ci if (CpuFeatures::IsSupported(AVX) || CpuFeatures::IsSupported(SSE4_2)) { 27461cb0ef41Sopenharmony_ci // 1. AVX, or SSE4_2 no requirements (I64x2GtS takes care of aliasing). 27471cb0ef41Sopenharmony_ci I64x2GtS(dst.fp(), lhs.fp(), rhs.fp(), kScratchDoubleReg); 27481cb0ef41Sopenharmony_ci } else { 27491cb0ef41Sopenharmony_ci // 2. Else, dst != lhs && dst != rhs (lhs == rhs is ok). 27501cb0ef41Sopenharmony_ci if (dst == lhs || dst == rhs) { 27511cb0ef41Sopenharmony_ci I64x2GtS(liftoff::kScratchDoubleReg2, lhs.fp(), rhs.fp(), 27521cb0ef41Sopenharmony_ci kScratchDoubleReg); 27531cb0ef41Sopenharmony_ci movaps(dst.fp(), liftoff::kScratchDoubleReg2); 27541cb0ef41Sopenharmony_ci } else { 27551cb0ef41Sopenharmony_ci I64x2GtS(dst.fp(), lhs.fp(), rhs.fp(), kScratchDoubleReg); 27561cb0ef41Sopenharmony_ci } 27571cb0ef41Sopenharmony_ci } 27581cb0ef41Sopenharmony_ci} 27591cb0ef41Sopenharmony_ci 27601cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i64x2_ge_s(LiftoffRegister dst, LiftoffRegister lhs, 27611cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 27621cb0ef41Sopenharmony_ci // Different register alias requirements depending on CpuFeatures supported: 27631cb0ef41Sopenharmony_ci if (CpuFeatures::IsSupported(AVX)) { 27641cb0ef41Sopenharmony_ci // 1. AVX, no requirements. 27651cb0ef41Sopenharmony_ci I64x2GeS(dst.fp(), lhs.fp(), rhs.fp(), kScratchDoubleReg); 27661cb0ef41Sopenharmony_ci } else if (CpuFeatures::IsSupported(SSE4_2)) { 27671cb0ef41Sopenharmony_ci // 2. SSE4_2, dst != lhs. 27681cb0ef41Sopenharmony_ci if (dst == lhs) { 27691cb0ef41Sopenharmony_ci I64x2GeS(liftoff::kScratchDoubleReg2, lhs.fp(), rhs.fp(), 27701cb0ef41Sopenharmony_ci kScratchDoubleReg); 27711cb0ef41Sopenharmony_ci movaps(dst.fp(), liftoff::kScratchDoubleReg2); 27721cb0ef41Sopenharmony_ci } else { 27731cb0ef41Sopenharmony_ci I64x2GeS(dst.fp(), lhs.fp(), rhs.fp(), kScratchDoubleReg); 27741cb0ef41Sopenharmony_ci } 27751cb0ef41Sopenharmony_ci } else { 27761cb0ef41Sopenharmony_ci // 3. Else, dst != lhs && dst != rhs (lhs == rhs is ok). 27771cb0ef41Sopenharmony_ci if (dst == lhs || dst == rhs) { 27781cb0ef41Sopenharmony_ci I64x2GeS(liftoff::kScratchDoubleReg2, lhs.fp(), rhs.fp(), 27791cb0ef41Sopenharmony_ci kScratchDoubleReg); 27801cb0ef41Sopenharmony_ci movaps(dst.fp(), liftoff::kScratchDoubleReg2); 27811cb0ef41Sopenharmony_ci } else { 27821cb0ef41Sopenharmony_ci I64x2GeS(dst.fp(), lhs.fp(), rhs.fp(), kScratchDoubleReg); 27831cb0ef41Sopenharmony_ci } 27841cb0ef41Sopenharmony_ci } 27851cb0ef41Sopenharmony_ci} 27861cb0ef41Sopenharmony_ci 27871cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_f32x4_eq(LiftoffRegister dst, LiftoffRegister lhs, 27881cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 27891cb0ef41Sopenharmony_ci liftoff::EmitSimdCommutativeBinOp<&Assembler::vcmpeqps, &Assembler::cmpeqps>( 27901cb0ef41Sopenharmony_ci this, dst, lhs, rhs); 27911cb0ef41Sopenharmony_ci} 27921cb0ef41Sopenharmony_ci 27931cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_f32x4_ne(LiftoffRegister dst, LiftoffRegister lhs, 27941cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 27951cb0ef41Sopenharmony_ci liftoff::EmitSimdCommutativeBinOp<&Assembler::vcmpneqps, 27961cb0ef41Sopenharmony_ci &Assembler::cmpneqps>(this, dst, lhs, rhs); 27971cb0ef41Sopenharmony_ci} 27981cb0ef41Sopenharmony_ci 27991cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_f32x4_lt(LiftoffRegister dst, LiftoffRegister lhs, 28001cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 28011cb0ef41Sopenharmony_ci liftoff::EmitSimdNonCommutativeBinOp<&Assembler::vcmpltps, 28021cb0ef41Sopenharmony_ci &Assembler::cmpltps>(this, dst, lhs, 28031cb0ef41Sopenharmony_ci rhs); 28041cb0ef41Sopenharmony_ci} 28051cb0ef41Sopenharmony_ci 28061cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_f32x4_le(LiftoffRegister dst, LiftoffRegister lhs, 28071cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 28081cb0ef41Sopenharmony_ci liftoff::EmitSimdNonCommutativeBinOp<&Assembler::vcmpleps, 28091cb0ef41Sopenharmony_ci &Assembler::cmpleps>(this, dst, lhs, 28101cb0ef41Sopenharmony_ci rhs); 28111cb0ef41Sopenharmony_ci} 28121cb0ef41Sopenharmony_ci 28131cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_f64x2_eq(LiftoffRegister dst, LiftoffRegister lhs, 28141cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 28151cb0ef41Sopenharmony_ci liftoff::EmitSimdCommutativeBinOp<&Assembler::vcmpeqpd, &Assembler::cmpeqpd>( 28161cb0ef41Sopenharmony_ci this, dst, lhs, rhs); 28171cb0ef41Sopenharmony_ci} 28181cb0ef41Sopenharmony_ci 28191cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_f64x2_ne(LiftoffRegister dst, LiftoffRegister lhs, 28201cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 28211cb0ef41Sopenharmony_ci liftoff::EmitSimdCommutativeBinOp<&Assembler::vcmpneqpd, 28221cb0ef41Sopenharmony_ci &Assembler::cmpneqpd>(this, dst, lhs, rhs); 28231cb0ef41Sopenharmony_ci} 28241cb0ef41Sopenharmony_ci 28251cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_f64x2_lt(LiftoffRegister dst, LiftoffRegister lhs, 28261cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 28271cb0ef41Sopenharmony_ci liftoff::EmitSimdNonCommutativeBinOp<&Assembler::vcmpltpd, 28281cb0ef41Sopenharmony_ci &Assembler::cmpltpd>(this, dst, lhs, 28291cb0ef41Sopenharmony_ci rhs); 28301cb0ef41Sopenharmony_ci} 28311cb0ef41Sopenharmony_ci 28321cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_f64x2_le(LiftoffRegister dst, LiftoffRegister lhs, 28331cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 28341cb0ef41Sopenharmony_ci liftoff::EmitSimdNonCommutativeBinOp<&Assembler::vcmplepd, 28351cb0ef41Sopenharmony_ci &Assembler::cmplepd>(this, dst, lhs, 28361cb0ef41Sopenharmony_ci rhs); 28371cb0ef41Sopenharmony_ci} 28381cb0ef41Sopenharmony_ci 28391cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_s128_const(LiftoffRegister dst, 28401cb0ef41Sopenharmony_ci const uint8_t imms[16]) { 28411cb0ef41Sopenharmony_ci uint64_t vals[2]; 28421cb0ef41Sopenharmony_ci memcpy(vals, imms, sizeof(vals)); 28431cb0ef41Sopenharmony_ci TurboAssembler::Move(dst.fp(), vals[1], vals[0]); 28441cb0ef41Sopenharmony_ci} 28451cb0ef41Sopenharmony_ci 28461cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_s128_not(LiftoffRegister dst, LiftoffRegister src) { 28471cb0ef41Sopenharmony_ci S128Not(dst.fp(), src.fp(), kScratchDoubleReg); 28481cb0ef41Sopenharmony_ci} 28491cb0ef41Sopenharmony_ci 28501cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_s128_and(LiftoffRegister dst, LiftoffRegister lhs, 28511cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 28521cb0ef41Sopenharmony_ci liftoff::EmitSimdCommutativeBinOp<&Assembler::vpand, &Assembler::pand>( 28531cb0ef41Sopenharmony_ci this, dst, lhs, rhs); 28541cb0ef41Sopenharmony_ci} 28551cb0ef41Sopenharmony_ci 28561cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_s128_or(LiftoffRegister dst, LiftoffRegister lhs, 28571cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 28581cb0ef41Sopenharmony_ci liftoff::EmitSimdCommutativeBinOp<&Assembler::vpor, &Assembler::por>( 28591cb0ef41Sopenharmony_ci this, dst, lhs, rhs); 28601cb0ef41Sopenharmony_ci} 28611cb0ef41Sopenharmony_ci 28621cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_s128_xor(LiftoffRegister dst, LiftoffRegister lhs, 28631cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 28641cb0ef41Sopenharmony_ci liftoff::EmitSimdCommutativeBinOp<&Assembler::vpxor, &Assembler::pxor>( 28651cb0ef41Sopenharmony_ci this, dst, lhs, rhs); 28661cb0ef41Sopenharmony_ci} 28671cb0ef41Sopenharmony_ci 28681cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_s128_select(LiftoffRegister dst, 28691cb0ef41Sopenharmony_ci LiftoffRegister src1, 28701cb0ef41Sopenharmony_ci LiftoffRegister src2, 28711cb0ef41Sopenharmony_ci LiftoffRegister mask) { 28721cb0ef41Sopenharmony_ci // Ensure that we don't overwrite any inputs with the movaps below. 28731cb0ef41Sopenharmony_ci DCHECK_NE(dst, src1); 28741cb0ef41Sopenharmony_ci DCHECK_NE(dst, src2); 28751cb0ef41Sopenharmony_ci if (!CpuFeatures::IsSupported(AVX) && dst != mask) { 28761cb0ef41Sopenharmony_ci movaps(dst.fp(), mask.fp()); 28771cb0ef41Sopenharmony_ci S128Select(dst.fp(), dst.fp(), src1.fp(), src2.fp(), kScratchDoubleReg); 28781cb0ef41Sopenharmony_ci } else { 28791cb0ef41Sopenharmony_ci S128Select(dst.fp(), mask.fp(), src1.fp(), src2.fp(), kScratchDoubleReg); 28801cb0ef41Sopenharmony_ci } 28811cb0ef41Sopenharmony_ci} 28821cb0ef41Sopenharmony_ci 28831cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i8x16_neg(LiftoffRegister dst, 28841cb0ef41Sopenharmony_ci LiftoffRegister src) { 28851cb0ef41Sopenharmony_ci if (dst.fp() == src.fp()) { 28861cb0ef41Sopenharmony_ci Pcmpeqd(kScratchDoubleReg, kScratchDoubleReg); 28871cb0ef41Sopenharmony_ci Psignb(dst.fp(), kScratchDoubleReg); 28881cb0ef41Sopenharmony_ci } else { 28891cb0ef41Sopenharmony_ci Pxor(dst.fp(), dst.fp()); 28901cb0ef41Sopenharmony_ci Psubb(dst.fp(), src.fp()); 28911cb0ef41Sopenharmony_ci } 28921cb0ef41Sopenharmony_ci} 28931cb0ef41Sopenharmony_ci 28941cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_v128_anytrue(LiftoffRegister dst, 28951cb0ef41Sopenharmony_ci LiftoffRegister src) { 28961cb0ef41Sopenharmony_ci liftoff::EmitAnyTrue(this, dst, src); 28971cb0ef41Sopenharmony_ci} 28981cb0ef41Sopenharmony_ci 28991cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i8x16_alltrue(LiftoffRegister dst, 29001cb0ef41Sopenharmony_ci LiftoffRegister src) { 29011cb0ef41Sopenharmony_ci liftoff::EmitAllTrue<&TurboAssembler::Pcmpeqb>(this, dst, src); 29021cb0ef41Sopenharmony_ci} 29031cb0ef41Sopenharmony_ci 29041cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i8x16_bitmask(LiftoffRegister dst, 29051cb0ef41Sopenharmony_ci LiftoffRegister src) { 29061cb0ef41Sopenharmony_ci Pmovmskb(dst.gp(), src.fp()); 29071cb0ef41Sopenharmony_ci} 29081cb0ef41Sopenharmony_ci 29091cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i8x16_shl(LiftoffRegister dst, LiftoffRegister lhs, 29101cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 29111cb0ef41Sopenharmony_ci I8x16Shl(dst.fp(), lhs.fp(), rhs.gp(), kScratchRegister, kScratchDoubleReg, 29121cb0ef41Sopenharmony_ci liftoff::kScratchDoubleReg2); 29131cb0ef41Sopenharmony_ci} 29141cb0ef41Sopenharmony_ci 29151cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i8x16_shli(LiftoffRegister dst, LiftoffRegister lhs, 29161cb0ef41Sopenharmony_ci int32_t rhs) { 29171cb0ef41Sopenharmony_ci I8x16Shl(dst.fp(), lhs.fp(), rhs, kScratchRegister, kScratchDoubleReg); 29181cb0ef41Sopenharmony_ci} 29191cb0ef41Sopenharmony_ci 29201cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i8x16_shr_s(LiftoffRegister dst, 29211cb0ef41Sopenharmony_ci LiftoffRegister lhs, 29221cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 29231cb0ef41Sopenharmony_ci I8x16ShrS(dst.fp(), lhs.fp(), rhs.gp(), kScratchRegister, kScratchDoubleReg, 29241cb0ef41Sopenharmony_ci liftoff::kScratchDoubleReg2); 29251cb0ef41Sopenharmony_ci} 29261cb0ef41Sopenharmony_ci 29271cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i8x16_shri_s(LiftoffRegister dst, 29281cb0ef41Sopenharmony_ci LiftoffRegister lhs, int32_t rhs) { 29291cb0ef41Sopenharmony_ci I8x16ShrS(dst.fp(), lhs.fp(), rhs, kScratchDoubleReg); 29301cb0ef41Sopenharmony_ci} 29311cb0ef41Sopenharmony_ci 29321cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i8x16_shr_u(LiftoffRegister dst, 29331cb0ef41Sopenharmony_ci LiftoffRegister lhs, 29341cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 29351cb0ef41Sopenharmony_ci I8x16ShrU(dst.fp(), lhs.fp(), rhs.gp(), kScratchRegister, kScratchDoubleReg, 29361cb0ef41Sopenharmony_ci liftoff::kScratchDoubleReg2); 29371cb0ef41Sopenharmony_ci} 29381cb0ef41Sopenharmony_ci 29391cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i8x16_shri_u(LiftoffRegister dst, 29401cb0ef41Sopenharmony_ci LiftoffRegister lhs, int32_t rhs) { 29411cb0ef41Sopenharmony_ci I8x16ShrU(dst.fp(), lhs.fp(), rhs, kScratchRegister, kScratchDoubleReg); 29421cb0ef41Sopenharmony_ci} 29431cb0ef41Sopenharmony_ci 29441cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i8x16_add(LiftoffRegister dst, LiftoffRegister lhs, 29451cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 29461cb0ef41Sopenharmony_ci liftoff::EmitSimdCommutativeBinOp<&Assembler::vpaddb, &Assembler::paddb>( 29471cb0ef41Sopenharmony_ci this, dst, lhs, rhs); 29481cb0ef41Sopenharmony_ci} 29491cb0ef41Sopenharmony_ci 29501cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i8x16_add_sat_s(LiftoffRegister dst, 29511cb0ef41Sopenharmony_ci LiftoffRegister lhs, 29521cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 29531cb0ef41Sopenharmony_ci liftoff::EmitSimdCommutativeBinOp<&Assembler::vpaddsb, &Assembler::paddsb>( 29541cb0ef41Sopenharmony_ci this, dst, lhs, rhs); 29551cb0ef41Sopenharmony_ci} 29561cb0ef41Sopenharmony_ci 29571cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i8x16_add_sat_u(LiftoffRegister dst, 29581cb0ef41Sopenharmony_ci LiftoffRegister lhs, 29591cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 29601cb0ef41Sopenharmony_ci liftoff::EmitSimdCommutativeBinOp<&Assembler::vpaddusb, &Assembler::paddusb>( 29611cb0ef41Sopenharmony_ci this, dst, lhs, rhs); 29621cb0ef41Sopenharmony_ci} 29631cb0ef41Sopenharmony_ci 29641cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i8x16_sub(LiftoffRegister dst, LiftoffRegister lhs, 29651cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 29661cb0ef41Sopenharmony_ci liftoff::EmitSimdNonCommutativeBinOp<&Assembler::vpsubb, &Assembler::psubb>( 29671cb0ef41Sopenharmony_ci this, dst, lhs, rhs); 29681cb0ef41Sopenharmony_ci} 29691cb0ef41Sopenharmony_ci 29701cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i8x16_sub_sat_s(LiftoffRegister dst, 29711cb0ef41Sopenharmony_ci LiftoffRegister lhs, 29721cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 29731cb0ef41Sopenharmony_ci liftoff::EmitSimdNonCommutativeBinOp<&Assembler::vpsubsb, &Assembler::psubsb>( 29741cb0ef41Sopenharmony_ci this, dst, lhs, rhs); 29751cb0ef41Sopenharmony_ci} 29761cb0ef41Sopenharmony_ci 29771cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i8x16_sub_sat_u(LiftoffRegister dst, 29781cb0ef41Sopenharmony_ci LiftoffRegister lhs, 29791cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 29801cb0ef41Sopenharmony_ci liftoff::EmitSimdNonCommutativeBinOp<&Assembler::vpsubusb, 29811cb0ef41Sopenharmony_ci &Assembler::psubusb>(this, dst, lhs, 29821cb0ef41Sopenharmony_ci rhs); 29831cb0ef41Sopenharmony_ci} 29841cb0ef41Sopenharmony_ci 29851cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i8x16_min_s(LiftoffRegister dst, 29861cb0ef41Sopenharmony_ci LiftoffRegister lhs, 29871cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 29881cb0ef41Sopenharmony_ci liftoff::EmitSimdCommutativeBinOp<&Assembler::vpminsb, &Assembler::pminsb>( 29891cb0ef41Sopenharmony_ci this, dst, lhs, rhs, base::Optional<CpuFeature>(SSE4_1)); 29901cb0ef41Sopenharmony_ci} 29911cb0ef41Sopenharmony_ci 29921cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i8x16_min_u(LiftoffRegister dst, 29931cb0ef41Sopenharmony_ci LiftoffRegister lhs, 29941cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 29951cb0ef41Sopenharmony_ci liftoff::EmitSimdCommutativeBinOp<&Assembler::vpminub, &Assembler::pminub>( 29961cb0ef41Sopenharmony_ci this, dst, lhs, rhs); 29971cb0ef41Sopenharmony_ci} 29981cb0ef41Sopenharmony_ci 29991cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i8x16_max_s(LiftoffRegister dst, 30001cb0ef41Sopenharmony_ci LiftoffRegister lhs, 30011cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 30021cb0ef41Sopenharmony_ci liftoff::EmitSimdCommutativeBinOp<&Assembler::vpmaxsb, &Assembler::pmaxsb>( 30031cb0ef41Sopenharmony_ci this, dst, lhs, rhs, base::Optional<CpuFeature>(SSE4_1)); 30041cb0ef41Sopenharmony_ci} 30051cb0ef41Sopenharmony_ci 30061cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i8x16_max_u(LiftoffRegister dst, 30071cb0ef41Sopenharmony_ci LiftoffRegister lhs, 30081cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 30091cb0ef41Sopenharmony_ci liftoff::EmitSimdCommutativeBinOp<&Assembler::vpmaxub, &Assembler::pmaxub>( 30101cb0ef41Sopenharmony_ci this, dst, lhs, rhs); 30111cb0ef41Sopenharmony_ci} 30121cb0ef41Sopenharmony_ci 30131cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i16x8_neg(LiftoffRegister dst, 30141cb0ef41Sopenharmony_ci LiftoffRegister src) { 30151cb0ef41Sopenharmony_ci if (dst.fp() == src.fp()) { 30161cb0ef41Sopenharmony_ci Pcmpeqd(kScratchDoubleReg, kScratchDoubleReg); 30171cb0ef41Sopenharmony_ci Psignw(dst.fp(), kScratchDoubleReg); 30181cb0ef41Sopenharmony_ci } else { 30191cb0ef41Sopenharmony_ci Pxor(dst.fp(), dst.fp()); 30201cb0ef41Sopenharmony_ci Psubw(dst.fp(), src.fp()); 30211cb0ef41Sopenharmony_ci } 30221cb0ef41Sopenharmony_ci} 30231cb0ef41Sopenharmony_ci 30241cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i16x8_alltrue(LiftoffRegister dst, 30251cb0ef41Sopenharmony_ci LiftoffRegister src) { 30261cb0ef41Sopenharmony_ci liftoff::EmitAllTrue<&TurboAssembler::Pcmpeqw>(this, dst, src); 30271cb0ef41Sopenharmony_ci} 30281cb0ef41Sopenharmony_ci 30291cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i16x8_bitmask(LiftoffRegister dst, 30301cb0ef41Sopenharmony_ci LiftoffRegister src) { 30311cb0ef41Sopenharmony_ci XMMRegister tmp = kScratchDoubleReg; 30321cb0ef41Sopenharmony_ci Packsswb(tmp, src.fp()); 30331cb0ef41Sopenharmony_ci Pmovmskb(dst.gp(), tmp); 30341cb0ef41Sopenharmony_ci shrq(dst.gp(), Immediate(8)); 30351cb0ef41Sopenharmony_ci} 30361cb0ef41Sopenharmony_ci 30371cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i16x8_shl(LiftoffRegister dst, LiftoffRegister lhs, 30381cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 30391cb0ef41Sopenharmony_ci liftoff::EmitSimdShiftOp<&Assembler::vpsllw, &Assembler::psllw, 4>(this, dst, 30401cb0ef41Sopenharmony_ci lhs, rhs); 30411cb0ef41Sopenharmony_ci} 30421cb0ef41Sopenharmony_ci 30431cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i16x8_shli(LiftoffRegister dst, LiftoffRegister lhs, 30441cb0ef41Sopenharmony_ci int32_t rhs) { 30451cb0ef41Sopenharmony_ci liftoff::EmitSimdShiftOpImm<&Assembler::vpsllw, &Assembler::psllw, 4>( 30461cb0ef41Sopenharmony_ci this, dst, lhs, rhs); 30471cb0ef41Sopenharmony_ci} 30481cb0ef41Sopenharmony_ci 30491cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i16x8_shr_s(LiftoffRegister dst, 30501cb0ef41Sopenharmony_ci LiftoffRegister lhs, 30511cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 30521cb0ef41Sopenharmony_ci liftoff::EmitSimdShiftOp<&Assembler::vpsraw, &Assembler::psraw, 4>(this, dst, 30531cb0ef41Sopenharmony_ci lhs, rhs); 30541cb0ef41Sopenharmony_ci} 30551cb0ef41Sopenharmony_ci 30561cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i16x8_shri_s(LiftoffRegister dst, 30571cb0ef41Sopenharmony_ci LiftoffRegister lhs, int32_t rhs) { 30581cb0ef41Sopenharmony_ci liftoff::EmitSimdShiftOpImm<&Assembler::vpsraw, &Assembler::psraw, 4>( 30591cb0ef41Sopenharmony_ci this, dst, lhs, rhs); 30601cb0ef41Sopenharmony_ci} 30611cb0ef41Sopenharmony_ci 30621cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i16x8_shr_u(LiftoffRegister dst, 30631cb0ef41Sopenharmony_ci LiftoffRegister lhs, 30641cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 30651cb0ef41Sopenharmony_ci liftoff::EmitSimdShiftOp<&Assembler::vpsrlw, &Assembler::psrlw, 4>(this, dst, 30661cb0ef41Sopenharmony_ci lhs, rhs); 30671cb0ef41Sopenharmony_ci} 30681cb0ef41Sopenharmony_ci 30691cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i16x8_shri_u(LiftoffRegister dst, 30701cb0ef41Sopenharmony_ci LiftoffRegister lhs, int32_t rhs) { 30711cb0ef41Sopenharmony_ci liftoff::EmitSimdShiftOpImm<&Assembler::vpsrlw, &Assembler::psrlw, 4>( 30721cb0ef41Sopenharmony_ci this, dst, lhs, rhs); 30731cb0ef41Sopenharmony_ci} 30741cb0ef41Sopenharmony_ci 30751cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i16x8_add(LiftoffRegister dst, LiftoffRegister lhs, 30761cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 30771cb0ef41Sopenharmony_ci liftoff::EmitSimdCommutativeBinOp<&Assembler::vpaddw, &Assembler::paddw>( 30781cb0ef41Sopenharmony_ci this, dst, lhs, rhs); 30791cb0ef41Sopenharmony_ci} 30801cb0ef41Sopenharmony_ci 30811cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i16x8_add_sat_s(LiftoffRegister dst, 30821cb0ef41Sopenharmony_ci LiftoffRegister lhs, 30831cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 30841cb0ef41Sopenharmony_ci liftoff::EmitSimdCommutativeBinOp<&Assembler::vpaddsw, &Assembler::paddsw>( 30851cb0ef41Sopenharmony_ci this, dst, lhs, rhs); 30861cb0ef41Sopenharmony_ci} 30871cb0ef41Sopenharmony_ci 30881cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i16x8_add_sat_u(LiftoffRegister dst, 30891cb0ef41Sopenharmony_ci LiftoffRegister lhs, 30901cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 30911cb0ef41Sopenharmony_ci liftoff::EmitSimdCommutativeBinOp<&Assembler::vpaddusw, &Assembler::paddusw>( 30921cb0ef41Sopenharmony_ci this, dst, lhs, rhs); 30931cb0ef41Sopenharmony_ci} 30941cb0ef41Sopenharmony_ci 30951cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i16x8_sub(LiftoffRegister dst, LiftoffRegister lhs, 30961cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 30971cb0ef41Sopenharmony_ci liftoff::EmitSimdNonCommutativeBinOp<&Assembler::vpsubw, &Assembler::psubw>( 30981cb0ef41Sopenharmony_ci this, dst, lhs, rhs); 30991cb0ef41Sopenharmony_ci} 31001cb0ef41Sopenharmony_ci 31011cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i16x8_sub_sat_s(LiftoffRegister dst, 31021cb0ef41Sopenharmony_ci LiftoffRegister lhs, 31031cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 31041cb0ef41Sopenharmony_ci liftoff::EmitSimdNonCommutativeBinOp<&Assembler::vpsubsw, &Assembler::psubsw>( 31051cb0ef41Sopenharmony_ci this, dst, lhs, rhs); 31061cb0ef41Sopenharmony_ci} 31071cb0ef41Sopenharmony_ci 31081cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i16x8_sub_sat_u(LiftoffRegister dst, 31091cb0ef41Sopenharmony_ci LiftoffRegister lhs, 31101cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 31111cb0ef41Sopenharmony_ci liftoff::EmitSimdNonCommutativeBinOp<&Assembler::vpsubusw, 31121cb0ef41Sopenharmony_ci &Assembler::psubusw>(this, dst, lhs, 31131cb0ef41Sopenharmony_ci rhs); 31141cb0ef41Sopenharmony_ci} 31151cb0ef41Sopenharmony_ci 31161cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i16x8_mul(LiftoffRegister dst, LiftoffRegister lhs, 31171cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 31181cb0ef41Sopenharmony_ci liftoff::EmitSimdCommutativeBinOp<&Assembler::vpmullw, &Assembler::pmullw>( 31191cb0ef41Sopenharmony_ci this, dst, lhs, rhs); 31201cb0ef41Sopenharmony_ci} 31211cb0ef41Sopenharmony_ci 31221cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i16x8_min_s(LiftoffRegister dst, 31231cb0ef41Sopenharmony_ci LiftoffRegister lhs, 31241cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 31251cb0ef41Sopenharmony_ci liftoff::EmitSimdCommutativeBinOp<&Assembler::vpminsw, &Assembler::pminsw>( 31261cb0ef41Sopenharmony_ci this, dst, lhs, rhs); 31271cb0ef41Sopenharmony_ci} 31281cb0ef41Sopenharmony_ci 31291cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i16x8_min_u(LiftoffRegister dst, 31301cb0ef41Sopenharmony_ci LiftoffRegister lhs, 31311cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 31321cb0ef41Sopenharmony_ci liftoff::EmitSimdCommutativeBinOp<&Assembler::vpminuw, &Assembler::pminuw>( 31331cb0ef41Sopenharmony_ci this, dst, lhs, rhs, base::Optional<CpuFeature>(SSE4_1)); 31341cb0ef41Sopenharmony_ci} 31351cb0ef41Sopenharmony_ci 31361cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i16x8_max_s(LiftoffRegister dst, 31371cb0ef41Sopenharmony_ci LiftoffRegister lhs, 31381cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 31391cb0ef41Sopenharmony_ci liftoff::EmitSimdCommutativeBinOp<&Assembler::vpmaxsw, &Assembler::pmaxsw>( 31401cb0ef41Sopenharmony_ci this, dst, lhs, rhs); 31411cb0ef41Sopenharmony_ci} 31421cb0ef41Sopenharmony_ci 31431cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i16x8_max_u(LiftoffRegister dst, 31441cb0ef41Sopenharmony_ci LiftoffRegister lhs, 31451cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 31461cb0ef41Sopenharmony_ci liftoff::EmitSimdCommutativeBinOp<&Assembler::vpmaxuw, &Assembler::pmaxuw>( 31471cb0ef41Sopenharmony_ci this, dst, lhs, rhs, base::Optional<CpuFeature>(SSE4_1)); 31481cb0ef41Sopenharmony_ci} 31491cb0ef41Sopenharmony_ci 31501cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i16x8_extadd_pairwise_i8x16_s(LiftoffRegister dst, 31511cb0ef41Sopenharmony_ci LiftoffRegister src) { 31521cb0ef41Sopenharmony_ci I16x8ExtAddPairwiseI8x16S(dst.fp(), src.fp(), kScratchDoubleReg, 31531cb0ef41Sopenharmony_ci kScratchRegister); 31541cb0ef41Sopenharmony_ci} 31551cb0ef41Sopenharmony_ci 31561cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i16x8_extadd_pairwise_i8x16_u(LiftoffRegister dst, 31571cb0ef41Sopenharmony_ci LiftoffRegister src) { 31581cb0ef41Sopenharmony_ci I16x8ExtAddPairwiseI8x16U(dst.fp(), src.fp(), kScratchRegister); 31591cb0ef41Sopenharmony_ci} 31601cb0ef41Sopenharmony_ci 31611cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i16x8_extmul_low_i8x16_s(LiftoffRegister dst, 31621cb0ef41Sopenharmony_ci LiftoffRegister src1, 31631cb0ef41Sopenharmony_ci LiftoffRegister src2) { 31641cb0ef41Sopenharmony_ci I16x8ExtMulLow(dst.fp(), src1.fp(), src2.fp(), kScratchDoubleReg, 31651cb0ef41Sopenharmony_ci /*is_signed=*/true); 31661cb0ef41Sopenharmony_ci} 31671cb0ef41Sopenharmony_ci 31681cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i16x8_extmul_low_i8x16_u(LiftoffRegister dst, 31691cb0ef41Sopenharmony_ci LiftoffRegister src1, 31701cb0ef41Sopenharmony_ci LiftoffRegister src2) { 31711cb0ef41Sopenharmony_ci I16x8ExtMulLow(dst.fp(), src1.fp(), src2.fp(), kScratchDoubleReg, 31721cb0ef41Sopenharmony_ci /*is_signed=*/false); 31731cb0ef41Sopenharmony_ci} 31741cb0ef41Sopenharmony_ci 31751cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i16x8_extmul_high_i8x16_s(LiftoffRegister dst, 31761cb0ef41Sopenharmony_ci LiftoffRegister src1, 31771cb0ef41Sopenharmony_ci LiftoffRegister src2) { 31781cb0ef41Sopenharmony_ci I16x8ExtMulHighS(dst.fp(), src1.fp(), src2.fp(), kScratchDoubleReg); 31791cb0ef41Sopenharmony_ci} 31801cb0ef41Sopenharmony_ci 31811cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i16x8_extmul_high_i8x16_u(LiftoffRegister dst, 31821cb0ef41Sopenharmony_ci LiftoffRegister src1, 31831cb0ef41Sopenharmony_ci LiftoffRegister src2) { 31841cb0ef41Sopenharmony_ci I16x8ExtMulHighU(dst.fp(), src1.fp(), src2.fp(), kScratchDoubleReg); 31851cb0ef41Sopenharmony_ci} 31861cb0ef41Sopenharmony_ci 31871cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i16x8_q15mulr_sat_s(LiftoffRegister dst, 31881cb0ef41Sopenharmony_ci LiftoffRegister src1, 31891cb0ef41Sopenharmony_ci LiftoffRegister src2) { 31901cb0ef41Sopenharmony_ci I16x8Q15MulRSatS(dst.fp(), src1.fp(), src2.fp(), kScratchDoubleReg); 31911cb0ef41Sopenharmony_ci} 31921cb0ef41Sopenharmony_ci 31931cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32x4_neg(LiftoffRegister dst, 31941cb0ef41Sopenharmony_ci LiftoffRegister src) { 31951cb0ef41Sopenharmony_ci if (dst.fp() == src.fp()) { 31961cb0ef41Sopenharmony_ci Pcmpeqd(kScratchDoubleReg, kScratchDoubleReg); 31971cb0ef41Sopenharmony_ci Psignd(dst.fp(), kScratchDoubleReg); 31981cb0ef41Sopenharmony_ci } else { 31991cb0ef41Sopenharmony_ci Pxor(dst.fp(), dst.fp()); 32001cb0ef41Sopenharmony_ci Psubd(dst.fp(), src.fp()); 32011cb0ef41Sopenharmony_ci } 32021cb0ef41Sopenharmony_ci} 32031cb0ef41Sopenharmony_ci 32041cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32x4_alltrue(LiftoffRegister dst, 32051cb0ef41Sopenharmony_ci LiftoffRegister src) { 32061cb0ef41Sopenharmony_ci liftoff::EmitAllTrue<&TurboAssembler::Pcmpeqd>(this, dst, src); 32071cb0ef41Sopenharmony_ci} 32081cb0ef41Sopenharmony_ci 32091cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32x4_bitmask(LiftoffRegister dst, 32101cb0ef41Sopenharmony_ci LiftoffRegister src) { 32111cb0ef41Sopenharmony_ci Movmskps(dst.gp(), src.fp()); 32121cb0ef41Sopenharmony_ci} 32131cb0ef41Sopenharmony_ci 32141cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32x4_shl(LiftoffRegister dst, LiftoffRegister lhs, 32151cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 32161cb0ef41Sopenharmony_ci liftoff::EmitSimdShiftOp<&Assembler::vpslld, &Assembler::pslld, 5>(this, dst, 32171cb0ef41Sopenharmony_ci lhs, rhs); 32181cb0ef41Sopenharmony_ci} 32191cb0ef41Sopenharmony_ci 32201cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32x4_shli(LiftoffRegister dst, LiftoffRegister lhs, 32211cb0ef41Sopenharmony_ci int32_t rhs) { 32221cb0ef41Sopenharmony_ci liftoff::EmitSimdShiftOpImm<&Assembler::vpslld, &Assembler::pslld, 5>( 32231cb0ef41Sopenharmony_ci this, dst, lhs, rhs); 32241cb0ef41Sopenharmony_ci} 32251cb0ef41Sopenharmony_ci 32261cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32x4_shr_s(LiftoffRegister dst, 32271cb0ef41Sopenharmony_ci LiftoffRegister lhs, 32281cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 32291cb0ef41Sopenharmony_ci liftoff::EmitSimdShiftOp<&Assembler::vpsrad, &Assembler::psrad, 5>(this, dst, 32301cb0ef41Sopenharmony_ci lhs, rhs); 32311cb0ef41Sopenharmony_ci} 32321cb0ef41Sopenharmony_ci 32331cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32x4_shri_s(LiftoffRegister dst, 32341cb0ef41Sopenharmony_ci LiftoffRegister lhs, int32_t rhs) { 32351cb0ef41Sopenharmony_ci liftoff::EmitSimdShiftOpImm<&Assembler::vpsrad, &Assembler::psrad, 5>( 32361cb0ef41Sopenharmony_ci this, dst, lhs, rhs); 32371cb0ef41Sopenharmony_ci} 32381cb0ef41Sopenharmony_ci 32391cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32x4_shr_u(LiftoffRegister dst, 32401cb0ef41Sopenharmony_ci LiftoffRegister lhs, 32411cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 32421cb0ef41Sopenharmony_ci liftoff::EmitSimdShiftOp<&Assembler::vpsrld, &Assembler::psrld, 5>(this, dst, 32431cb0ef41Sopenharmony_ci lhs, rhs); 32441cb0ef41Sopenharmony_ci} 32451cb0ef41Sopenharmony_ci 32461cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32x4_shri_u(LiftoffRegister dst, 32471cb0ef41Sopenharmony_ci LiftoffRegister lhs, int32_t rhs) { 32481cb0ef41Sopenharmony_ci liftoff::EmitSimdShiftOpImm<&Assembler::vpsrld, &Assembler::psrld, 5>( 32491cb0ef41Sopenharmony_ci this, dst, lhs, rhs); 32501cb0ef41Sopenharmony_ci} 32511cb0ef41Sopenharmony_ci 32521cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32x4_add(LiftoffRegister dst, LiftoffRegister lhs, 32531cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 32541cb0ef41Sopenharmony_ci liftoff::EmitSimdCommutativeBinOp<&Assembler::vpaddd, &Assembler::paddd>( 32551cb0ef41Sopenharmony_ci this, dst, lhs, rhs); 32561cb0ef41Sopenharmony_ci} 32571cb0ef41Sopenharmony_ci 32581cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32x4_sub(LiftoffRegister dst, LiftoffRegister lhs, 32591cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 32601cb0ef41Sopenharmony_ci liftoff::EmitSimdNonCommutativeBinOp<&Assembler::vpsubd, &Assembler::psubd>( 32611cb0ef41Sopenharmony_ci this, dst, lhs, rhs); 32621cb0ef41Sopenharmony_ci} 32631cb0ef41Sopenharmony_ci 32641cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32x4_mul(LiftoffRegister dst, LiftoffRegister lhs, 32651cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 32661cb0ef41Sopenharmony_ci liftoff::EmitSimdCommutativeBinOp<&Assembler::vpmulld, &Assembler::pmulld>( 32671cb0ef41Sopenharmony_ci this, dst, lhs, rhs, base::Optional<CpuFeature>(SSE4_1)); 32681cb0ef41Sopenharmony_ci} 32691cb0ef41Sopenharmony_ci 32701cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32x4_min_s(LiftoffRegister dst, 32711cb0ef41Sopenharmony_ci LiftoffRegister lhs, 32721cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 32731cb0ef41Sopenharmony_ci liftoff::EmitSimdCommutativeBinOp<&Assembler::vpminsd, &Assembler::pminsd>( 32741cb0ef41Sopenharmony_ci this, dst, lhs, rhs, base::Optional<CpuFeature>(SSE4_1)); 32751cb0ef41Sopenharmony_ci} 32761cb0ef41Sopenharmony_ci 32771cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32x4_min_u(LiftoffRegister dst, 32781cb0ef41Sopenharmony_ci LiftoffRegister lhs, 32791cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 32801cb0ef41Sopenharmony_ci liftoff::EmitSimdCommutativeBinOp<&Assembler::vpminud, &Assembler::pminud>( 32811cb0ef41Sopenharmony_ci this, dst, lhs, rhs, base::Optional<CpuFeature>(SSE4_1)); 32821cb0ef41Sopenharmony_ci} 32831cb0ef41Sopenharmony_ci 32841cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32x4_max_s(LiftoffRegister dst, 32851cb0ef41Sopenharmony_ci LiftoffRegister lhs, 32861cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 32871cb0ef41Sopenharmony_ci liftoff::EmitSimdCommutativeBinOp<&Assembler::vpmaxsd, &Assembler::pmaxsd>( 32881cb0ef41Sopenharmony_ci this, dst, lhs, rhs, base::Optional<CpuFeature>(SSE4_1)); 32891cb0ef41Sopenharmony_ci} 32901cb0ef41Sopenharmony_ci 32911cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32x4_max_u(LiftoffRegister dst, 32921cb0ef41Sopenharmony_ci LiftoffRegister lhs, 32931cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 32941cb0ef41Sopenharmony_ci liftoff::EmitSimdCommutativeBinOp<&Assembler::vpmaxud, &Assembler::pmaxud>( 32951cb0ef41Sopenharmony_ci this, dst, lhs, rhs, base::Optional<CpuFeature>(SSE4_1)); 32961cb0ef41Sopenharmony_ci} 32971cb0ef41Sopenharmony_ci 32981cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32x4_dot_i16x8_s(LiftoffRegister dst, 32991cb0ef41Sopenharmony_ci LiftoffRegister lhs, 33001cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 33011cb0ef41Sopenharmony_ci liftoff::EmitSimdCommutativeBinOp<&Assembler::vpmaddwd, &Assembler::pmaddwd>( 33021cb0ef41Sopenharmony_ci this, dst, lhs, rhs); 33031cb0ef41Sopenharmony_ci} 33041cb0ef41Sopenharmony_ci 33051cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32x4_extadd_pairwise_i16x8_s(LiftoffRegister dst, 33061cb0ef41Sopenharmony_ci LiftoffRegister src) { 33071cb0ef41Sopenharmony_ci I32x4ExtAddPairwiseI16x8S(dst.fp(), src.fp(), kScratchRegister); 33081cb0ef41Sopenharmony_ci} 33091cb0ef41Sopenharmony_ci 33101cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32x4_extadd_pairwise_i16x8_u(LiftoffRegister dst, 33111cb0ef41Sopenharmony_ci LiftoffRegister src) { 33121cb0ef41Sopenharmony_ci I32x4ExtAddPairwiseI16x8U(dst.fp(), src.fp(), kScratchDoubleReg); 33131cb0ef41Sopenharmony_ci} 33141cb0ef41Sopenharmony_ci 33151cb0ef41Sopenharmony_cinamespace liftoff { 33161cb0ef41Sopenharmony_ci// Helper function to check for register aliasing, AVX support, and moves 33171cb0ef41Sopenharmony_ci// registers around before calling the actual macro-assembler function. 33181cb0ef41Sopenharmony_ciinline void I32x4ExtMulHelper(LiftoffAssembler* assm, XMMRegister dst, 33191cb0ef41Sopenharmony_ci XMMRegister src1, XMMRegister src2, bool low, 33201cb0ef41Sopenharmony_ci bool is_signed) { 33211cb0ef41Sopenharmony_ci // I32x4ExtMul requires dst == src1 if AVX is not supported. 33221cb0ef41Sopenharmony_ci if (CpuFeatures::IsSupported(AVX) || dst == src1) { 33231cb0ef41Sopenharmony_ci assm->I32x4ExtMul(dst, src1, src2, kScratchDoubleReg, low, is_signed); 33241cb0ef41Sopenharmony_ci } else if (dst != src2) { 33251cb0ef41Sopenharmony_ci // dst != src1 && dst != src2 33261cb0ef41Sopenharmony_ci assm->movaps(dst, src1); 33271cb0ef41Sopenharmony_ci assm->I32x4ExtMul(dst, dst, src2, kScratchDoubleReg, low, is_signed); 33281cb0ef41Sopenharmony_ci } else { 33291cb0ef41Sopenharmony_ci // dst == src2 33301cb0ef41Sopenharmony_ci // Extended multiplication is commutative, 33311cb0ef41Sopenharmony_ci assm->movaps(dst, src2); 33321cb0ef41Sopenharmony_ci assm->I32x4ExtMul(dst, dst, src1, kScratchDoubleReg, low, is_signed); 33331cb0ef41Sopenharmony_ci } 33341cb0ef41Sopenharmony_ci} 33351cb0ef41Sopenharmony_ci} // namespace liftoff 33361cb0ef41Sopenharmony_ci 33371cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32x4_extmul_low_i16x8_s(LiftoffRegister dst, 33381cb0ef41Sopenharmony_ci LiftoffRegister src1, 33391cb0ef41Sopenharmony_ci LiftoffRegister src2) { 33401cb0ef41Sopenharmony_ci liftoff::I32x4ExtMulHelper(this, dst.fp(), src1.fp(), src2.fp(), /*low=*/true, 33411cb0ef41Sopenharmony_ci /*is_signed=*/true); 33421cb0ef41Sopenharmony_ci} 33431cb0ef41Sopenharmony_ci 33441cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32x4_extmul_low_i16x8_u(LiftoffRegister dst, 33451cb0ef41Sopenharmony_ci LiftoffRegister src1, 33461cb0ef41Sopenharmony_ci LiftoffRegister src2) { 33471cb0ef41Sopenharmony_ci liftoff::I32x4ExtMulHelper(this, dst.fp(), src1.fp(), src2.fp(), /*low=*/true, 33481cb0ef41Sopenharmony_ci /*is_signed=*/false); 33491cb0ef41Sopenharmony_ci} 33501cb0ef41Sopenharmony_ci 33511cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32x4_extmul_high_i16x8_s(LiftoffRegister dst, 33521cb0ef41Sopenharmony_ci LiftoffRegister src1, 33531cb0ef41Sopenharmony_ci LiftoffRegister src2) { 33541cb0ef41Sopenharmony_ci liftoff::I32x4ExtMulHelper(this, dst.fp(), src1.fp(), src2.fp(), 33551cb0ef41Sopenharmony_ci /*low=*/false, 33561cb0ef41Sopenharmony_ci /*is_signed=*/true); 33571cb0ef41Sopenharmony_ci} 33581cb0ef41Sopenharmony_ci 33591cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32x4_extmul_high_i16x8_u(LiftoffRegister dst, 33601cb0ef41Sopenharmony_ci LiftoffRegister src1, 33611cb0ef41Sopenharmony_ci LiftoffRegister src2) { 33621cb0ef41Sopenharmony_ci liftoff::I32x4ExtMulHelper(this, dst.fp(), src1.fp(), src2.fp(), 33631cb0ef41Sopenharmony_ci /*low=*/false, 33641cb0ef41Sopenharmony_ci /*is_signed=*/false); 33651cb0ef41Sopenharmony_ci} 33661cb0ef41Sopenharmony_ci 33671cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i64x2_neg(LiftoffRegister dst, 33681cb0ef41Sopenharmony_ci LiftoffRegister src) { 33691cb0ef41Sopenharmony_ci I64x2Neg(dst.fp(), src.fp(), kScratchDoubleReg); 33701cb0ef41Sopenharmony_ci} 33711cb0ef41Sopenharmony_ci 33721cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i64x2_alltrue(LiftoffRegister dst, 33731cb0ef41Sopenharmony_ci LiftoffRegister src) { 33741cb0ef41Sopenharmony_ci liftoff::EmitAllTrue<&TurboAssembler::Pcmpeqq>(this, dst, src, SSE4_1); 33751cb0ef41Sopenharmony_ci} 33761cb0ef41Sopenharmony_ci 33771cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i64x2_shl(LiftoffRegister dst, LiftoffRegister lhs, 33781cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 33791cb0ef41Sopenharmony_ci liftoff::EmitSimdShiftOp<&Assembler::vpsllq, &Assembler::psllq, 6>(this, dst, 33801cb0ef41Sopenharmony_ci lhs, rhs); 33811cb0ef41Sopenharmony_ci} 33821cb0ef41Sopenharmony_ci 33831cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i64x2_shli(LiftoffRegister dst, LiftoffRegister lhs, 33841cb0ef41Sopenharmony_ci int32_t rhs) { 33851cb0ef41Sopenharmony_ci liftoff::EmitSimdShiftOpImm<&Assembler::vpsllq, &Assembler::psllq, 6>( 33861cb0ef41Sopenharmony_ci this, dst, lhs, rhs); 33871cb0ef41Sopenharmony_ci} 33881cb0ef41Sopenharmony_ci 33891cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i64x2_shr_s(LiftoffRegister dst, 33901cb0ef41Sopenharmony_ci LiftoffRegister lhs, 33911cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 33921cb0ef41Sopenharmony_ci I64x2ShrS(dst.fp(), lhs.fp(), rhs.gp(), kScratchDoubleReg, 33931cb0ef41Sopenharmony_ci liftoff::kScratchDoubleReg2, kScratchRegister); 33941cb0ef41Sopenharmony_ci} 33951cb0ef41Sopenharmony_ci 33961cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i64x2_shri_s(LiftoffRegister dst, 33971cb0ef41Sopenharmony_ci LiftoffRegister lhs, int32_t rhs) { 33981cb0ef41Sopenharmony_ci I64x2ShrS(dst.fp(), lhs.fp(), rhs & 0x3F, kScratchDoubleReg); 33991cb0ef41Sopenharmony_ci} 34001cb0ef41Sopenharmony_ci 34011cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i64x2_shr_u(LiftoffRegister dst, 34021cb0ef41Sopenharmony_ci LiftoffRegister lhs, 34031cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 34041cb0ef41Sopenharmony_ci liftoff::EmitSimdShiftOp<&Assembler::vpsrlq, &Assembler::psrlq, 6>(this, dst, 34051cb0ef41Sopenharmony_ci lhs, rhs); 34061cb0ef41Sopenharmony_ci} 34071cb0ef41Sopenharmony_ci 34081cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i64x2_shri_u(LiftoffRegister dst, 34091cb0ef41Sopenharmony_ci LiftoffRegister lhs, int32_t rhs) { 34101cb0ef41Sopenharmony_ci liftoff::EmitSimdShiftOpImm<&Assembler::vpsrlq, &Assembler::psrlq, 6>( 34111cb0ef41Sopenharmony_ci this, dst, lhs, rhs); 34121cb0ef41Sopenharmony_ci} 34131cb0ef41Sopenharmony_ci 34141cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i64x2_add(LiftoffRegister dst, LiftoffRegister lhs, 34151cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 34161cb0ef41Sopenharmony_ci liftoff::EmitSimdCommutativeBinOp<&Assembler::vpaddq, &Assembler::paddq>( 34171cb0ef41Sopenharmony_ci this, dst, lhs, rhs); 34181cb0ef41Sopenharmony_ci} 34191cb0ef41Sopenharmony_ci 34201cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i64x2_sub(LiftoffRegister dst, LiftoffRegister lhs, 34211cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 34221cb0ef41Sopenharmony_ci liftoff::EmitSimdNonCommutativeBinOp<&Assembler::vpsubq, &Assembler::psubq>( 34231cb0ef41Sopenharmony_ci this, dst, lhs, rhs); 34241cb0ef41Sopenharmony_ci} 34251cb0ef41Sopenharmony_ci 34261cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i64x2_mul(LiftoffRegister dst, LiftoffRegister lhs, 34271cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 34281cb0ef41Sopenharmony_ci static constexpr RegClass tmp_rc = reg_class_for(kS128); 34291cb0ef41Sopenharmony_ci LiftoffRegister tmp1 = 34301cb0ef41Sopenharmony_ci GetUnusedRegister(tmp_rc, LiftoffRegList{dst, lhs, rhs}); 34311cb0ef41Sopenharmony_ci LiftoffRegister tmp2 = 34321cb0ef41Sopenharmony_ci GetUnusedRegister(tmp_rc, LiftoffRegList{dst, lhs, rhs, tmp1}); 34331cb0ef41Sopenharmony_ci I64x2Mul(dst.fp(), lhs.fp(), rhs.fp(), tmp1.fp(), tmp2.fp()); 34341cb0ef41Sopenharmony_ci} 34351cb0ef41Sopenharmony_ci 34361cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i64x2_extmul_low_i32x4_s(LiftoffRegister dst, 34371cb0ef41Sopenharmony_ci LiftoffRegister src1, 34381cb0ef41Sopenharmony_ci LiftoffRegister src2) { 34391cb0ef41Sopenharmony_ci I64x2ExtMul(dst.fp(), src1.fp(), src2.fp(), kScratchDoubleReg, /*low=*/true, 34401cb0ef41Sopenharmony_ci /*is_signed=*/true); 34411cb0ef41Sopenharmony_ci} 34421cb0ef41Sopenharmony_ci 34431cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i64x2_extmul_low_i32x4_u(LiftoffRegister dst, 34441cb0ef41Sopenharmony_ci LiftoffRegister src1, 34451cb0ef41Sopenharmony_ci LiftoffRegister src2) { 34461cb0ef41Sopenharmony_ci I64x2ExtMul(dst.fp(), src1.fp(), src2.fp(), kScratchDoubleReg, /*low=*/true, 34471cb0ef41Sopenharmony_ci /*is_signed=*/false); 34481cb0ef41Sopenharmony_ci} 34491cb0ef41Sopenharmony_ci 34501cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i64x2_extmul_high_i32x4_s(LiftoffRegister dst, 34511cb0ef41Sopenharmony_ci LiftoffRegister src1, 34521cb0ef41Sopenharmony_ci LiftoffRegister src2) { 34531cb0ef41Sopenharmony_ci I64x2ExtMul(dst.fp(), src1.fp(), src2.fp(), kScratchDoubleReg, /*low=*/false, 34541cb0ef41Sopenharmony_ci /*is_signed=*/true); 34551cb0ef41Sopenharmony_ci} 34561cb0ef41Sopenharmony_ci 34571cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i64x2_extmul_high_i32x4_u(LiftoffRegister dst, 34581cb0ef41Sopenharmony_ci LiftoffRegister src1, 34591cb0ef41Sopenharmony_ci LiftoffRegister src2) { 34601cb0ef41Sopenharmony_ci I64x2ExtMul(dst.fp(), src1.fp(), src2.fp(), kScratchDoubleReg, /*low=*/false, 34611cb0ef41Sopenharmony_ci /*is_signed=*/false); 34621cb0ef41Sopenharmony_ci} 34631cb0ef41Sopenharmony_ci 34641cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i64x2_bitmask(LiftoffRegister dst, 34651cb0ef41Sopenharmony_ci LiftoffRegister src) { 34661cb0ef41Sopenharmony_ci Movmskpd(dst.gp(), src.fp()); 34671cb0ef41Sopenharmony_ci} 34681cb0ef41Sopenharmony_ci 34691cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i64x2_sconvert_i32x4_low(LiftoffRegister dst, 34701cb0ef41Sopenharmony_ci LiftoffRegister src) { 34711cb0ef41Sopenharmony_ci Pmovsxdq(dst.fp(), src.fp()); 34721cb0ef41Sopenharmony_ci} 34731cb0ef41Sopenharmony_ci 34741cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i64x2_sconvert_i32x4_high(LiftoffRegister dst, 34751cb0ef41Sopenharmony_ci LiftoffRegister src) { 34761cb0ef41Sopenharmony_ci I64x2SConvertI32x4High(dst.fp(), src.fp()); 34771cb0ef41Sopenharmony_ci} 34781cb0ef41Sopenharmony_ci 34791cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i64x2_uconvert_i32x4_low(LiftoffRegister dst, 34801cb0ef41Sopenharmony_ci LiftoffRegister src) { 34811cb0ef41Sopenharmony_ci Pmovzxdq(dst.fp(), src.fp()); 34821cb0ef41Sopenharmony_ci} 34831cb0ef41Sopenharmony_ci 34841cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i64x2_uconvert_i32x4_high(LiftoffRegister dst, 34851cb0ef41Sopenharmony_ci LiftoffRegister src) { 34861cb0ef41Sopenharmony_ci I64x2UConvertI32x4High(dst.fp(), src.fp(), kScratchDoubleReg); 34871cb0ef41Sopenharmony_ci} 34881cb0ef41Sopenharmony_ci 34891cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_f32x4_abs(LiftoffRegister dst, 34901cb0ef41Sopenharmony_ci LiftoffRegister src) { 34911cb0ef41Sopenharmony_ci Absps(dst.fp(), src.fp(), kScratchRegister); 34921cb0ef41Sopenharmony_ci} 34931cb0ef41Sopenharmony_ci 34941cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_f32x4_neg(LiftoffRegister dst, 34951cb0ef41Sopenharmony_ci LiftoffRegister src) { 34961cb0ef41Sopenharmony_ci Negps(dst.fp(), src.fp(), kScratchRegister); 34971cb0ef41Sopenharmony_ci} 34981cb0ef41Sopenharmony_ci 34991cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_f32x4_sqrt(LiftoffRegister dst, 35001cb0ef41Sopenharmony_ci LiftoffRegister src) { 35011cb0ef41Sopenharmony_ci Sqrtps(dst.fp(), src.fp()); 35021cb0ef41Sopenharmony_ci} 35031cb0ef41Sopenharmony_ci 35041cb0ef41Sopenharmony_cibool LiftoffAssembler::emit_f32x4_ceil(LiftoffRegister dst, 35051cb0ef41Sopenharmony_ci LiftoffRegister src) { 35061cb0ef41Sopenharmony_ci DCHECK(CpuFeatures::IsSupported(SSE4_1)); 35071cb0ef41Sopenharmony_ci Roundps(dst.fp(), src.fp(), kRoundUp); 35081cb0ef41Sopenharmony_ci return true; 35091cb0ef41Sopenharmony_ci} 35101cb0ef41Sopenharmony_ci 35111cb0ef41Sopenharmony_cibool LiftoffAssembler::emit_f32x4_floor(LiftoffRegister dst, 35121cb0ef41Sopenharmony_ci LiftoffRegister src) { 35131cb0ef41Sopenharmony_ci DCHECK(CpuFeatures::IsSupported(SSE4_1)); 35141cb0ef41Sopenharmony_ci Roundps(dst.fp(), src.fp(), kRoundDown); 35151cb0ef41Sopenharmony_ci return true; 35161cb0ef41Sopenharmony_ci} 35171cb0ef41Sopenharmony_ci 35181cb0ef41Sopenharmony_cibool LiftoffAssembler::emit_f32x4_trunc(LiftoffRegister dst, 35191cb0ef41Sopenharmony_ci LiftoffRegister src) { 35201cb0ef41Sopenharmony_ci DCHECK(CpuFeatures::IsSupported(SSE4_1)); 35211cb0ef41Sopenharmony_ci Roundps(dst.fp(), src.fp(), kRoundToZero); 35221cb0ef41Sopenharmony_ci return true; 35231cb0ef41Sopenharmony_ci} 35241cb0ef41Sopenharmony_ci 35251cb0ef41Sopenharmony_cibool LiftoffAssembler::emit_f32x4_nearest_int(LiftoffRegister dst, 35261cb0ef41Sopenharmony_ci LiftoffRegister src) { 35271cb0ef41Sopenharmony_ci DCHECK(CpuFeatures::IsSupported(SSE4_1)); 35281cb0ef41Sopenharmony_ci Roundps(dst.fp(), src.fp(), kRoundToNearest); 35291cb0ef41Sopenharmony_ci return true; 35301cb0ef41Sopenharmony_ci} 35311cb0ef41Sopenharmony_ci 35321cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_f32x4_add(LiftoffRegister dst, LiftoffRegister lhs, 35331cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 35341cb0ef41Sopenharmony_ci liftoff::EmitSimdCommutativeBinOp<&Assembler::vaddps, &Assembler::addps>( 35351cb0ef41Sopenharmony_ci this, dst, lhs, rhs); 35361cb0ef41Sopenharmony_ci} 35371cb0ef41Sopenharmony_ci 35381cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_f32x4_sub(LiftoffRegister dst, LiftoffRegister lhs, 35391cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 35401cb0ef41Sopenharmony_ci liftoff::EmitSimdNonCommutativeBinOp<&Assembler::vsubps, &Assembler::subps>( 35411cb0ef41Sopenharmony_ci this, dst, lhs, rhs); 35421cb0ef41Sopenharmony_ci} 35431cb0ef41Sopenharmony_ci 35441cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_f32x4_mul(LiftoffRegister dst, LiftoffRegister lhs, 35451cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 35461cb0ef41Sopenharmony_ci liftoff::EmitSimdCommutativeBinOp<&Assembler::vmulps, &Assembler::mulps>( 35471cb0ef41Sopenharmony_ci this, dst, lhs, rhs); 35481cb0ef41Sopenharmony_ci} 35491cb0ef41Sopenharmony_ci 35501cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_f32x4_div(LiftoffRegister dst, LiftoffRegister lhs, 35511cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 35521cb0ef41Sopenharmony_ci liftoff::EmitSimdNonCommutativeBinOp<&Assembler::vdivps, &Assembler::divps>( 35531cb0ef41Sopenharmony_ci this, dst, lhs, rhs); 35541cb0ef41Sopenharmony_ci} 35551cb0ef41Sopenharmony_ci 35561cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_f32x4_min(LiftoffRegister dst, LiftoffRegister lhs, 35571cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 35581cb0ef41Sopenharmony_ci F32x4Min(dst.fp(), lhs.fp(), rhs.fp(), kScratchDoubleReg); 35591cb0ef41Sopenharmony_ci} 35601cb0ef41Sopenharmony_ci 35611cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_f32x4_max(LiftoffRegister dst, LiftoffRegister lhs, 35621cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 35631cb0ef41Sopenharmony_ci F32x4Max(dst.fp(), lhs.fp(), rhs.fp(), kScratchDoubleReg); 35641cb0ef41Sopenharmony_ci} 35651cb0ef41Sopenharmony_ci 35661cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_f32x4_pmin(LiftoffRegister dst, LiftoffRegister lhs, 35671cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 35681cb0ef41Sopenharmony_ci // Due to the way minps works, pmin(a, b) = minps(b, a). 35691cb0ef41Sopenharmony_ci liftoff::EmitSimdNonCommutativeBinOp<&Assembler::vminps, &Assembler::minps>( 35701cb0ef41Sopenharmony_ci this, dst, rhs, lhs); 35711cb0ef41Sopenharmony_ci} 35721cb0ef41Sopenharmony_ci 35731cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_f32x4_pmax(LiftoffRegister dst, LiftoffRegister lhs, 35741cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 35751cb0ef41Sopenharmony_ci // Due to the way maxps works, pmax(a, b) = maxps(b, a). 35761cb0ef41Sopenharmony_ci liftoff::EmitSimdNonCommutativeBinOp<&Assembler::vmaxps, &Assembler::maxps>( 35771cb0ef41Sopenharmony_ci this, dst, rhs, lhs); 35781cb0ef41Sopenharmony_ci} 35791cb0ef41Sopenharmony_ci 35801cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_f64x2_abs(LiftoffRegister dst, 35811cb0ef41Sopenharmony_ci LiftoffRegister src) { 35821cb0ef41Sopenharmony_ci Abspd(dst.fp(), src.fp(), kScratchRegister); 35831cb0ef41Sopenharmony_ci} 35841cb0ef41Sopenharmony_ci 35851cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_f64x2_neg(LiftoffRegister dst, 35861cb0ef41Sopenharmony_ci LiftoffRegister src) { 35871cb0ef41Sopenharmony_ci Negpd(dst.fp(), src.fp(), kScratchRegister); 35881cb0ef41Sopenharmony_ci} 35891cb0ef41Sopenharmony_ci 35901cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_f64x2_sqrt(LiftoffRegister dst, 35911cb0ef41Sopenharmony_ci LiftoffRegister src) { 35921cb0ef41Sopenharmony_ci Sqrtpd(dst.fp(), src.fp()); 35931cb0ef41Sopenharmony_ci} 35941cb0ef41Sopenharmony_ci 35951cb0ef41Sopenharmony_cibool LiftoffAssembler::emit_f64x2_ceil(LiftoffRegister dst, 35961cb0ef41Sopenharmony_ci LiftoffRegister src) { 35971cb0ef41Sopenharmony_ci DCHECK(CpuFeatures::IsSupported(SSE4_1)); 35981cb0ef41Sopenharmony_ci Roundpd(dst.fp(), src.fp(), kRoundUp); 35991cb0ef41Sopenharmony_ci return true; 36001cb0ef41Sopenharmony_ci} 36011cb0ef41Sopenharmony_ci 36021cb0ef41Sopenharmony_cibool LiftoffAssembler::emit_f64x2_floor(LiftoffRegister dst, 36031cb0ef41Sopenharmony_ci LiftoffRegister src) { 36041cb0ef41Sopenharmony_ci DCHECK(CpuFeatures::IsSupported(SSE4_1)); 36051cb0ef41Sopenharmony_ci Roundpd(dst.fp(), src.fp(), kRoundDown); 36061cb0ef41Sopenharmony_ci return true; 36071cb0ef41Sopenharmony_ci} 36081cb0ef41Sopenharmony_ci 36091cb0ef41Sopenharmony_cibool LiftoffAssembler::emit_f64x2_trunc(LiftoffRegister dst, 36101cb0ef41Sopenharmony_ci LiftoffRegister src) { 36111cb0ef41Sopenharmony_ci DCHECK(CpuFeatures::IsSupported(SSE4_1)); 36121cb0ef41Sopenharmony_ci Roundpd(dst.fp(), src.fp(), kRoundToZero); 36131cb0ef41Sopenharmony_ci return true; 36141cb0ef41Sopenharmony_ci} 36151cb0ef41Sopenharmony_ci 36161cb0ef41Sopenharmony_cibool LiftoffAssembler::emit_f64x2_nearest_int(LiftoffRegister dst, 36171cb0ef41Sopenharmony_ci LiftoffRegister src) { 36181cb0ef41Sopenharmony_ci DCHECK(CpuFeatures::IsSupported(SSE4_1)); 36191cb0ef41Sopenharmony_ci Roundpd(dst.fp(), src.fp(), kRoundToNearest); 36201cb0ef41Sopenharmony_ci return true; 36211cb0ef41Sopenharmony_ci} 36221cb0ef41Sopenharmony_ci 36231cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_f64x2_add(LiftoffRegister dst, LiftoffRegister lhs, 36241cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 36251cb0ef41Sopenharmony_ci liftoff::EmitSimdCommutativeBinOp<&Assembler::vaddpd, &Assembler::addpd>( 36261cb0ef41Sopenharmony_ci this, dst, lhs, rhs); 36271cb0ef41Sopenharmony_ci} 36281cb0ef41Sopenharmony_ci 36291cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_f64x2_sub(LiftoffRegister dst, LiftoffRegister lhs, 36301cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 36311cb0ef41Sopenharmony_ci liftoff::EmitSimdNonCommutativeBinOp<&Assembler::vsubpd, &Assembler::subpd>( 36321cb0ef41Sopenharmony_ci this, dst, lhs, rhs); 36331cb0ef41Sopenharmony_ci} 36341cb0ef41Sopenharmony_ci 36351cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_f64x2_mul(LiftoffRegister dst, LiftoffRegister lhs, 36361cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 36371cb0ef41Sopenharmony_ci liftoff::EmitSimdCommutativeBinOp<&Assembler::vmulpd, &Assembler::mulpd>( 36381cb0ef41Sopenharmony_ci this, dst, lhs, rhs); 36391cb0ef41Sopenharmony_ci} 36401cb0ef41Sopenharmony_ci 36411cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_f64x2_div(LiftoffRegister dst, LiftoffRegister lhs, 36421cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 36431cb0ef41Sopenharmony_ci liftoff::EmitSimdNonCommutativeBinOp<&Assembler::vdivpd, &Assembler::divpd>( 36441cb0ef41Sopenharmony_ci this, dst, lhs, rhs); 36451cb0ef41Sopenharmony_ci} 36461cb0ef41Sopenharmony_ci 36471cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_f64x2_min(LiftoffRegister dst, LiftoffRegister lhs, 36481cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 36491cb0ef41Sopenharmony_ci F64x2Min(dst.fp(), lhs.fp(), rhs.fp(), kScratchDoubleReg); 36501cb0ef41Sopenharmony_ci} 36511cb0ef41Sopenharmony_ci 36521cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_f64x2_max(LiftoffRegister dst, LiftoffRegister lhs, 36531cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 36541cb0ef41Sopenharmony_ci F64x2Max(dst.fp(), lhs.fp(), rhs.fp(), kScratchDoubleReg); 36551cb0ef41Sopenharmony_ci} 36561cb0ef41Sopenharmony_ci 36571cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_f64x2_pmin(LiftoffRegister dst, LiftoffRegister lhs, 36581cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 36591cb0ef41Sopenharmony_ci // Due to the way minpd works, pmin(a, b) = minpd(b, a). 36601cb0ef41Sopenharmony_ci liftoff::EmitSimdNonCommutativeBinOp<&Assembler::vminpd, &Assembler::minpd>( 36611cb0ef41Sopenharmony_ci this, dst, rhs, lhs); 36621cb0ef41Sopenharmony_ci} 36631cb0ef41Sopenharmony_ci 36641cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_f64x2_pmax(LiftoffRegister dst, LiftoffRegister lhs, 36651cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 36661cb0ef41Sopenharmony_ci // Due to the way maxpd works, pmax(a, b) = maxpd(b, a). 36671cb0ef41Sopenharmony_ci liftoff::EmitSimdNonCommutativeBinOp<&Assembler::vmaxpd, &Assembler::maxpd>( 36681cb0ef41Sopenharmony_ci this, dst, rhs, lhs); 36691cb0ef41Sopenharmony_ci} 36701cb0ef41Sopenharmony_ci 36711cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_f64x2_convert_low_i32x4_s(LiftoffRegister dst, 36721cb0ef41Sopenharmony_ci LiftoffRegister src) { 36731cb0ef41Sopenharmony_ci Cvtdq2pd(dst.fp(), src.fp()); 36741cb0ef41Sopenharmony_ci} 36751cb0ef41Sopenharmony_ci 36761cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_f64x2_convert_low_i32x4_u(LiftoffRegister dst, 36771cb0ef41Sopenharmony_ci LiftoffRegister src) { 36781cb0ef41Sopenharmony_ci F64x2ConvertLowI32x4U(dst.fp(), src.fp(), kScratchRegister); 36791cb0ef41Sopenharmony_ci} 36801cb0ef41Sopenharmony_ci 36811cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_f64x2_promote_low_f32x4(LiftoffRegister dst, 36821cb0ef41Sopenharmony_ci LiftoffRegister src) { 36831cb0ef41Sopenharmony_ci Cvtps2pd(dst.fp(), src.fp()); 36841cb0ef41Sopenharmony_ci} 36851cb0ef41Sopenharmony_ci 36861cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32x4_sconvert_f32x4(LiftoffRegister dst, 36871cb0ef41Sopenharmony_ci LiftoffRegister src) { 36881cb0ef41Sopenharmony_ci I32x4SConvertF32x4(dst.fp(), src.fp(), kScratchDoubleReg, kScratchRegister); 36891cb0ef41Sopenharmony_ci} 36901cb0ef41Sopenharmony_ci 36911cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32x4_uconvert_f32x4(LiftoffRegister dst, 36921cb0ef41Sopenharmony_ci LiftoffRegister src) { 36931cb0ef41Sopenharmony_ci // NAN->0, negative->0. 36941cb0ef41Sopenharmony_ci Pxor(kScratchDoubleReg, kScratchDoubleReg); 36951cb0ef41Sopenharmony_ci if (CpuFeatures::IsSupported(AVX)) { 36961cb0ef41Sopenharmony_ci CpuFeatureScope scope(this, AVX); 36971cb0ef41Sopenharmony_ci vmaxps(dst.fp(), src.fp(), kScratchDoubleReg); 36981cb0ef41Sopenharmony_ci } else { 36991cb0ef41Sopenharmony_ci if (dst.fp() != src.fp()) movaps(dst.fp(), src.fp()); 37001cb0ef41Sopenharmony_ci maxps(dst.fp(), kScratchDoubleReg); 37011cb0ef41Sopenharmony_ci } 37021cb0ef41Sopenharmony_ci // scratch: float representation of max_signed. 37031cb0ef41Sopenharmony_ci Pcmpeqd(kScratchDoubleReg, kScratchDoubleReg); 37041cb0ef41Sopenharmony_ci Psrld(kScratchDoubleReg, uint8_t{1}); // 0x7fffffff 37051cb0ef41Sopenharmony_ci Cvtdq2ps(kScratchDoubleReg, kScratchDoubleReg); // 0x4f000000 37061cb0ef41Sopenharmony_ci // scratch2: convert (src-max_signed). 37071cb0ef41Sopenharmony_ci // Set positive overflow lanes to 0x7FFFFFFF. 37081cb0ef41Sopenharmony_ci // Set negative lanes to 0. 37091cb0ef41Sopenharmony_ci if (CpuFeatures::IsSupported(AVX)) { 37101cb0ef41Sopenharmony_ci CpuFeatureScope scope(this, AVX); 37111cb0ef41Sopenharmony_ci vsubps(liftoff::kScratchDoubleReg2, dst.fp(), kScratchDoubleReg); 37121cb0ef41Sopenharmony_ci } else { 37131cb0ef41Sopenharmony_ci movaps(liftoff::kScratchDoubleReg2, dst.fp()); 37141cb0ef41Sopenharmony_ci subps(liftoff::kScratchDoubleReg2, kScratchDoubleReg); 37151cb0ef41Sopenharmony_ci } 37161cb0ef41Sopenharmony_ci Cmpleps(kScratchDoubleReg, liftoff::kScratchDoubleReg2); 37171cb0ef41Sopenharmony_ci Cvttps2dq(liftoff::kScratchDoubleReg2, liftoff::kScratchDoubleReg2); 37181cb0ef41Sopenharmony_ci Pxor(liftoff::kScratchDoubleReg2, kScratchDoubleReg); 37191cb0ef41Sopenharmony_ci Pxor(kScratchDoubleReg, kScratchDoubleReg); 37201cb0ef41Sopenharmony_ci Pmaxsd(liftoff::kScratchDoubleReg2, kScratchDoubleReg); 37211cb0ef41Sopenharmony_ci // Convert to int. Overflow lanes above max_signed will be 0x80000000. 37221cb0ef41Sopenharmony_ci Cvttps2dq(dst.fp(), dst.fp()); 37231cb0ef41Sopenharmony_ci // Add (src-max_signed) for overflow lanes. 37241cb0ef41Sopenharmony_ci Paddd(dst.fp(), liftoff::kScratchDoubleReg2); 37251cb0ef41Sopenharmony_ci} 37261cb0ef41Sopenharmony_ci 37271cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_f32x4_sconvert_i32x4(LiftoffRegister dst, 37281cb0ef41Sopenharmony_ci LiftoffRegister src) { 37291cb0ef41Sopenharmony_ci Cvtdq2ps(dst.fp(), src.fp()); 37301cb0ef41Sopenharmony_ci} 37311cb0ef41Sopenharmony_ci 37321cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_f32x4_uconvert_i32x4(LiftoffRegister dst, 37331cb0ef41Sopenharmony_ci LiftoffRegister src) { 37341cb0ef41Sopenharmony_ci Pxor(kScratchDoubleReg, kScratchDoubleReg); // Zeros. 37351cb0ef41Sopenharmony_ci Pblendw(kScratchDoubleReg, src.fp(), uint8_t{0x55}); // Get lo 16 bits. 37361cb0ef41Sopenharmony_ci if (CpuFeatures::IsSupported(AVX)) { 37371cb0ef41Sopenharmony_ci CpuFeatureScope scope(this, AVX); 37381cb0ef41Sopenharmony_ci vpsubd(dst.fp(), src.fp(), kScratchDoubleReg); // Get hi 16 bits. 37391cb0ef41Sopenharmony_ci } else { 37401cb0ef41Sopenharmony_ci if (dst.fp() != src.fp()) movaps(dst.fp(), src.fp()); 37411cb0ef41Sopenharmony_ci psubd(dst.fp(), kScratchDoubleReg); 37421cb0ef41Sopenharmony_ci } 37431cb0ef41Sopenharmony_ci Cvtdq2ps(kScratchDoubleReg, kScratchDoubleReg); // Convert lo exactly. 37441cb0ef41Sopenharmony_ci Psrld(dst.fp(), byte{1}); // Divide by 2 to get in unsigned range. 37451cb0ef41Sopenharmony_ci Cvtdq2ps(dst.fp(), dst.fp()); // Convert hi, exactly. 37461cb0ef41Sopenharmony_ci Addps(dst.fp(), dst.fp()); // Double hi, exactly. 37471cb0ef41Sopenharmony_ci Addps(dst.fp(), kScratchDoubleReg); // Add hi and lo, may round. 37481cb0ef41Sopenharmony_ci} 37491cb0ef41Sopenharmony_ci 37501cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_f32x4_demote_f64x2_zero(LiftoffRegister dst, 37511cb0ef41Sopenharmony_ci LiftoffRegister src) { 37521cb0ef41Sopenharmony_ci Cvtpd2ps(dst.fp(), src.fp()); 37531cb0ef41Sopenharmony_ci} 37541cb0ef41Sopenharmony_ci 37551cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i8x16_sconvert_i16x8(LiftoffRegister dst, 37561cb0ef41Sopenharmony_ci LiftoffRegister lhs, 37571cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 37581cb0ef41Sopenharmony_ci liftoff::EmitSimdNonCommutativeBinOp<&Assembler::vpacksswb, 37591cb0ef41Sopenharmony_ci &Assembler::packsswb>(this, dst, lhs, 37601cb0ef41Sopenharmony_ci rhs); 37611cb0ef41Sopenharmony_ci} 37621cb0ef41Sopenharmony_ci 37631cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i8x16_uconvert_i16x8(LiftoffRegister dst, 37641cb0ef41Sopenharmony_ci LiftoffRegister lhs, 37651cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 37661cb0ef41Sopenharmony_ci liftoff::EmitSimdNonCommutativeBinOp<&Assembler::vpackuswb, 37671cb0ef41Sopenharmony_ci &Assembler::packuswb>(this, dst, lhs, 37681cb0ef41Sopenharmony_ci rhs); 37691cb0ef41Sopenharmony_ci} 37701cb0ef41Sopenharmony_ci 37711cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i16x8_sconvert_i32x4(LiftoffRegister dst, 37721cb0ef41Sopenharmony_ci LiftoffRegister lhs, 37731cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 37741cb0ef41Sopenharmony_ci liftoff::EmitSimdNonCommutativeBinOp<&Assembler::vpackssdw, 37751cb0ef41Sopenharmony_ci &Assembler::packssdw>(this, dst, lhs, 37761cb0ef41Sopenharmony_ci rhs); 37771cb0ef41Sopenharmony_ci} 37781cb0ef41Sopenharmony_ci 37791cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i16x8_uconvert_i32x4(LiftoffRegister dst, 37801cb0ef41Sopenharmony_ci LiftoffRegister lhs, 37811cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 37821cb0ef41Sopenharmony_ci liftoff::EmitSimdNonCommutativeBinOp<&Assembler::vpackusdw, 37831cb0ef41Sopenharmony_ci &Assembler::packusdw>(this, dst, lhs, 37841cb0ef41Sopenharmony_ci rhs, SSE4_1); 37851cb0ef41Sopenharmony_ci} 37861cb0ef41Sopenharmony_ci 37871cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i16x8_sconvert_i8x16_low(LiftoffRegister dst, 37881cb0ef41Sopenharmony_ci LiftoffRegister src) { 37891cb0ef41Sopenharmony_ci Pmovsxbw(dst.fp(), src.fp()); 37901cb0ef41Sopenharmony_ci} 37911cb0ef41Sopenharmony_ci 37921cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i16x8_sconvert_i8x16_high(LiftoffRegister dst, 37931cb0ef41Sopenharmony_ci LiftoffRegister src) { 37941cb0ef41Sopenharmony_ci I16x8SConvertI8x16High(dst.fp(), src.fp()); 37951cb0ef41Sopenharmony_ci} 37961cb0ef41Sopenharmony_ci 37971cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i16x8_uconvert_i8x16_low(LiftoffRegister dst, 37981cb0ef41Sopenharmony_ci LiftoffRegister src) { 37991cb0ef41Sopenharmony_ci Pmovzxbw(dst.fp(), src.fp()); 38001cb0ef41Sopenharmony_ci} 38011cb0ef41Sopenharmony_ci 38021cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i16x8_uconvert_i8x16_high(LiftoffRegister dst, 38031cb0ef41Sopenharmony_ci LiftoffRegister src) { 38041cb0ef41Sopenharmony_ci I16x8UConvertI8x16High(dst.fp(), src.fp(), kScratchDoubleReg); 38051cb0ef41Sopenharmony_ci} 38061cb0ef41Sopenharmony_ci 38071cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32x4_sconvert_i16x8_low(LiftoffRegister dst, 38081cb0ef41Sopenharmony_ci LiftoffRegister src) { 38091cb0ef41Sopenharmony_ci Pmovsxwd(dst.fp(), src.fp()); 38101cb0ef41Sopenharmony_ci} 38111cb0ef41Sopenharmony_ci 38121cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32x4_sconvert_i16x8_high(LiftoffRegister dst, 38131cb0ef41Sopenharmony_ci LiftoffRegister src) { 38141cb0ef41Sopenharmony_ci I32x4SConvertI16x8High(dst.fp(), src.fp()); 38151cb0ef41Sopenharmony_ci} 38161cb0ef41Sopenharmony_ci 38171cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32x4_uconvert_i16x8_low(LiftoffRegister dst, 38181cb0ef41Sopenharmony_ci LiftoffRegister src) { 38191cb0ef41Sopenharmony_ci Pmovzxwd(dst.fp(), src.fp()); 38201cb0ef41Sopenharmony_ci} 38211cb0ef41Sopenharmony_ci 38221cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32x4_uconvert_i16x8_high(LiftoffRegister dst, 38231cb0ef41Sopenharmony_ci LiftoffRegister src) { 38241cb0ef41Sopenharmony_ci I32x4UConvertI16x8High(dst.fp(), src.fp(), kScratchDoubleReg); 38251cb0ef41Sopenharmony_ci} 38261cb0ef41Sopenharmony_ci 38271cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32x4_trunc_sat_f64x2_s_zero(LiftoffRegister dst, 38281cb0ef41Sopenharmony_ci LiftoffRegister src) { 38291cb0ef41Sopenharmony_ci I32x4TruncSatF64x2SZero(dst.fp(), src.fp(), kScratchDoubleReg, 38301cb0ef41Sopenharmony_ci kScratchRegister); 38311cb0ef41Sopenharmony_ci} 38321cb0ef41Sopenharmony_ci 38331cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32x4_trunc_sat_f64x2_u_zero(LiftoffRegister dst, 38341cb0ef41Sopenharmony_ci LiftoffRegister src) { 38351cb0ef41Sopenharmony_ci I32x4TruncSatF64x2UZero(dst.fp(), src.fp(), kScratchDoubleReg, 38361cb0ef41Sopenharmony_ci kScratchRegister); 38371cb0ef41Sopenharmony_ci} 38381cb0ef41Sopenharmony_ci 38391cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_s128_and_not(LiftoffRegister dst, 38401cb0ef41Sopenharmony_ci LiftoffRegister lhs, 38411cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 38421cb0ef41Sopenharmony_ci liftoff::EmitSimdNonCommutativeBinOp<&Assembler::vandnps, &Assembler::andnps>( 38431cb0ef41Sopenharmony_ci this, dst, rhs, lhs); 38441cb0ef41Sopenharmony_ci} 38451cb0ef41Sopenharmony_ci 38461cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i8x16_rounding_average_u(LiftoffRegister dst, 38471cb0ef41Sopenharmony_ci LiftoffRegister lhs, 38481cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 38491cb0ef41Sopenharmony_ci liftoff::EmitSimdCommutativeBinOp<&Assembler::vpavgb, &Assembler::pavgb>( 38501cb0ef41Sopenharmony_ci this, dst, lhs, rhs); 38511cb0ef41Sopenharmony_ci} 38521cb0ef41Sopenharmony_ci 38531cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i16x8_rounding_average_u(LiftoffRegister dst, 38541cb0ef41Sopenharmony_ci LiftoffRegister lhs, 38551cb0ef41Sopenharmony_ci LiftoffRegister rhs) { 38561cb0ef41Sopenharmony_ci liftoff::EmitSimdCommutativeBinOp<&Assembler::vpavgw, &Assembler::pavgw>( 38571cb0ef41Sopenharmony_ci this, dst, lhs, rhs); 38581cb0ef41Sopenharmony_ci} 38591cb0ef41Sopenharmony_ci 38601cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i8x16_abs(LiftoffRegister dst, 38611cb0ef41Sopenharmony_ci LiftoffRegister src) { 38621cb0ef41Sopenharmony_ci Pabsb(dst.fp(), src.fp()); 38631cb0ef41Sopenharmony_ci} 38641cb0ef41Sopenharmony_ci 38651cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i16x8_abs(LiftoffRegister dst, 38661cb0ef41Sopenharmony_ci LiftoffRegister src) { 38671cb0ef41Sopenharmony_ci Pabsw(dst.fp(), src.fp()); 38681cb0ef41Sopenharmony_ci} 38691cb0ef41Sopenharmony_ci 38701cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32x4_abs(LiftoffRegister dst, 38711cb0ef41Sopenharmony_ci LiftoffRegister src) { 38721cb0ef41Sopenharmony_ci Pabsd(dst.fp(), src.fp()); 38731cb0ef41Sopenharmony_ci} 38741cb0ef41Sopenharmony_ci 38751cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i64x2_abs(LiftoffRegister dst, 38761cb0ef41Sopenharmony_ci LiftoffRegister src) { 38771cb0ef41Sopenharmony_ci I64x2Abs(dst.fp(), src.fp(), kScratchDoubleReg); 38781cb0ef41Sopenharmony_ci} 38791cb0ef41Sopenharmony_ci 38801cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i8x16_extract_lane_s(LiftoffRegister dst, 38811cb0ef41Sopenharmony_ci LiftoffRegister lhs, 38821cb0ef41Sopenharmony_ci uint8_t imm_lane_idx) { 38831cb0ef41Sopenharmony_ci Pextrb(dst.gp(), lhs.fp(), imm_lane_idx); 38841cb0ef41Sopenharmony_ci movsxbl(dst.gp(), dst.gp()); 38851cb0ef41Sopenharmony_ci} 38861cb0ef41Sopenharmony_ci 38871cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i8x16_extract_lane_u(LiftoffRegister dst, 38881cb0ef41Sopenharmony_ci LiftoffRegister lhs, 38891cb0ef41Sopenharmony_ci uint8_t imm_lane_idx) { 38901cb0ef41Sopenharmony_ci Pextrb(dst.gp(), lhs.fp(), imm_lane_idx); 38911cb0ef41Sopenharmony_ci} 38921cb0ef41Sopenharmony_ci 38931cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i16x8_extract_lane_s(LiftoffRegister dst, 38941cb0ef41Sopenharmony_ci LiftoffRegister lhs, 38951cb0ef41Sopenharmony_ci uint8_t imm_lane_idx) { 38961cb0ef41Sopenharmony_ci Pextrw(dst.gp(), lhs.fp(), imm_lane_idx); 38971cb0ef41Sopenharmony_ci movsxwl(dst.gp(), dst.gp()); 38981cb0ef41Sopenharmony_ci} 38991cb0ef41Sopenharmony_ci 39001cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i16x8_extract_lane_u(LiftoffRegister dst, 39011cb0ef41Sopenharmony_ci LiftoffRegister lhs, 39021cb0ef41Sopenharmony_ci uint8_t imm_lane_idx) { 39031cb0ef41Sopenharmony_ci Pextrw(dst.gp(), lhs.fp(), imm_lane_idx); 39041cb0ef41Sopenharmony_ci} 39051cb0ef41Sopenharmony_ci 39061cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32x4_extract_lane(LiftoffRegister dst, 39071cb0ef41Sopenharmony_ci LiftoffRegister lhs, 39081cb0ef41Sopenharmony_ci uint8_t imm_lane_idx) { 39091cb0ef41Sopenharmony_ci Pextrd(dst.gp(), lhs.fp(), imm_lane_idx); 39101cb0ef41Sopenharmony_ci} 39111cb0ef41Sopenharmony_ci 39121cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i64x2_extract_lane(LiftoffRegister dst, 39131cb0ef41Sopenharmony_ci LiftoffRegister lhs, 39141cb0ef41Sopenharmony_ci uint8_t imm_lane_idx) { 39151cb0ef41Sopenharmony_ci Pextrq(dst.gp(), lhs.fp(), static_cast<int8_t>(imm_lane_idx)); 39161cb0ef41Sopenharmony_ci} 39171cb0ef41Sopenharmony_ci 39181cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_f32x4_extract_lane(LiftoffRegister dst, 39191cb0ef41Sopenharmony_ci LiftoffRegister lhs, 39201cb0ef41Sopenharmony_ci uint8_t imm_lane_idx) { 39211cb0ef41Sopenharmony_ci F32x4ExtractLane(dst.fp(), lhs.fp(), imm_lane_idx); 39221cb0ef41Sopenharmony_ci} 39231cb0ef41Sopenharmony_ci 39241cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_f64x2_extract_lane(LiftoffRegister dst, 39251cb0ef41Sopenharmony_ci LiftoffRegister lhs, 39261cb0ef41Sopenharmony_ci uint8_t imm_lane_idx) { 39271cb0ef41Sopenharmony_ci F64x2ExtractLane(dst.fp(), lhs.fp(), imm_lane_idx); 39281cb0ef41Sopenharmony_ci} 39291cb0ef41Sopenharmony_ci 39301cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i8x16_replace_lane(LiftoffRegister dst, 39311cb0ef41Sopenharmony_ci LiftoffRegister src1, 39321cb0ef41Sopenharmony_ci LiftoffRegister src2, 39331cb0ef41Sopenharmony_ci uint8_t imm_lane_idx) { 39341cb0ef41Sopenharmony_ci if (CpuFeatures::IsSupported(AVX)) { 39351cb0ef41Sopenharmony_ci CpuFeatureScope scope(this, AVX); 39361cb0ef41Sopenharmony_ci vpinsrb(dst.fp(), src1.fp(), src2.gp(), imm_lane_idx); 39371cb0ef41Sopenharmony_ci } else { 39381cb0ef41Sopenharmony_ci CpuFeatureScope scope(this, SSE4_1); 39391cb0ef41Sopenharmony_ci if (dst.fp() != src1.fp()) movaps(dst.fp(), src1.fp()); 39401cb0ef41Sopenharmony_ci pinsrb(dst.fp(), src2.gp(), imm_lane_idx); 39411cb0ef41Sopenharmony_ci } 39421cb0ef41Sopenharmony_ci} 39431cb0ef41Sopenharmony_ci 39441cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i16x8_replace_lane(LiftoffRegister dst, 39451cb0ef41Sopenharmony_ci LiftoffRegister src1, 39461cb0ef41Sopenharmony_ci LiftoffRegister src2, 39471cb0ef41Sopenharmony_ci uint8_t imm_lane_idx) { 39481cb0ef41Sopenharmony_ci if (CpuFeatures::IsSupported(AVX)) { 39491cb0ef41Sopenharmony_ci CpuFeatureScope scope(this, AVX); 39501cb0ef41Sopenharmony_ci vpinsrw(dst.fp(), src1.fp(), src2.gp(), imm_lane_idx); 39511cb0ef41Sopenharmony_ci } else { 39521cb0ef41Sopenharmony_ci if (dst.fp() != src1.fp()) movaps(dst.fp(), src1.fp()); 39531cb0ef41Sopenharmony_ci pinsrw(dst.fp(), src2.gp(), imm_lane_idx); 39541cb0ef41Sopenharmony_ci } 39551cb0ef41Sopenharmony_ci} 39561cb0ef41Sopenharmony_ci 39571cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i32x4_replace_lane(LiftoffRegister dst, 39581cb0ef41Sopenharmony_ci LiftoffRegister src1, 39591cb0ef41Sopenharmony_ci LiftoffRegister src2, 39601cb0ef41Sopenharmony_ci uint8_t imm_lane_idx) { 39611cb0ef41Sopenharmony_ci if (CpuFeatures::IsSupported(AVX)) { 39621cb0ef41Sopenharmony_ci CpuFeatureScope scope(this, AVX); 39631cb0ef41Sopenharmony_ci vpinsrd(dst.fp(), src1.fp(), src2.gp(), imm_lane_idx); 39641cb0ef41Sopenharmony_ci } else { 39651cb0ef41Sopenharmony_ci CpuFeatureScope scope(this, SSE4_1); 39661cb0ef41Sopenharmony_ci if (dst.fp() != src1.fp()) movaps(dst.fp(), src1.fp()); 39671cb0ef41Sopenharmony_ci pinsrd(dst.fp(), src2.gp(), imm_lane_idx); 39681cb0ef41Sopenharmony_ci } 39691cb0ef41Sopenharmony_ci} 39701cb0ef41Sopenharmony_ci 39711cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_i64x2_replace_lane(LiftoffRegister dst, 39721cb0ef41Sopenharmony_ci LiftoffRegister src1, 39731cb0ef41Sopenharmony_ci LiftoffRegister src2, 39741cb0ef41Sopenharmony_ci uint8_t imm_lane_idx) { 39751cb0ef41Sopenharmony_ci if (CpuFeatures::IsSupported(AVX)) { 39761cb0ef41Sopenharmony_ci CpuFeatureScope scope(this, AVX); 39771cb0ef41Sopenharmony_ci vpinsrq(dst.fp(), src1.fp(), src2.gp(), imm_lane_idx); 39781cb0ef41Sopenharmony_ci } else { 39791cb0ef41Sopenharmony_ci CpuFeatureScope scope(this, SSE4_1); 39801cb0ef41Sopenharmony_ci if (dst.fp() != src1.fp()) movaps(dst.fp(), src1.fp()); 39811cb0ef41Sopenharmony_ci pinsrq(dst.fp(), src2.gp(), imm_lane_idx); 39821cb0ef41Sopenharmony_ci } 39831cb0ef41Sopenharmony_ci} 39841cb0ef41Sopenharmony_ci 39851cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_f32x4_replace_lane(LiftoffRegister dst, 39861cb0ef41Sopenharmony_ci LiftoffRegister src1, 39871cb0ef41Sopenharmony_ci LiftoffRegister src2, 39881cb0ef41Sopenharmony_ci uint8_t imm_lane_idx) { 39891cb0ef41Sopenharmony_ci if (CpuFeatures::IsSupported(AVX)) { 39901cb0ef41Sopenharmony_ci CpuFeatureScope scope(this, AVX); 39911cb0ef41Sopenharmony_ci vinsertps(dst.fp(), src1.fp(), src2.fp(), (imm_lane_idx << 4) & 0x30); 39921cb0ef41Sopenharmony_ci } else { 39931cb0ef41Sopenharmony_ci CpuFeatureScope scope(this, SSE4_1); 39941cb0ef41Sopenharmony_ci if (dst.fp() != src1.fp()) movaps(dst.fp(), src1.fp()); 39951cb0ef41Sopenharmony_ci insertps(dst.fp(), src2.fp(), (imm_lane_idx << 4) & 0x30); 39961cb0ef41Sopenharmony_ci } 39971cb0ef41Sopenharmony_ci} 39981cb0ef41Sopenharmony_ci 39991cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_f64x2_replace_lane(LiftoffRegister dst, 40001cb0ef41Sopenharmony_ci LiftoffRegister src1, 40011cb0ef41Sopenharmony_ci LiftoffRegister src2, 40021cb0ef41Sopenharmony_ci uint8_t imm_lane_idx) { 40031cb0ef41Sopenharmony_ci F64x2ReplaceLane(dst.fp(), src1.fp(), src2.fp(), imm_lane_idx); 40041cb0ef41Sopenharmony_ci} 40051cb0ef41Sopenharmony_ci 40061cb0ef41Sopenharmony_civoid LiftoffAssembler::StackCheck(Label* ool_code, Register limit_address) { 40071cb0ef41Sopenharmony_ci cmpq(rsp, Operand(limit_address, 0)); 40081cb0ef41Sopenharmony_ci j(below_equal, ool_code); 40091cb0ef41Sopenharmony_ci} 40101cb0ef41Sopenharmony_ci 40111cb0ef41Sopenharmony_civoid LiftoffAssembler::CallTrapCallbackForTesting() { 40121cb0ef41Sopenharmony_ci PrepareCallCFunction(0); 40131cb0ef41Sopenharmony_ci CallCFunction(ExternalReference::wasm_call_trap_callback_for_testing(), 0); 40141cb0ef41Sopenharmony_ci} 40151cb0ef41Sopenharmony_ci 40161cb0ef41Sopenharmony_civoid LiftoffAssembler::AssertUnreachable(AbortReason reason) { 40171cb0ef41Sopenharmony_ci TurboAssembler::AssertUnreachable(reason); 40181cb0ef41Sopenharmony_ci} 40191cb0ef41Sopenharmony_ci 40201cb0ef41Sopenharmony_civoid LiftoffAssembler::PushRegisters(LiftoffRegList regs) { 40211cb0ef41Sopenharmony_ci LiftoffRegList gp_regs = regs & kGpCacheRegList; 40221cb0ef41Sopenharmony_ci while (!gp_regs.is_empty()) { 40231cb0ef41Sopenharmony_ci LiftoffRegister reg = gp_regs.GetFirstRegSet(); 40241cb0ef41Sopenharmony_ci pushq(reg.gp()); 40251cb0ef41Sopenharmony_ci gp_regs.clear(reg); 40261cb0ef41Sopenharmony_ci } 40271cb0ef41Sopenharmony_ci LiftoffRegList fp_regs = regs & kFpCacheRegList; 40281cb0ef41Sopenharmony_ci unsigned num_fp_regs = fp_regs.GetNumRegsSet(); 40291cb0ef41Sopenharmony_ci if (num_fp_regs) { 40301cb0ef41Sopenharmony_ci AllocateStackSpace(num_fp_regs * kSimd128Size); 40311cb0ef41Sopenharmony_ci unsigned offset = 0; 40321cb0ef41Sopenharmony_ci while (!fp_regs.is_empty()) { 40331cb0ef41Sopenharmony_ci LiftoffRegister reg = fp_regs.GetFirstRegSet(); 40341cb0ef41Sopenharmony_ci Movdqu(Operand(rsp, offset), reg.fp()); 40351cb0ef41Sopenharmony_ci fp_regs.clear(reg); 40361cb0ef41Sopenharmony_ci offset += kSimd128Size; 40371cb0ef41Sopenharmony_ci } 40381cb0ef41Sopenharmony_ci DCHECK_EQ(offset, num_fp_regs * kSimd128Size); 40391cb0ef41Sopenharmony_ci } 40401cb0ef41Sopenharmony_ci} 40411cb0ef41Sopenharmony_ci 40421cb0ef41Sopenharmony_civoid LiftoffAssembler::PopRegisters(LiftoffRegList regs) { 40431cb0ef41Sopenharmony_ci LiftoffRegList fp_regs = regs & kFpCacheRegList; 40441cb0ef41Sopenharmony_ci unsigned fp_offset = 0; 40451cb0ef41Sopenharmony_ci while (!fp_regs.is_empty()) { 40461cb0ef41Sopenharmony_ci LiftoffRegister reg = fp_regs.GetFirstRegSet(); 40471cb0ef41Sopenharmony_ci Movdqu(reg.fp(), Operand(rsp, fp_offset)); 40481cb0ef41Sopenharmony_ci fp_regs.clear(reg); 40491cb0ef41Sopenharmony_ci fp_offset += kSimd128Size; 40501cb0ef41Sopenharmony_ci } 40511cb0ef41Sopenharmony_ci if (fp_offset) addq(rsp, Immediate(fp_offset)); 40521cb0ef41Sopenharmony_ci LiftoffRegList gp_regs = regs & kGpCacheRegList; 40531cb0ef41Sopenharmony_ci while (!gp_regs.is_empty()) { 40541cb0ef41Sopenharmony_ci LiftoffRegister reg = gp_regs.GetLastRegSet(); 40551cb0ef41Sopenharmony_ci popq(reg.gp()); 40561cb0ef41Sopenharmony_ci gp_regs.clear(reg); 40571cb0ef41Sopenharmony_ci } 40581cb0ef41Sopenharmony_ci} 40591cb0ef41Sopenharmony_ci 40601cb0ef41Sopenharmony_civoid LiftoffAssembler::RecordSpillsInSafepoint( 40611cb0ef41Sopenharmony_ci SafepointTableBuilder::Safepoint& safepoint, LiftoffRegList all_spills, 40621cb0ef41Sopenharmony_ci LiftoffRegList ref_spills, int spill_offset) { 40631cb0ef41Sopenharmony_ci int spill_space_size = 0; 40641cb0ef41Sopenharmony_ci while (!all_spills.is_empty()) { 40651cb0ef41Sopenharmony_ci LiftoffRegister reg = all_spills.GetFirstRegSet(); 40661cb0ef41Sopenharmony_ci if (ref_spills.has(reg)) { 40671cb0ef41Sopenharmony_ci safepoint.DefineTaggedStackSlot(spill_offset); 40681cb0ef41Sopenharmony_ci } 40691cb0ef41Sopenharmony_ci all_spills.clear(reg); 40701cb0ef41Sopenharmony_ci ++spill_offset; 40711cb0ef41Sopenharmony_ci spill_space_size += kSystemPointerSize; 40721cb0ef41Sopenharmony_ci } 40731cb0ef41Sopenharmony_ci // Record the number of additional spill slots. 40741cb0ef41Sopenharmony_ci RecordOolSpillSpaceSize(spill_space_size); 40751cb0ef41Sopenharmony_ci} 40761cb0ef41Sopenharmony_ci 40771cb0ef41Sopenharmony_civoid LiftoffAssembler::DropStackSlotsAndRet(uint32_t num_stack_slots) { 40781cb0ef41Sopenharmony_ci DCHECK_LT(num_stack_slots, 40791cb0ef41Sopenharmony_ci (1 << 16) / kSystemPointerSize); // 16 bit immediate 40801cb0ef41Sopenharmony_ci ret(static_cast<int>(num_stack_slots * kSystemPointerSize)); 40811cb0ef41Sopenharmony_ci} 40821cb0ef41Sopenharmony_ci 40831cb0ef41Sopenharmony_civoid LiftoffAssembler::CallC(const ValueKindSig* sig, 40841cb0ef41Sopenharmony_ci const LiftoffRegister* args, 40851cb0ef41Sopenharmony_ci const LiftoffRegister* rets, 40861cb0ef41Sopenharmony_ci ValueKind out_argument_kind, int stack_bytes, 40871cb0ef41Sopenharmony_ci ExternalReference ext_ref) { 40881cb0ef41Sopenharmony_ci AllocateStackSpace(stack_bytes); 40891cb0ef41Sopenharmony_ci 40901cb0ef41Sopenharmony_ci int arg_bytes = 0; 40911cb0ef41Sopenharmony_ci for (ValueKind param_kind : sig->parameters()) { 40921cb0ef41Sopenharmony_ci liftoff::Store(this, Operand(rsp, arg_bytes), *args++, param_kind); 40931cb0ef41Sopenharmony_ci arg_bytes += value_kind_size(param_kind); 40941cb0ef41Sopenharmony_ci } 40951cb0ef41Sopenharmony_ci DCHECK_LE(arg_bytes, stack_bytes); 40961cb0ef41Sopenharmony_ci 40971cb0ef41Sopenharmony_ci // Pass a pointer to the buffer with the arguments to the C function. 40981cb0ef41Sopenharmony_ci movq(arg_reg_1, rsp); 40991cb0ef41Sopenharmony_ci 41001cb0ef41Sopenharmony_ci constexpr int kNumCCallArgs = 1; 41011cb0ef41Sopenharmony_ci 41021cb0ef41Sopenharmony_ci // Now call the C function. 41031cb0ef41Sopenharmony_ci PrepareCallCFunction(kNumCCallArgs); 41041cb0ef41Sopenharmony_ci CallCFunction(ext_ref, kNumCCallArgs); 41051cb0ef41Sopenharmony_ci 41061cb0ef41Sopenharmony_ci // Move return value to the right register. 41071cb0ef41Sopenharmony_ci const LiftoffRegister* next_result_reg = rets; 41081cb0ef41Sopenharmony_ci if (sig->return_count() > 0) { 41091cb0ef41Sopenharmony_ci DCHECK_EQ(1, sig->return_count()); 41101cb0ef41Sopenharmony_ci constexpr Register kReturnReg = rax; 41111cb0ef41Sopenharmony_ci if (kReturnReg != next_result_reg->gp()) { 41121cb0ef41Sopenharmony_ci Move(*next_result_reg, LiftoffRegister(kReturnReg), sig->GetReturn(0)); 41131cb0ef41Sopenharmony_ci } 41141cb0ef41Sopenharmony_ci ++next_result_reg; 41151cb0ef41Sopenharmony_ci } 41161cb0ef41Sopenharmony_ci 41171cb0ef41Sopenharmony_ci // Load potential output value from the buffer on the stack. 41181cb0ef41Sopenharmony_ci if (out_argument_kind != kVoid) { 41191cb0ef41Sopenharmony_ci liftoff::Load(this, *next_result_reg, Operand(rsp, 0), out_argument_kind); 41201cb0ef41Sopenharmony_ci } 41211cb0ef41Sopenharmony_ci 41221cb0ef41Sopenharmony_ci addq(rsp, Immediate(stack_bytes)); 41231cb0ef41Sopenharmony_ci} 41241cb0ef41Sopenharmony_ci 41251cb0ef41Sopenharmony_civoid LiftoffAssembler::CallNativeWasmCode(Address addr) { 41261cb0ef41Sopenharmony_ci near_call(addr, RelocInfo::WASM_CALL); 41271cb0ef41Sopenharmony_ci} 41281cb0ef41Sopenharmony_ci 41291cb0ef41Sopenharmony_civoid LiftoffAssembler::TailCallNativeWasmCode(Address addr) { 41301cb0ef41Sopenharmony_ci near_jmp(addr, RelocInfo::WASM_CALL); 41311cb0ef41Sopenharmony_ci} 41321cb0ef41Sopenharmony_ci 41331cb0ef41Sopenharmony_civoid LiftoffAssembler::CallIndirect(const ValueKindSig* sig, 41341cb0ef41Sopenharmony_ci compiler::CallDescriptor* call_descriptor, 41351cb0ef41Sopenharmony_ci Register target) { 41361cb0ef41Sopenharmony_ci if (target == no_reg) { 41371cb0ef41Sopenharmony_ci popq(kScratchRegister); 41381cb0ef41Sopenharmony_ci target = kScratchRegister; 41391cb0ef41Sopenharmony_ci } 41401cb0ef41Sopenharmony_ci call(target); 41411cb0ef41Sopenharmony_ci} 41421cb0ef41Sopenharmony_ci 41431cb0ef41Sopenharmony_civoid LiftoffAssembler::TailCallIndirect(Register target) { 41441cb0ef41Sopenharmony_ci if (target == no_reg) { 41451cb0ef41Sopenharmony_ci popq(kScratchRegister); 41461cb0ef41Sopenharmony_ci target = kScratchRegister; 41471cb0ef41Sopenharmony_ci } 41481cb0ef41Sopenharmony_ci jmp(target); 41491cb0ef41Sopenharmony_ci} 41501cb0ef41Sopenharmony_ci 41511cb0ef41Sopenharmony_civoid LiftoffAssembler::CallRuntimeStub(WasmCode::RuntimeStubId sid) { 41521cb0ef41Sopenharmony_ci // A direct call to a wasm runtime stub defined in this module. 41531cb0ef41Sopenharmony_ci // Just encode the stub index. This will be patched at relocation. 41541cb0ef41Sopenharmony_ci near_call(static_cast<Address>(sid), RelocInfo::WASM_STUB_CALL); 41551cb0ef41Sopenharmony_ci} 41561cb0ef41Sopenharmony_ci 41571cb0ef41Sopenharmony_civoid LiftoffAssembler::AllocateStackSlot(Register addr, uint32_t size) { 41581cb0ef41Sopenharmony_ci AllocateStackSpace(size); 41591cb0ef41Sopenharmony_ci movq(addr, rsp); 41601cb0ef41Sopenharmony_ci} 41611cb0ef41Sopenharmony_ci 41621cb0ef41Sopenharmony_civoid LiftoffAssembler::DeallocateStackSlot(uint32_t size) { 41631cb0ef41Sopenharmony_ci addq(rsp, Immediate(size)); 41641cb0ef41Sopenharmony_ci} 41651cb0ef41Sopenharmony_ci 41661cb0ef41Sopenharmony_civoid LiftoffAssembler::MaybeOSR() { 41671cb0ef41Sopenharmony_ci cmpq(liftoff::GetOSRTargetSlot(), Immediate(0)); 41681cb0ef41Sopenharmony_ci j(not_equal, static_cast<Address>(WasmCode::kWasmOnStackReplace), 41691cb0ef41Sopenharmony_ci RelocInfo::WASM_STUB_CALL); 41701cb0ef41Sopenharmony_ci} 41711cb0ef41Sopenharmony_ci 41721cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_set_if_nan(Register dst, DoubleRegister src, 41731cb0ef41Sopenharmony_ci ValueKind kind) { 41741cb0ef41Sopenharmony_ci if (kind == kF32) { 41751cb0ef41Sopenharmony_ci Ucomiss(src, src); 41761cb0ef41Sopenharmony_ci } else { 41771cb0ef41Sopenharmony_ci DCHECK_EQ(kind, kF64); 41781cb0ef41Sopenharmony_ci Ucomisd(src, src); 41791cb0ef41Sopenharmony_ci } 41801cb0ef41Sopenharmony_ci Label ret; 41811cb0ef41Sopenharmony_ci j(parity_odd, &ret); 41821cb0ef41Sopenharmony_ci movl(Operand(dst, 0), Immediate(1)); 41831cb0ef41Sopenharmony_ci bind(&ret); 41841cb0ef41Sopenharmony_ci} 41851cb0ef41Sopenharmony_ci 41861cb0ef41Sopenharmony_civoid LiftoffAssembler::emit_s128_set_if_nan(Register dst, LiftoffRegister src, 41871cb0ef41Sopenharmony_ci Register tmp_gp, 41881cb0ef41Sopenharmony_ci LiftoffRegister tmp_s128, 41891cb0ef41Sopenharmony_ci ValueKind lane_kind) { 41901cb0ef41Sopenharmony_ci if (lane_kind == kF32) { 41911cb0ef41Sopenharmony_ci movaps(tmp_s128.fp(), src.fp()); 41921cb0ef41Sopenharmony_ci cmpunordps(tmp_s128.fp(), tmp_s128.fp()); 41931cb0ef41Sopenharmony_ci } else { 41941cb0ef41Sopenharmony_ci DCHECK_EQ(lane_kind, kF64); 41951cb0ef41Sopenharmony_ci movapd(tmp_s128.fp(), src.fp()); 41961cb0ef41Sopenharmony_ci cmpunordpd(tmp_s128.fp(), tmp_s128.fp()); 41971cb0ef41Sopenharmony_ci } 41981cb0ef41Sopenharmony_ci pmovmskb(tmp_gp, tmp_s128.fp()); 41991cb0ef41Sopenharmony_ci orl(Operand(dst, 0), tmp_gp); 42001cb0ef41Sopenharmony_ci} 42011cb0ef41Sopenharmony_ci 42021cb0ef41Sopenharmony_civoid LiftoffStackSlots::Construct(int param_slots) { 42031cb0ef41Sopenharmony_ci DCHECK_LT(0, slots_.size()); 42041cb0ef41Sopenharmony_ci SortInPushOrder(); 42051cb0ef41Sopenharmony_ci int last_stack_slot = param_slots; 42061cb0ef41Sopenharmony_ci for (auto& slot : slots_) { 42071cb0ef41Sopenharmony_ci const int stack_slot = slot.dst_slot_; 42081cb0ef41Sopenharmony_ci int stack_decrement = (last_stack_slot - stack_slot) * kSystemPointerSize; 42091cb0ef41Sopenharmony_ci last_stack_slot = stack_slot; 42101cb0ef41Sopenharmony_ci const LiftoffAssembler::VarState& src = slot.src_; 42111cb0ef41Sopenharmony_ci DCHECK_LT(0, stack_decrement); 42121cb0ef41Sopenharmony_ci switch (src.loc()) { 42131cb0ef41Sopenharmony_ci case LiftoffAssembler::VarState::kStack: 42141cb0ef41Sopenharmony_ci if (src.kind() == kI32) { 42151cb0ef41Sopenharmony_ci asm_->AllocateStackSpace(stack_decrement - kSystemPointerSize); 42161cb0ef41Sopenharmony_ci // Load i32 values to a register first to ensure they are zero 42171cb0ef41Sopenharmony_ci // extended. 42181cb0ef41Sopenharmony_ci asm_->movl(kScratchRegister, liftoff::GetStackSlot(slot.src_offset_)); 42191cb0ef41Sopenharmony_ci asm_->pushq(kScratchRegister); 42201cb0ef41Sopenharmony_ci } else if (src.kind() == kS128) { 42211cb0ef41Sopenharmony_ci asm_->AllocateStackSpace(stack_decrement - kSimd128Size); 42221cb0ef41Sopenharmony_ci // Since offsets are subtracted from sp, we need a smaller offset to 42231cb0ef41Sopenharmony_ci // push the top of a s128 value. 42241cb0ef41Sopenharmony_ci asm_->pushq(liftoff::GetStackSlot(slot.src_offset_ - 8)); 42251cb0ef41Sopenharmony_ci asm_->pushq(liftoff::GetStackSlot(slot.src_offset_)); 42261cb0ef41Sopenharmony_ci } else { 42271cb0ef41Sopenharmony_ci asm_->AllocateStackSpace(stack_decrement - kSystemPointerSize); 42281cb0ef41Sopenharmony_ci // For all other types, just push the whole (8-byte) stack slot. 42291cb0ef41Sopenharmony_ci // This is also ok for f32 values (even though we copy 4 uninitialized 42301cb0ef41Sopenharmony_ci // bytes), because f32 and f64 values are clearly distinguished in 42311cb0ef41Sopenharmony_ci // Turbofan, so the uninitialized bytes are never accessed. 42321cb0ef41Sopenharmony_ci asm_->pushq(liftoff::GetStackSlot(slot.src_offset_)); 42331cb0ef41Sopenharmony_ci } 42341cb0ef41Sopenharmony_ci break; 42351cb0ef41Sopenharmony_ci case LiftoffAssembler::VarState::kRegister: { 42361cb0ef41Sopenharmony_ci int pushed = src.kind() == kS128 ? kSimd128Size : kSystemPointerSize; 42371cb0ef41Sopenharmony_ci liftoff::push(asm_, src.reg(), src.kind(), stack_decrement - pushed); 42381cb0ef41Sopenharmony_ci break; 42391cb0ef41Sopenharmony_ci } 42401cb0ef41Sopenharmony_ci case LiftoffAssembler::VarState::kIntConst: 42411cb0ef41Sopenharmony_ci asm_->AllocateStackSpace(stack_decrement - kSystemPointerSize); 42421cb0ef41Sopenharmony_ci asm_->pushq(Immediate(src.i32_const())); 42431cb0ef41Sopenharmony_ci break; 42441cb0ef41Sopenharmony_ci } 42451cb0ef41Sopenharmony_ci } 42461cb0ef41Sopenharmony_ci} 42471cb0ef41Sopenharmony_ci 42481cb0ef41Sopenharmony_ci#undef RETURN_FALSE_IF_MISSING_CPU_FEATURE 42491cb0ef41Sopenharmony_ci 42501cb0ef41Sopenharmony_ci} // namespace wasm 42511cb0ef41Sopenharmony_ci} // namespace internal 42521cb0ef41Sopenharmony_ci} // namespace v8 42531cb0ef41Sopenharmony_ci 42541cb0ef41Sopenharmony_ci#endif // V8_WASM_BASELINE_X64_LIFTOFF_ASSEMBLER_X64_H_ 4255