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