11cb0ef41Sopenharmony_ci// Copyright (c) 1994-2006 Sun Microsystems Inc.
21cb0ef41Sopenharmony_ci// All Rights Reserved.
31cb0ef41Sopenharmony_ci//
41cb0ef41Sopenharmony_ci// Redistribution and use in source and binary forms, with or without
51cb0ef41Sopenharmony_ci// modification, are permitted provided that the following conditions
61cb0ef41Sopenharmony_ci// are met:
71cb0ef41Sopenharmony_ci//
81cb0ef41Sopenharmony_ci// - Redistributions of source code must retain the above copyright notice,
91cb0ef41Sopenharmony_ci// this list of conditions and the following disclaimer.
101cb0ef41Sopenharmony_ci//
111cb0ef41Sopenharmony_ci// - Redistribution in binary form must reproduce the above copyright
121cb0ef41Sopenharmony_ci// notice, this list of conditions and the following disclaimer in the
131cb0ef41Sopenharmony_ci// documentation and/or other materials provided with the
141cb0ef41Sopenharmony_ci// distribution.
151cb0ef41Sopenharmony_ci//
161cb0ef41Sopenharmony_ci// - Neither the name of Sun Microsystems or the names of contributors may
171cb0ef41Sopenharmony_ci// be used to endorse or promote products derived from this software without
181cb0ef41Sopenharmony_ci// specific prior written permission.
191cb0ef41Sopenharmony_ci//
201cb0ef41Sopenharmony_ci// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
211cb0ef41Sopenharmony_ci// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
221cb0ef41Sopenharmony_ci// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
231cb0ef41Sopenharmony_ci// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
241cb0ef41Sopenharmony_ci// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
251cb0ef41Sopenharmony_ci// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
261cb0ef41Sopenharmony_ci// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
271cb0ef41Sopenharmony_ci// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
281cb0ef41Sopenharmony_ci// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
291cb0ef41Sopenharmony_ci// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
301cb0ef41Sopenharmony_ci// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
311cb0ef41Sopenharmony_ci// OF THE POSSIBILITY OF SUCH DAMAGE.
321cb0ef41Sopenharmony_ci
331cb0ef41Sopenharmony_ci// The original source code covered by the above license above has been
341cb0ef41Sopenharmony_ci// modified significantly by Google Inc.
351cb0ef41Sopenharmony_ci// Copyright 2012 the V8 project authors. All rights reserved.
361cb0ef41Sopenharmony_ci
371cb0ef41Sopenharmony_ci#include "src/codegen/arm/assembler-arm.h"
381cb0ef41Sopenharmony_ci
391cb0ef41Sopenharmony_ci#if V8_TARGET_ARCH_ARM
401cb0ef41Sopenharmony_ci
411cb0ef41Sopenharmony_ci#include "src/base/bits.h"
421cb0ef41Sopenharmony_ci#include "src/base/cpu.h"
431cb0ef41Sopenharmony_ci#include "src/base/overflowing-math.h"
441cb0ef41Sopenharmony_ci#include "src/codegen/arm/assembler-arm-inl.h"
451cb0ef41Sopenharmony_ci#include "src/codegen/assembler-inl.h"
461cb0ef41Sopenharmony_ci#include "src/codegen/machine-type.h"
471cb0ef41Sopenharmony_ci#include "src/codegen/macro-assembler.h"
481cb0ef41Sopenharmony_ci#include "src/codegen/string-constants.h"
491cb0ef41Sopenharmony_ci#include "src/deoptimizer/deoptimizer.h"
501cb0ef41Sopenharmony_ci#include "src/objects/objects-inl.h"
511cb0ef41Sopenharmony_ci
521cb0ef41Sopenharmony_cinamespace v8 {
531cb0ef41Sopenharmony_cinamespace internal {
541cb0ef41Sopenharmony_ci
551cb0ef41Sopenharmony_cistatic const unsigned kArmv6 = 0u;
561cb0ef41Sopenharmony_cistatic const unsigned kArmv7 = kArmv6 | (1u << ARMv7);
571cb0ef41Sopenharmony_cistatic const unsigned kArmv7WithSudiv = kArmv7 | (1u << ARMv7_SUDIV);
581cb0ef41Sopenharmony_cistatic const unsigned kArmv8 = kArmv7WithSudiv | (1u << ARMv8);
591cb0ef41Sopenharmony_ci
601cb0ef41Sopenharmony_cistatic unsigned CpuFeaturesFromCommandLine() {
611cb0ef41Sopenharmony_ci  unsigned result;
621cb0ef41Sopenharmony_ci  if (strcmp(FLAG_arm_arch, "armv8") == 0) {
631cb0ef41Sopenharmony_ci    result = kArmv8;
641cb0ef41Sopenharmony_ci  } else if (strcmp(FLAG_arm_arch, "armv7+sudiv") == 0) {
651cb0ef41Sopenharmony_ci    result = kArmv7WithSudiv;
661cb0ef41Sopenharmony_ci  } else if (strcmp(FLAG_arm_arch, "armv7") == 0) {
671cb0ef41Sopenharmony_ci    result = kArmv7;
681cb0ef41Sopenharmony_ci  } else if (strcmp(FLAG_arm_arch, "armv6") == 0) {
691cb0ef41Sopenharmony_ci    result = kArmv6;
701cb0ef41Sopenharmony_ci  } else {
711cb0ef41Sopenharmony_ci    fprintf(stderr, "Error: unrecognised value for --arm-arch ('%s').\n",
721cb0ef41Sopenharmony_ci            FLAG_arm_arch);
731cb0ef41Sopenharmony_ci    fprintf(stderr,
741cb0ef41Sopenharmony_ci            "Supported values are:  armv8\n"
751cb0ef41Sopenharmony_ci            "                       armv7+sudiv\n"
761cb0ef41Sopenharmony_ci            "                       armv7\n"
771cb0ef41Sopenharmony_ci            "                       armv6\n");
781cb0ef41Sopenharmony_ci    FATAL("arm-arch");
791cb0ef41Sopenharmony_ci  }
801cb0ef41Sopenharmony_ci
811cb0ef41Sopenharmony_ci  // If any of the old (deprecated) flags are specified, print a warning, but
821cb0ef41Sopenharmony_ci  // otherwise try to respect them for now.
831cb0ef41Sopenharmony_ci  // TODO(jbramley): When all the old bots have been updated, remove this.
841cb0ef41Sopenharmony_ci  if (FLAG_enable_armv7.has_value || FLAG_enable_vfp3.has_value ||
851cb0ef41Sopenharmony_ci      FLAG_enable_32dregs.has_value || FLAG_enable_neon.has_value ||
861cb0ef41Sopenharmony_ci      FLAG_enable_sudiv.has_value || FLAG_enable_armv8.has_value) {
871cb0ef41Sopenharmony_ci    // As an approximation of the old behaviour, set the default values from the
881cb0ef41Sopenharmony_ci    // arm_arch setting, then apply the flags over the top.
891cb0ef41Sopenharmony_ci    bool enable_armv7 = (result & (1u << ARMv7)) != 0;
901cb0ef41Sopenharmony_ci    bool enable_vfp3 = (result & (1u << ARMv7)) != 0;
911cb0ef41Sopenharmony_ci    bool enable_32dregs = (result & (1u << ARMv7)) != 0;
921cb0ef41Sopenharmony_ci    bool enable_neon = (result & (1u << ARMv7)) != 0;
931cb0ef41Sopenharmony_ci    bool enable_sudiv = (result & (1u << ARMv7_SUDIV)) != 0;
941cb0ef41Sopenharmony_ci    bool enable_armv8 = (result & (1u << ARMv8)) != 0;
951cb0ef41Sopenharmony_ci    if (FLAG_enable_armv7.has_value) {
961cb0ef41Sopenharmony_ci      fprintf(stderr,
971cb0ef41Sopenharmony_ci              "Warning: --enable_armv7 is deprecated. "
981cb0ef41Sopenharmony_ci              "Use --arm_arch instead.\n");
991cb0ef41Sopenharmony_ci      enable_armv7 = FLAG_enable_armv7.value;
1001cb0ef41Sopenharmony_ci    }
1011cb0ef41Sopenharmony_ci    if (FLAG_enable_vfp3.has_value) {
1021cb0ef41Sopenharmony_ci      fprintf(stderr,
1031cb0ef41Sopenharmony_ci              "Warning: --enable_vfp3 is deprecated. "
1041cb0ef41Sopenharmony_ci              "Use --arm_arch instead.\n");
1051cb0ef41Sopenharmony_ci      enable_vfp3 = FLAG_enable_vfp3.value;
1061cb0ef41Sopenharmony_ci    }
1071cb0ef41Sopenharmony_ci    if (FLAG_enable_32dregs.has_value) {
1081cb0ef41Sopenharmony_ci      fprintf(stderr,
1091cb0ef41Sopenharmony_ci              "Warning: --enable_32dregs is deprecated. "
1101cb0ef41Sopenharmony_ci              "Use --arm_arch instead.\n");
1111cb0ef41Sopenharmony_ci      enable_32dregs = FLAG_enable_32dregs.value;
1121cb0ef41Sopenharmony_ci    }
1131cb0ef41Sopenharmony_ci    if (FLAG_enable_neon.has_value) {
1141cb0ef41Sopenharmony_ci      fprintf(stderr,
1151cb0ef41Sopenharmony_ci              "Warning: --enable_neon is deprecated. "
1161cb0ef41Sopenharmony_ci              "Use --arm_arch instead.\n");
1171cb0ef41Sopenharmony_ci      enable_neon = FLAG_enable_neon.value;
1181cb0ef41Sopenharmony_ci    }
1191cb0ef41Sopenharmony_ci    if (FLAG_enable_sudiv.has_value) {
1201cb0ef41Sopenharmony_ci      fprintf(stderr,
1211cb0ef41Sopenharmony_ci              "Warning: --enable_sudiv is deprecated. "
1221cb0ef41Sopenharmony_ci              "Use --arm_arch instead.\n");
1231cb0ef41Sopenharmony_ci      enable_sudiv = FLAG_enable_sudiv.value;
1241cb0ef41Sopenharmony_ci    }
1251cb0ef41Sopenharmony_ci    if (FLAG_enable_armv8.has_value) {
1261cb0ef41Sopenharmony_ci      fprintf(stderr,
1271cb0ef41Sopenharmony_ci              "Warning: --enable_armv8 is deprecated. "
1281cb0ef41Sopenharmony_ci              "Use --arm_arch instead.\n");
1291cb0ef41Sopenharmony_ci      enable_armv8 = FLAG_enable_armv8.value;
1301cb0ef41Sopenharmony_ci    }
1311cb0ef41Sopenharmony_ci    // Emulate the old implications.
1321cb0ef41Sopenharmony_ci    if (enable_armv8) {
1331cb0ef41Sopenharmony_ci      enable_vfp3 = true;
1341cb0ef41Sopenharmony_ci      enable_neon = true;
1351cb0ef41Sopenharmony_ci      enable_32dregs = true;
1361cb0ef41Sopenharmony_ci      enable_sudiv = true;
1371cb0ef41Sopenharmony_ci    }
1381cb0ef41Sopenharmony_ci    // Select the best available configuration.
1391cb0ef41Sopenharmony_ci    if (enable_armv7 && enable_vfp3 && enable_32dregs && enable_neon) {
1401cb0ef41Sopenharmony_ci      if (enable_sudiv) {
1411cb0ef41Sopenharmony_ci        if (enable_armv8) {
1421cb0ef41Sopenharmony_ci          result = kArmv8;
1431cb0ef41Sopenharmony_ci        } else {
1441cb0ef41Sopenharmony_ci          result = kArmv7WithSudiv;
1451cb0ef41Sopenharmony_ci        }
1461cb0ef41Sopenharmony_ci      } else {
1471cb0ef41Sopenharmony_ci        result = kArmv7;
1481cb0ef41Sopenharmony_ci      }
1491cb0ef41Sopenharmony_ci    } else {
1501cb0ef41Sopenharmony_ci      result = kArmv6;
1511cb0ef41Sopenharmony_ci    }
1521cb0ef41Sopenharmony_ci  }
1531cb0ef41Sopenharmony_ci  return result;
1541cb0ef41Sopenharmony_ci}
1551cb0ef41Sopenharmony_ci
1561cb0ef41Sopenharmony_ci// Get the CPU features enabled by the build.
1571cb0ef41Sopenharmony_ci// For cross compilation the preprocessor symbols such as
1581cb0ef41Sopenharmony_ci// CAN_USE_ARMV7_INSTRUCTIONS and CAN_USE_VFP3_INSTRUCTIONS can be used to
1591cb0ef41Sopenharmony_ci// enable ARMv7 and VFPv3 instructions when building the snapshot. However,
1601cb0ef41Sopenharmony_ci// these flags should be consistent with a supported ARM configuration:
1611cb0ef41Sopenharmony_ci//  "armv6":       ARMv6 + VFPv2
1621cb0ef41Sopenharmony_ci//  "armv7":       ARMv7 + VFPv3-D32 + NEON
1631cb0ef41Sopenharmony_ci//  "armv7+sudiv": ARMv7 + VFPv4-D32 + NEON + SUDIV
1641cb0ef41Sopenharmony_ci//  "armv8":       ARMv8 (+ all of the above)
1651cb0ef41Sopenharmony_cistatic constexpr unsigned CpuFeaturesFromCompiler() {
1661cb0ef41Sopenharmony_ci// TODO(jbramley): Once the build flags are simplified, these tests should
1671cb0ef41Sopenharmony_ci// also be simplified.
1681cb0ef41Sopenharmony_ci
1691cb0ef41Sopenharmony_ci// Check *architectural* implications.
1701cb0ef41Sopenharmony_ci#if defined(CAN_USE_ARMV8_INSTRUCTIONS) && !defined(CAN_USE_ARMV7_INSTRUCTIONS)
1711cb0ef41Sopenharmony_ci#error "CAN_USE_ARMV8_INSTRUCTIONS should imply CAN_USE_ARMV7_INSTRUCTIONS"
1721cb0ef41Sopenharmony_ci#endif
1731cb0ef41Sopenharmony_ci#if defined(CAN_USE_ARMV8_INSTRUCTIONS) && !defined(CAN_USE_SUDIV)
1741cb0ef41Sopenharmony_ci#error "CAN_USE_ARMV8_INSTRUCTIONS should imply CAN_USE_SUDIV"
1751cb0ef41Sopenharmony_ci#endif
1761cb0ef41Sopenharmony_ci#if defined(CAN_USE_ARMV7_INSTRUCTIONS) != defined(CAN_USE_VFP3_INSTRUCTIONS)
1771cb0ef41Sopenharmony_ci// V8 requires VFP, and all ARMv7 devices with VFP have VFPv3. Similarly,
1781cb0ef41Sopenharmony_ci// VFPv3 isn't available before ARMv7.
1791cb0ef41Sopenharmony_ci#error "CAN_USE_ARMV7_INSTRUCTIONS should match CAN_USE_VFP3_INSTRUCTIONS"
1801cb0ef41Sopenharmony_ci#endif
1811cb0ef41Sopenharmony_ci#if defined(CAN_USE_NEON) && !defined(CAN_USE_ARMV7_INSTRUCTIONS)
1821cb0ef41Sopenharmony_ci#error "CAN_USE_NEON should imply CAN_USE_ARMV7_INSTRUCTIONS"
1831cb0ef41Sopenharmony_ci#endif
1841cb0ef41Sopenharmony_ci
1851cb0ef41Sopenharmony_ci// Find compiler-implied features.
1861cb0ef41Sopenharmony_ci#if defined(CAN_USE_ARMV8_INSTRUCTIONS) &&                           \
1871cb0ef41Sopenharmony_ci    defined(CAN_USE_ARMV7_INSTRUCTIONS) && defined(CAN_USE_SUDIV) && \
1881cb0ef41Sopenharmony_ci    defined(CAN_USE_NEON) && defined(CAN_USE_VFP3_INSTRUCTIONS)
1891cb0ef41Sopenharmony_ci  return kArmv8;
1901cb0ef41Sopenharmony_ci#elif defined(CAN_USE_ARMV7_INSTRUCTIONS) && defined(CAN_USE_SUDIV) && \
1911cb0ef41Sopenharmony_ci    defined(CAN_USE_NEON) && defined(CAN_USE_VFP3_INSTRUCTIONS)
1921cb0ef41Sopenharmony_ci  return kArmv7WithSudiv;
1931cb0ef41Sopenharmony_ci#elif defined(CAN_USE_ARMV7_INSTRUCTIONS) && defined(CAN_USE_NEON) && \
1941cb0ef41Sopenharmony_ci    defined(CAN_USE_VFP3_INSTRUCTIONS)
1951cb0ef41Sopenharmony_ci  return kArmv7;
1961cb0ef41Sopenharmony_ci#else
1971cb0ef41Sopenharmony_ci  return kArmv6;
1981cb0ef41Sopenharmony_ci#endif
1991cb0ef41Sopenharmony_ci}
2001cb0ef41Sopenharmony_ci
2011cb0ef41Sopenharmony_cibool CpuFeatures::SupportsWasmSimd128() { return IsSupported(NEON); }
2021cb0ef41Sopenharmony_ci
2031cb0ef41Sopenharmony_civoid CpuFeatures::ProbeImpl(bool cross_compile) {
2041cb0ef41Sopenharmony_ci  dcache_line_size_ = 64;
2051cb0ef41Sopenharmony_ci
2061cb0ef41Sopenharmony_ci  unsigned command_line = CpuFeaturesFromCommandLine();
2071cb0ef41Sopenharmony_ci  // Only use statically determined features for cross compile (snapshot).
2081cb0ef41Sopenharmony_ci  if (cross_compile) {
2091cb0ef41Sopenharmony_ci    supported_ |= command_line & CpuFeaturesFromCompiler();
2101cb0ef41Sopenharmony_ci    return;
2111cb0ef41Sopenharmony_ci  }
2121cb0ef41Sopenharmony_ci
2131cb0ef41Sopenharmony_ci#ifndef __arm__
2141cb0ef41Sopenharmony_ci  // For the simulator build, use whatever the flags specify.
2151cb0ef41Sopenharmony_ci  supported_ |= command_line;
2161cb0ef41Sopenharmony_ci
2171cb0ef41Sopenharmony_ci#else  // __arm__
2181cb0ef41Sopenharmony_ci  // Probe for additional features at runtime.
2191cb0ef41Sopenharmony_ci  base::CPU cpu;
2201cb0ef41Sopenharmony_ci  // Runtime detection is slightly fuzzy, and some inferences are necessary.
2211cb0ef41Sopenharmony_ci  unsigned runtime = kArmv6;
2221cb0ef41Sopenharmony_ci  // NEON and VFPv3 imply at least ARMv7-A.
2231cb0ef41Sopenharmony_ci  if (cpu.has_neon() && cpu.has_vfp3_d32()) {
2241cb0ef41Sopenharmony_ci    DCHECK(cpu.has_vfp3());
2251cb0ef41Sopenharmony_ci    runtime |= kArmv7;
2261cb0ef41Sopenharmony_ci    if (cpu.has_idiva()) {
2271cb0ef41Sopenharmony_ci      runtime |= kArmv7WithSudiv;
2281cb0ef41Sopenharmony_ci      if (cpu.architecture() >= 8) {
2291cb0ef41Sopenharmony_ci        runtime |= kArmv8;
2301cb0ef41Sopenharmony_ci      }
2311cb0ef41Sopenharmony_ci    }
2321cb0ef41Sopenharmony_ci  }
2331cb0ef41Sopenharmony_ci
2341cb0ef41Sopenharmony_ci  // Use the best of the features found by CPU detection and those inferred from
2351cb0ef41Sopenharmony_ci  // the build system. In both cases, restrict available features using the
2361cb0ef41Sopenharmony_ci  // command-line. Note that the command-line flags are very permissive (kArmv8)
2371cb0ef41Sopenharmony_ci  // by default.
2381cb0ef41Sopenharmony_ci  supported_ |= command_line & CpuFeaturesFromCompiler();
2391cb0ef41Sopenharmony_ci  supported_ |= command_line & runtime;
2401cb0ef41Sopenharmony_ci
2411cb0ef41Sopenharmony_ci  // Additional tuning options.
2421cb0ef41Sopenharmony_ci
2431cb0ef41Sopenharmony_ci  // ARM Cortex-A9 and Cortex-A5 have 32 byte cachelines.
2441cb0ef41Sopenharmony_ci  if (cpu.implementer() == base::CPU::kArm &&
2451cb0ef41Sopenharmony_ci      (cpu.part() == base::CPU::kArmCortexA5 ||
2461cb0ef41Sopenharmony_ci       cpu.part() == base::CPU::kArmCortexA9)) {
2471cb0ef41Sopenharmony_ci    dcache_line_size_ = 32;
2481cb0ef41Sopenharmony_ci  }
2491cb0ef41Sopenharmony_ci#endif
2501cb0ef41Sopenharmony_ci
2511cb0ef41Sopenharmony_ci  DCHECK_IMPLIES(IsSupported(ARMv7_SUDIV), IsSupported(ARMv7));
2521cb0ef41Sopenharmony_ci  DCHECK_IMPLIES(IsSupported(ARMv8), IsSupported(ARMv7_SUDIV));
2531cb0ef41Sopenharmony_ci
2541cb0ef41Sopenharmony_ci  // Set a static value on whether Simd is supported.
2551cb0ef41Sopenharmony_ci  // This variable is only used for certain archs to query SupportWasmSimd128()
2561cb0ef41Sopenharmony_ci  // at runtime in builtins using an extern ref. Other callers should use
2571cb0ef41Sopenharmony_ci  // CpuFeatures::SupportWasmSimd128().
2581cb0ef41Sopenharmony_ci  CpuFeatures::supports_wasm_simd_128_ = CpuFeatures::SupportsWasmSimd128();
2591cb0ef41Sopenharmony_ci}
2601cb0ef41Sopenharmony_ci
2611cb0ef41Sopenharmony_civoid CpuFeatures::PrintTarget() {
2621cb0ef41Sopenharmony_ci  const char* arm_arch = nullptr;
2631cb0ef41Sopenharmony_ci  const char* arm_target_type = "";
2641cb0ef41Sopenharmony_ci  const char* arm_no_probe = "";
2651cb0ef41Sopenharmony_ci  const char* arm_fpu = "";
2661cb0ef41Sopenharmony_ci  const char* arm_thumb = "";
2671cb0ef41Sopenharmony_ci  const char* arm_float_abi = nullptr;
2681cb0ef41Sopenharmony_ci
2691cb0ef41Sopenharmony_ci#if !defined __arm__
2701cb0ef41Sopenharmony_ci  arm_target_type = " simulator";
2711cb0ef41Sopenharmony_ci#endif
2721cb0ef41Sopenharmony_ci
2731cb0ef41Sopenharmony_ci#if defined ARM_TEST_NO_FEATURE_PROBE
2741cb0ef41Sopenharmony_ci  arm_no_probe = " noprobe";
2751cb0ef41Sopenharmony_ci#endif
2761cb0ef41Sopenharmony_ci
2771cb0ef41Sopenharmony_ci#if defined CAN_USE_ARMV8_INSTRUCTIONS
2781cb0ef41Sopenharmony_ci  arm_arch = "arm v8";
2791cb0ef41Sopenharmony_ci#elif defined CAN_USE_ARMV7_INSTRUCTIONS
2801cb0ef41Sopenharmony_ci  arm_arch = "arm v7";
2811cb0ef41Sopenharmony_ci#else
2821cb0ef41Sopenharmony_ci  arm_arch = "arm v6";
2831cb0ef41Sopenharmony_ci#endif
2841cb0ef41Sopenharmony_ci
2851cb0ef41Sopenharmony_ci#if defined CAN_USE_NEON
2861cb0ef41Sopenharmony_ci  arm_fpu = " neon";
2871cb0ef41Sopenharmony_ci#elif defined CAN_USE_VFP3_INSTRUCTIONS
2881cb0ef41Sopenharmony_ci#if defined CAN_USE_VFP32DREGS
2891cb0ef41Sopenharmony_ci  arm_fpu = " vfp3";
2901cb0ef41Sopenharmony_ci#else
2911cb0ef41Sopenharmony_ci  arm_fpu = " vfp3-d16";
2921cb0ef41Sopenharmony_ci#endif
2931cb0ef41Sopenharmony_ci#else
2941cb0ef41Sopenharmony_ci  arm_fpu = " vfp2";
2951cb0ef41Sopenharmony_ci#endif
2961cb0ef41Sopenharmony_ci
2971cb0ef41Sopenharmony_ci#ifdef __arm__
2981cb0ef41Sopenharmony_ci  arm_float_abi = base::OS::ArmUsingHardFloat() ? "hard" : "softfp";
2991cb0ef41Sopenharmony_ci#elif USE_EABI_HARDFLOAT
3001cb0ef41Sopenharmony_ci  arm_float_abi = "hard";
3011cb0ef41Sopenharmony_ci#else
3021cb0ef41Sopenharmony_ci  arm_float_abi = "softfp";
3031cb0ef41Sopenharmony_ci#endif
3041cb0ef41Sopenharmony_ci
3051cb0ef41Sopenharmony_ci#if defined __arm__ && (defined __thumb__) || (defined __thumb2__)
3061cb0ef41Sopenharmony_ci  arm_thumb = " thumb";
3071cb0ef41Sopenharmony_ci#endif
3081cb0ef41Sopenharmony_ci
3091cb0ef41Sopenharmony_ci  printf("target%s%s %s%s%s %s\n", arm_target_type, arm_no_probe, arm_arch,
3101cb0ef41Sopenharmony_ci         arm_fpu, arm_thumb, arm_float_abi);
3111cb0ef41Sopenharmony_ci}
3121cb0ef41Sopenharmony_ci
3131cb0ef41Sopenharmony_civoid CpuFeatures::PrintFeatures() {
3141cb0ef41Sopenharmony_ci  printf("ARMv8=%d ARMv7=%d VFPv3=%d VFP32DREGS=%d NEON=%d SUDIV=%d",
3151cb0ef41Sopenharmony_ci         CpuFeatures::IsSupported(ARMv8), CpuFeatures::IsSupported(ARMv7),
3161cb0ef41Sopenharmony_ci         CpuFeatures::IsSupported(VFPv3), CpuFeatures::IsSupported(VFP32DREGS),
3171cb0ef41Sopenharmony_ci         CpuFeatures::IsSupported(NEON), CpuFeatures::IsSupported(SUDIV));
3181cb0ef41Sopenharmony_ci#ifdef __arm__
3191cb0ef41Sopenharmony_ci  bool eabi_hardfloat = base::OS::ArmUsingHardFloat();
3201cb0ef41Sopenharmony_ci#elif USE_EABI_HARDFLOAT
3211cb0ef41Sopenharmony_ci  bool eabi_hardfloat = true;
3221cb0ef41Sopenharmony_ci#else
3231cb0ef41Sopenharmony_ci  bool eabi_hardfloat = false;
3241cb0ef41Sopenharmony_ci#endif
3251cb0ef41Sopenharmony_ci  printf(" USE_EABI_HARDFLOAT=%d\n", eabi_hardfloat);
3261cb0ef41Sopenharmony_ci}
3271cb0ef41Sopenharmony_ci
3281cb0ef41Sopenharmony_ci// -----------------------------------------------------------------------------
3291cb0ef41Sopenharmony_ci// Implementation of RelocInfo
3301cb0ef41Sopenharmony_ci
3311cb0ef41Sopenharmony_ci// static
3321cb0ef41Sopenharmony_ciconst int RelocInfo::kApplyMask =
3331cb0ef41Sopenharmony_ci    RelocInfo::ModeMask(RelocInfo::RELATIVE_CODE_TARGET);
3341cb0ef41Sopenharmony_ci
3351cb0ef41Sopenharmony_cibool RelocInfo::IsCodedSpecially() {
3361cb0ef41Sopenharmony_ci  // The deserializer needs to know whether a pointer is specially coded.  Being
3371cb0ef41Sopenharmony_ci  // specially coded on ARM means that it is a movw/movt instruction. We don't
3381cb0ef41Sopenharmony_ci  // generate those for relocatable pointers.
3391cb0ef41Sopenharmony_ci  return false;
3401cb0ef41Sopenharmony_ci}
3411cb0ef41Sopenharmony_ci
3421cb0ef41Sopenharmony_cibool RelocInfo::IsInConstantPool() {
3431cb0ef41Sopenharmony_ci  return Assembler::is_constant_pool_load(pc_);
3441cb0ef41Sopenharmony_ci}
3451cb0ef41Sopenharmony_ci
3461cb0ef41Sopenharmony_ciuint32_t RelocInfo::wasm_call_tag() const {
3471cb0ef41Sopenharmony_ci  DCHECK(rmode_ == WASM_CALL || rmode_ == WASM_STUB_CALL);
3481cb0ef41Sopenharmony_ci  return static_cast<uint32_t>(
3491cb0ef41Sopenharmony_ci      Assembler::target_address_at(pc_, constant_pool_));
3501cb0ef41Sopenharmony_ci}
3511cb0ef41Sopenharmony_ci
3521cb0ef41Sopenharmony_ci// -----------------------------------------------------------------------------
3531cb0ef41Sopenharmony_ci// Implementation of Operand and MemOperand
3541cb0ef41Sopenharmony_ci// See assembler-arm-inl.h for inlined constructors
3551cb0ef41Sopenharmony_ci
3561cb0ef41Sopenharmony_ciOperand::Operand(Handle<HeapObject> handle) {
3571cb0ef41Sopenharmony_ci  rm_ = no_reg;
3581cb0ef41Sopenharmony_ci  value_.immediate = static_cast<intptr_t>(handle.address());
3591cb0ef41Sopenharmony_ci  rmode_ = RelocInfo::FULL_EMBEDDED_OBJECT;
3601cb0ef41Sopenharmony_ci}
3611cb0ef41Sopenharmony_ci
3621cb0ef41Sopenharmony_ciOperand::Operand(Register rm, ShiftOp shift_op, int shift_imm) {
3631cb0ef41Sopenharmony_ci  DCHECK(is_uint5(shift_imm));
3641cb0ef41Sopenharmony_ci
3651cb0ef41Sopenharmony_ci  rm_ = rm;
3661cb0ef41Sopenharmony_ci  rs_ = no_reg;
3671cb0ef41Sopenharmony_ci  shift_op_ = shift_op;
3681cb0ef41Sopenharmony_ci  shift_imm_ = shift_imm & 31;
3691cb0ef41Sopenharmony_ci
3701cb0ef41Sopenharmony_ci  if ((shift_op == ROR) && (shift_imm == 0)) {
3711cb0ef41Sopenharmony_ci    // ROR #0 is functionally equivalent to LSL #0 and this allow us to encode
3721cb0ef41Sopenharmony_ci    // RRX as ROR #0 (See below).
3731cb0ef41Sopenharmony_ci    shift_op = LSL;
3741cb0ef41Sopenharmony_ci  } else if (shift_op == RRX) {
3751cb0ef41Sopenharmony_ci    // encoded as ROR with shift_imm == 0
3761cb0ef41Sopenharmony_ci    DCHECK_EQ(shift_imm, 0);
3771cb0ef41Sopenharmony_ci    shift_op_ = ROR;
3781cb0ef41Sopenharmony_ci    shift_imm_ = 0;
3791cb0ef41Sopenharmony_ci  }
3801cb0ef41Sopenharmony_ci}
3811cb0ef41Sopenharmony_ci
3821cb0ef41Sopenharmony_ciOperand::Operand(Register rm, ShiftOp shift_op, Register rs) {
3831cb0ef41Sopenharmony_ci  DCHECK(shift_op != RRX);
3841cb0ef41Sopenharmony_ci  rm_ = rm;
3851cb0ef41Sopenharmony_ci  rs_ = no_reg;
3861cb0ef41Sopenharmony_ci  shift_op_ = shift_op;
3871cb0ef41Sopenharmony_ci  rs_ = rs;
3881cb0ef41Sopenharmony_ci}
3891cb0ef41Sopenharmony_ci
3901cb0ef41Sopenharmony_ciOperand Operand::EmbeddedNumber(double value) {
3911cb0ef41Sopenharmony_ci  int32_t smi;
3921cb0ef41Sopenharmony_ci  if (DoubleToSmiInteger(value, &smi)) return Operand(Smi::FromInt(smi));
3931cb0ef41Sopenharmony_ci  Operand result(0, RelocInfo::FULL_EMBEDDED_OBJECT);
3941cb0ef41Sopenharmony_ci  result.is_heap_object_request_ = true;
3951cb0ef41Sopenharmony_ci  result.value_.heap_object_request = HeapObjectRequest(value);
3961cb0ef41Sopenharmony_ci  return result;
3971cb0ef41Sopenharmony_ci}
3981cb0ef41Sopenharmony_ci
3991cb0ef41Sopenharmony_ciOperand Operand::EmbeddedStringConstant(const StringConstantBase* str) {
4001cb0ef41Sopenharmony_ci  Operand result(0, RelocInfo::FULL_EMBEDDED_OBJECT);
4011cb0ef41Sopenharmony_ci  result.is_heap_object_request_ = true;
4021cb0ef41Sopenharmony_ci  result.value_.heap_object_request = HeapObjectRequest(str);
4031cb0ef41Sopenharmony_ci  return result;
4041cb0ef41Sopenharmony_ci}
4051cb0ef41Sopenharmony_ci
4061cb0ef41Sopenharmony_ciMemOperand::MemOperand(Register rn, int32_t offset, AddrMode am)
4071cb0ef41Sopenharmony_ci    : rn_(rn), rm_(no_reg), offset_(offset), am_(am) {
4081cb0ef41Sopenharmony_ci  // Accesses below the stack pointer are not safe, and are prohibited by the
4091cb0ef41Sopenharmony_ci  // ABI. We can check obvious violations here.
4101cb0ef41Sopenharmony_ci  if (rn == sp) {
4111cb0ef41Sopenharmony_ci    if (am == Offset) DCHECK_LE(0, offset);
4121cb0ef41Sopenharmony_ci    if (am == NegOffset) DCHECK_GE(0, offset);
4131cb0ef41Sopenharmony_ci  }
4141cb0ef41Sopenharmony_ci}
4151cb0ef41Sopenharmony_ci
4161cb0ef41Sopenharmony_ciMemOperand::MemOperand(Register rn, Register rm, AddrMode am)
4171cb0ef41Sopenharmony_ci    : rn_(rn), rm_(rm), shift_op_(LSL), shift_imm_(0), am_(am) {}
4181cb0ef41Sopenharmony_ci
4191cb0ef41Sopenharmony_ciMemOperand::MemOperand(Register rn, Register rm, ShiftOp shift_op,
4201cb0ef41Sopenharmony_ci                       int shift_imm, AddrMode am)
4211cb0ef41Sopenharmony_ci    : rn_(rn),
4221cb0ef41Sopenharmony_ci      rm_(rm),
4231cb0ef41Sopenharmony_ci      shift_op_(shift_op),
4241cb0ef41Sopenharmony_ci      shift_imm_(shift_imm & 31),
4251cb0ef41Sopenharmony_ci      am_(am) {
4261cb0ef41Sopenharmony_ci  DCHECK(is_uint5(shift_imm));
4271cb0ef41Sopenharmony_ci}
4281cb0ef41Sopenharmony_ci
4291cb0ef41Sopenharmony_ciNeonMemOperand::NeonMemOperand(Register rn, AddrMode am, int align)
4301cb0ef41Sopenharmony_ci    : rn_(rn), rm_(am == Offset ? pc : sp) {
4311cb0ef41Sopenharmony_ci  DCHECK((am == Offset) || (am == PostIndex));
4321cb0ef41Sopenharmony_ci  SetAlignment(align);
4331cb0ef41Sopenharmony_ci}
4341cb0ef41Sopenharmony_ci
4351cb0ef41Sopenharmony_ciNeonMemOperand::NeonMemOperand(Register rn, Register rm, int align)
4361cb0ef41Sopenharmony_ci    : rn_(rn), rm_(rm) {
4371cb0ef41Sopenharmony_ci  SetAlignment(align);
4381cb0ef41Sopenharmony_ci}
4391cb0ef41Sopenharmony_ci
4401cb0ef41Sopenharmony_civoid NeonMemOperand::SetAlignment(int align) {
4411cb0ef41Sopenharmony_ci  switch (align) {
4421cb0ef41Sopenharmony_ci    case 0:
4431cb0ef41Sopenharmony_ci      align_ = 0;
4441cb0ef41Sopenharmony_ci      break;
4451cb0ef41Sopenharmony_ci    case 64:
4461cb0ef41Sopenharmony_ci      align_ = 1;
4471cb0ef41Sopenharmony_ci      break;
4481cb0ef41Sopenharmony_ci    case 128:
4491cb0ef41Sopenharmony_ci      align_ = 2;
4501cb0ef41Sopenharmony_ci      break;
4511cb0ef41Sopenharmony_ci    case 256:
4521cb0ef41Sopenharmony_ci      align_ = 3;
4531cb0ef41Sopenharmony_ci      break;
4541cb0ef41Sopenharmony_ci    default:
4551cb0ef41Sopenharmony_ci      UNREACHABLE();
4561cb0ef41Sopenharmony_ci  }
4571cb0ef41Sopenharmony_ci}
4581cb0ef41Sopenharmony_ci
4591cb0ef41Sopenharmony_civoid Assembler::AllocateAndInstallRequestedHeapObjects(Isolate* isolate) {
4601cb0ef41Sopenharmony_ci  DCHECK_IMPLIES(isolate == nullptr, heap_object_requests_.empty());
4611cb0ef41Sopenharmony_ci  for (auto& request : heap_object_requests_) {
4621cb0ef41Sopenharmony_ci    Handle<HeapObject> object;
4631cb0ef41Sopenharmony_ci    switch (request.kind()) {
4641cb0ef41Sopenharmony_ci      case HeapObjectRequest::kHeapNumber:
4651cb0ef41Sopenharmony_ci        object = isolate->factory()->NewHeapNumber<AllocationType::kOld>(
4661cb0ef41Sopenharmony_ci            request.heap_number());
4671cb0ef41Sopenharmony_ci        break;
4681cb0ef41Sopenharmony_ci      case HeapObjectRequest::kStringConstant: {
4691cb0ef41Sopenharmony_ci        const StringConstantBase* str = request.string();
4701cb0ef41Sopenharmony_ci        CHECK_NOT_NULL(str);
4711cb0ef41Sopenharmony_ci        object = str->AllocateStringConstant(isolate);
4721cb0ef41Sopenharmony_ci        break;
4731cb0ef41Sopenharmony_ci      }
4741cb0ef41Sopenharmony_ci    }
4751cb0ef41Sopenharmony_ci    Address pc = reinterpret_cast<Address>(buffer_start_) + request.offset();
4761cb0ef41Sopenharmony_ci    Memory<Address>(constant_pool_entry_address(pc, 0 /* unused */)) =
4771cb0ef41Sopenharmony_ci        object.address();
4781cb0ef41Sopenharmony_ci  }
4791cb0ef41Sopenharmony_ci}
4801cb0ef41Sopenharmony_ci
4811cb0ef41Sopenharmony_ci// -----------------------------------------------------------------------------
4821cb0ef41Sopenharmony_ci// Specific instructions, constants, and masks.
4831cb0ef41Sopenharmony_ci
4841cb0ef41Sopenharmony_ci// str(r, MemOperand(sp, 4, NegPreIndex), al) instruction (aka push(r))
4851cb0ef41Sopenharmony_ci// register r is not encoded.
4861cb0ef41Sopenharmony_ciconst Instr kPushRegPattern = al | B26 | 4 | NegPreIndex | sp.code() * B16;
4871cb0ef41Sopenharmony_ci// ldr(r, MemOperand(sp, 4, PostIndex), al) instruction (aka pop(r))
4881cb0ef41Sopenharmony_ci// register r is not encoded.
4891cb0ef41Sopenharmony_ciconst Instr kPopRegPattern = al | B26 | L | 4 | PostIndex | sp.code() * B16;
4901cb0ef41Sopenharmony_ci// ldr rd, [pc, #offset]
4911cb0ef41Sopenharmony_ciconst Instr kLdrPCImmedMask = 15 * B24 | 7 * B20 | 15 * B16;
4921cb0ef41Sopenharmony_ciconst Instr kLdrPCImmedPattern = 5 * B24 | L | pc.code() * B16;
4931cb0ef41Sopenharmony_ci// Pc-relative call or jump to a signed imm24 offset.
4941cb0ef41Sopenharmony_ci// bl pc + #offset
4951cb0ef41Sopenharmony_ci// b  pc + #offset
4961cb0ef41Sopenharmony_ciconst Instr kBOrBlPCImmedMask = 0xE * B24;
4971cb0ef41Sopenharmony_ciconst Instr kBOrBlPCImmedPattern = 0xA * B24;
4981cb0ef41Sopenharmony_ci// vldr dd, [pc, #offset]
4991cb0ef41Sopenharmony_ciconst Instr kVldrDPCMask = 15 * B24 | 3 * B20 | 15 * B16 | 15 * B8;
5001cb0ef41Sopenharmony_ciconst Instr kVldrDPCPattern = 13 * B24 | L | pc.code() * B16 | 11 * B8;
5011cb0ef41Sopenharmony_ci// blxcc rm
5021cb0ef41Sopenharmony_ciconst Instr kBlxRegMask =
5031cb0ef41Sopenharmony_ci    15 * B24 | 15 * B20 | 15 * B16 | 15 * B12 | 15 * B8 | 15 * B4;
5041cb0ef41Sopenharmony_ciconst Instr kBlxRegPattern = B24 | B21 | 15 * B16 | 15 * B12 | 15 * B8 | BLX;
5051cb0ef41Sopenharmony_ciconst Instr kBlxIp = al | kBlxRegPattern | ip.code();
5061cb0ef41Sopenharmony_ciconst Instr kMovMvnMask = 0x6D * B21 | 0xF * B16;
5071cb0ef41Sopenharmony_ciconst Instr kMovMvnPattern = 0xD * B21;
5081cb0ef41Sopenharmony_ciconst Instr kMovMvnFlip = B22;
5091cb0ef41Sopenharmony_ciconst Instr kMovLeaveCCMask = 0xDFF * B16;
5101cb0ef41Sopenharmony_ciconst Instr kMovLeaveCCPattern = 0x1A0 * B16;
5111cb0ef41Sopenharmony_ciconst Instr kMovwPattern = 0x30 * B20;
5121cb0ef41Sopenharmony_ciconst Instr kMovtPattern = 0x34 * B20;
5131cb0ef41Sopenharmony_ciconst Instr kMovwLeaveCCFlip = 0x5 * B21;
5141cb0ef41Sopenharmony_ciconst Instr kMovImmedMask = 0x7F * B21;
5151cb0ef41Sopenharmony_ciconst Instr kMovImmedPattern = 0x1D * B21;
5161cb0ef41Sopenharmony_ciconst Instr kOrrImmedMask = 0x7F * B21;
5171cb0ef41Sopenharmony_ciconst Instr kOrrImmedPattern = 0x1C * B21;
5181cb0ef41Sopenharmony_ciconst Instr kCmpCmnMask = 0xDD * B20 | 0xF * B12;
5191cb0ef41Sopenharmony_ciconst Instr kCmpCmnPattern = 0x15 * B20;
5201cb0ef41Sopenharmony_ciconst Instr kCmpCmnFlip = B21;
5211cb0ef41Sopenharmony_ciconst Instr kAddSubFlip = 0x6 * B21;
5221cb0ef41Sopenharmony_ciconst Instr kAndBicFlip = 0xE * B21;
5231cb0ef41Sopenharmony_ci
5241cb0ef41Sopenharmony_ci// A mask for the Rd register for push, pop, ldr, str instructions.
5251cb0ef41Sopenharmony_ciconst Instr kLdrRegFpOffsetPattern = al | B26 | L | Offset | fp.code() * B16;
5261cb0ef41Sopenharmony_ciconst Instr kStrRegFpOffsetPattern = al | B26 | Offset | fp.code() * B16;
5271cb0ef41Sopenharmony_ciconst Instr kLdrRegFpNegOffsetPattern =
5281cb0ef41Sopenharmony_ci    al | B26 | L | NegOffset | fp.code() * B16;
5291cb0ef41Sopenharmony_ciconst Instr kStrRegFpNegOffsetPattern = al | B26 | NegOffset | fp.code() * B16;
5301cb0ef41Sopenharmony_ciconst Instr kLdrStrInstrTypeMask = 0xFFFF0000;
5311cb0ef41Sopenharmony_ci
5321cb0ef41Sopenharmony_ciAssembler::Assembler(const AssemblerOptions& options,
5331cb0ef41Sopenharmony_ci                     std::unique_ptr<AssemblerBuffer> buffer)
5341cb0ef41Sopenharmony_ci    : AssemblerBase(options, std::move(buffer)),
5351cb0ef41Sopenharmony_ci      pending_32_bit_constants_(),
5361cb0ef41Sopenharmony_ci      scratch_register_list_({ip}) {
5371cb0ef41Sopenharmony_ci  reloc_info_writer.Reposition(buffer_start_ + buffer_->size(), pc_);
5381cb0ef41Sopenharmony_ci  constant_pool_deadline_ = kMaxInt;
5391cb0ef41Sopenharmony_ci  const_pool_blocked_nesting_ = 0;
5401cb0ef41Sopenharmony_ci  no_const_pool_before_ = 0;
5411cb0ef41Sopenharmony_ci  first_const_pool_32_use_ = -1;
5421cb0ef41Sopenharmony_ci  last_bound_pos_ = 0;
5431cb0ef41Sopenharmony_ci  if (CpuFeatures::IsSupported(VFP32DREGS)) {
5441cb0ef41Sopenharmony_ci    // Register objects tend to be abstracted and survive between scopes, so
5451cb0ef41Sopenharmony_ci    // it's awkward to use CpuFeatures::VFP32DREGS with CpuFeatureScope. To make
5461cb0ef41Sopenharmony_ci    // its use consistent with other features, we always enable it if we can.
5471cb0ef41Sopenharmony_ci    EnableCpuFeature(VFP32DREGS);
5481cb0ef41Sopenharmony_ci    // Make sure we pick two D registers which alias a Q register. This way, we
5491cb0ef41Sopenharmony_ci    // can use a Q as a scratch if NEON is supported.
5501cb0ef41Sopenharmony_ci    scratch_vfp_register_list_ = d14.ToVfpRegList() | d15.ToVfpRegList();
5511cb0ef41Sopenharmony_ci  } else {
5521cb0ef41Sopenharmony_ci    // When VFP32DREGS is not supported, d15 become allocatable. Therefore we
5531cb0ef41Sopenharmony_ci    // cannot use it as a scratch.
5541cb0ef41Sopenharmony_ci    scratch_vfp_register_list_ = d14.ToVfpRegList();
5551cb0ef41Sopenharmony_ci  }
5561cb0ef41Sopenharmony_ci}
5571cb0ef41Sopenharmony_ci
5581cb0ef41Sopenharmony_ciAssembler::~Assembler() {
5591cb0ef41Sopenharmony_ci  DCHECK_EQ(const_pool_blocked_nesting_, 0);
5601cb0ef41Sopenharmony_ci  DCHECK_EQ(first_const_pool_32_use_, -1);
5611cb0ef41Sopenharmony_ci}
5621cb0ef41Sopenharmony_ci
5631cb0ef41Sopenharmony_civoid Assembler::GetCode(Isolate* isolate, CodeDesc* desc,
5641cb0ef41Sopenharmony_ci                        SafepointTableBuilder* safepoint_table_builder,
5651cb0ef41Sopenharmony_ci                        int handler_table_offset) {
5661cb0ef41Sopenharmony_ci  // As a crutch to avoid having to add manual Align calls wherever we use a
5671cb0ef41Sopenharmony_ci  // raw workflow to create Code objects (mostly in tests), add another Align
5681cb0ef41Sopenharmony_ci  // call here. It does no harm - the end of the Code object is aligned to the
5691cb0ef41Sopenharmony_ci  // (larger) kCodeAlignment anyways.
5701cb0ef41Sopenharmony_ci  // TODO(jgruber): Consider moving responsibility for proper alignment to
5711cb0ef41Sopenharmony_ci  // metadata table builders (safepoint, handler, constant pool, code
5721cb0ef41Sopenharmony_ci  // comments).
5731cb0ef41Sopenharmony_ci  DataAlign(Code::kMetadataAlignment);
5741cb0ef41Sopenharmony_ci
5751cb0ef41Sopenharmony_ci  // Emit constant pool if necessary.
5761cb0ef41Sopenharmony_ci  CheckConstPool(true, false);
5771cb0ef41Sopenharmony_ci  DCHECK(pending_32_bit_constants_.empty());
5781cb0ef41Sopenharmony_ci
5791cb0ef41Sopenharmony_ci  int code_comments_size = WriteCodeComments();
5801cb0ef41Sopenharmony_ci
5811cb0ef41Sopenharmony_ci  AllocateAndInstallRequestedHeapObjects(isolate);
5821cb0ef41Sopenharmony_ci
5831cb0ef41Sopenharmony_ci  // Set up code descriptor.
5841cb0ef41Sopenharmony_ci  // TODO(jgruber): Reconsider how these offsets and sizes are maintained up to
5851cb0ef41Sopenharmony_ci  // this point to make CodeDesc initialization less fiddly.
5861cb0ef41Sopenharmony_ci
5871cb0ef41Sopenharmony_ci  static constexpr int kConstantPoolSize = 0;
5881cb0ef41Sopenharmony_ci  const int instruction_size = pc_offset();
5891cb0ef41Sopenharmony_ci  const int code_comments_offset = instruction_size - code_comments_size;
5901cb0ef41Sopenharmony_ci  const int constant_pool_offset = code_comments_offset - kConstantPoolSize;
5911cb0ef41Sopenharmony_ci  const int handler_table_offset2 = (handler_table_offset == kNoHandlerTable)
5921cb0ef41Sopenharmony_ci                                        ? constant_pool_offset
5931cb0ef41Sopenharmony_ci                                        : handler_table_offset;
5941cb0ef41Sopenharmony_ci  const int safepoint_table_offset =
5951cb0ef41Sopenharmony_ci      (safepoint_table_builder == kNoSafepointTable)
5961cb0ef41Sopenharmony_ci          ? handler_table_offset2
5971cb0ef41Sopenharmony_ci          : safepoint_table_builder->safepoint_table_offset();
5981cb0ef41Sopenharmony_ci  const int reloc_info_offset =
5991cb0ef41Sopenharmony_ci      static_cast<int>(reloc_info_writer.pos() - buffer_->start());
6001cb0ef41Sopenharmony_ci  CodeDesc::Initialize(desc, this, safepoint_table_offset,
6011cb0ef41Sopenharmony_ci                       handler_table_offset2, constant_pool_offset,
6021cb0ef41Sopenharmony_ci                       code_comments_offset, reloc_info_offset);
6031cb0ef41Sopenharmony_ci}
6041cb0ef41Sopenharmony_ci
6051cb0ef41Sopenharmony_civoid Assembler::Align(int m) {
6061cb0ef41Sopenharmony_ci  DCHECK(m >= 4 && base::bits::IsPowerOfTwo(m));
6071cb0ef41Sopenharmony_ci  DCHECK_EQ(pc_offset() & (kInstrSize - 1), 0);
6081cb0ef41Sopenharmony_ci  while ((pc_offset() & (m - 1)) != 0) {
6091cb0ef41Sopenharmony_ci    nop();
6101cb0ef41Sopenharmony_ci  }
6111cb0ef41Sopenharmony_ci}
6121cb0ef41Sopenharmony_ci
6131cb0ef41Sopenharmony_civoid Assembler::CodeTargetAlign() {
6141cb0ef41Sopenharmony_ci  // Preferred alignment of jump targets on some ARM chips.
6151cb0ef41Sopenharmony_ci  Align(8);
6161cb0ef41Sopenharmony_ci}
6171cb0ef41Sopenharmony_ci
6181cb0ef41Sopenharmony_ciCondition Assembler::GetCondition(Instr instr) {
6191cb0ef41Sopenharmony_ci  return Instruction::ConditionField(instr);
6201cb0ef41Sopenharmony_ci}
6211cb0ef41Sopenharmony_ci
6221cb0ef41Sopenharmony_cibool Assembler::IsLdrRegisterImmediate(Instr instr) {
6231cb0ef41Sopenharmony_ci  return (instr & (B27 | B26 | B25 | B22 | B20)) == (B26 | B20);
6241cb0ef41Sopenharmony_ci}
6251cb0ef41Sopenharmony_ci
6261cb0ef41Sopenharmony_cibool Assembler::IsVldrDRegisterImmediate(Instr instr) {
6271cb0ef41Sopenharmony_ci  return (instr & (15 * B24 | 3 * B20 | 15 * B8)) == (13 * B24 | B20 | 11 * B8);
6281cb0ef41Sopenharmony_ci}
6291cb0ef41Sopenharmony_ci
6301cb0ef41Sopenharmony_ciint Assembler::GetLdrRegisterImmediateOffset(Instr instr) {
6311cb0ef41Sopenharmony_ci  DCHECK(IsLdrRegisterImmediate(instr));
6321cb0ef41Sopenharmony_ci  bool positive = (instr & B23) == B23;
6331cb0ef41Sopenharmony_ci  int offset = instr & kOff12Mask;  // Zero extended offset.
6341cb0ef41Sopenharmony_ci  return positive ? offset : -offset;
6351cb0ef41Sopenharmony_ci}
6361cb0ef41Sopenharmony_ci
6371cb0ef41Sopenharmony_ciint Assembler::GetVldrDRegisterImmediateOffset(Instr instr) {
6381cb0ef41Sopenharmony_ci  DCHECK(IsVldrDRegisterImmediate(instr));
6391cb0ef41Sopenharmony_ci  bool positive = (instr & B23) == B23;
6401cb0ef41Sopenharmony_ci  int offset = instr & kOff8Mask;  // Zero extended offset.
6411cb0ef41Sopenharmony_ci  offset <<= 2;
6421cb0ef41Sopenharmony_ci  return positive ? offset : -offset;
6431cb0ef41Sopenharmony_ci}
6441cb0ef41Sopenharmony_ci
6451cb0ef41Sopenharmony_ciInstr Assembler::SetLdrRegisterImmediateOffset(Instr instr, int offset) {
6461cb0ef41Sopenharmony_ci  DCHECK(IsLdrRegisterImmediate(instr));
6471cb0ef41Sopenharmony_ci  bool positive = offset >= 0;
6481cb0ef41Sopenharmony_ci  if (!positive) offset = -offset;
6491cb0ef41Sopenharmony_ci  DCHECK(is_uint12(offset));
6501cb0ef41Sopenharmony_ci  // Set bit indicating whether the offset should be added.
6511cb0ef41Sopenharmony_ci  instr = (instr & ~B23) | (positive ? B23 : 0);
6521cb0ef41Sopenharmony_ci  // Set the actual offset.
6531cb0ef41Sopenharmony_ci  return (instr & ~kOff12Mask) | offset;
6541cb0ef41Sopenharmony_ci}
6551cb0ef41Sopenharmony_ci
6561cb0ef41Sopenharmony_ciInstr Assembler::SetVldrDRegisterImmediateOffset(Instr instr, int offset) {
6571cb0ef41Sopenharmony_ci  DCHECK(IsVldrDRegisterImmediate(instr));
6581cb0ef41Sopenharmony_ci  DCHECK((offset & ~3) == offset);  // Must be 64-bit aligned.
6591cb0ef41Sopenharmony_ci  bool positive = offset >= 0;
6601cb0ef41Sopenharmony_ci  if (!positive) offset = -offset;
6611cb0ef41Sopenharmony_ci  DCHECK(is_uint10(offset));
6621cb0ef41Sopenharmony_ci  // Set bit indicating whether the offset should be added.
6631cb0ef41Sopenharmony_ci  instr = (instr & ~B23) | (positive ? B23 : 0);
6641cb0ef41Sopenharmony_ci  // Set the actual offset. Its bottom 2 bits are zero.
6651cb0ef41Sopenharmony_ci  return (instr & ~kOff8Mask) | (offset >> 2);
6661cb0ef41Sopenharmony_ci}
6671cb0ef41Sopenharmony_ci
6681cb0ef41Sopenharmony_cibool Assembler::IsStrRegisterImmediate(Instr instr) {
6691cb0ef41Sopenharmony_ci  return (instr & (B27 | B26 | B25 | B22 | B20)) == B26;
6701cb0ef41Sopenharmony_ci}
6711cb0ef41Sopenharmony_ci
6721cb0ef41Sopenharmony_ciInstr Assembler::SetStrRegisterImmediateOffset(Instr instr, int offset) {
6731cb0ef41Sopenharmony_ci  DCHECK(IsStrRegisterImmediate(instr));
6741cb0ef41Sopenharmony_ci  bool positive = offset >= 0;
6751cb0ef41Sopenharmony_ci  if (!positive) offset = -offset;
6761cb0ef41Sopenharmony_ci  DCHECK(is_uint12(offset));
6771cb0ef41Sopenharmony_ci  // Set bit indicating whether the offset should be added.
6781cb0ef41Sopenharmony_ci  instr = (instr & ~B23) | (positive ? B23 : 0);
6791cb0ef41Sopenharmony_ci  // Set the actual offset.
6801cb0ef41Sopenharmony_ci  return (instr & ~kOff12Mask) | offset;
6811cb0ef41Sopenharmony_ci}
6821cb0ef41Sopenharmony_ci
6831cb0ef41Sopenharmony_cibool Assembler::IsAddRegisterImmediate(Instr instr) {
6841cb0ef41Sopenharmony_ci  return (instr & (B27 | B26 | B25 | B24 | B23 | B22 | B21)) == (B25 | B23);
6851cb0ef41Sopenharmony_ci}
6861cb0ef41Sopenharmony_ci
6871cb0ef41Sopenharmony_ciInstr Assembler::SetAddRegisterImmediateOffset(Instr instr, int offset) {
6881cb0ef41Sopenharmony_ci  DCHECK(IsAddRegisterImmediate(instr));
6891cb0ef41Sopenharmony_ci  DCHECK_GE(offset, 0);
6901cb0ef41Sopenharmony_ci  DCHECK(is_uint12(offset));
6911cb0ef41Sopenharmony_ci  // Set the offset.
6921cb0ef41Sopenharmony_ci  return (instr & ~kOff12Mask) | offset;
6931cb0ef41Sopenharmony_ci}
6941cb0ef41Sopenharmony_ci
6951cb0ef41Sopenharmony_ciRegister Assembler::GetRd(Instr instr) {
6961cb0ef41Sopenharmony_ci  return Register::from_code(Instruction::RdValue(instr));
6971cb0ef41Sopenharmony_ci}
6981cb0ef41Sopenharmony_ci
6991cb0ef41Sopenharmony_ciRegister Assembler::GetRn(Instr instr) {
7001cb0ef41Sopenharmony_ci  return Register::from_code(Instruction::RnValue(instr));
7011cb0ef41Sopenharmony_ci}
7021cb0ef41Sopenharmony_ci
7031cb0ef41Sopenharmony_ciRegister Assembler::GetRm(Instr instr) {
7041cb0ef41Sopenharmony_ci  return Register::from_code(Instruction::RmValue(instr));
7051cb0ef41Sopenharmony_ci}
7061cb0ef41Sopenharmony_ci
7071cb0ef41Sopenharmony_cibool Assembler::IsPush(Instr instr) {
7081cb0ef41Sopenharmony_ci  return ((instr & ~kRdMask) == kPushRegPattern);
7091cb0ef41Sopenharmony_ci}
7101cb0ef41Sopenharmony_ci
7111cb0ef41Sopenharmony_cibool Assembler::IsPop(Instr instr) {
7121cb0ef41Sopenharmony_ci  return ((instr & ~kRdMask) == kPopRegPattern);
7131cb0ef41Sopenharmony_ci}
7141cb0ef41Sopenharmony_ci
7151cb0ef41Sopenharmony_cibool Assembler::IsStrRegFpOffset(Instr instr) {
7161cb0ef41Sopenharmony_ci  return ((instr & kLdrStrInstrTypeMask) == kStrRegFpOffsetPattern);
7171cb0ef41Sopenharmony_ci}
7181cb0ef41Sopenharmony_ci
7191cb0ef41Sopenharmony_cibool Assembler::IsLdrRegFpOffset(Instr instr) {
7201cb0ef41Sopenharmony_ci  return ((instr & kLdrStrInstrTypeMask) == kLdrRegFpOffsetPattern);
7211cb0ef41Sopenharmony_ci}
7221cb0ef41Sopenharmony_ci
7231cb0ef41Sopenharmony_cibool Assembler::IsStrRegFpNegOffset(Instr instr) {
7241cb0ef41Sopenharmony_ci  return ((instr & kLdrStrInstrTypeMask) == kStrRegFpNegOffsetPattern);
7251cb0ef41Sopenharmony_ci}
7261cb0ef41Sopenharmony_ci
7271cb0ef41Sopenharmony_cibool Assembler::IsLdrRegFpNegOffset(Instr instr) {
7281cb0ef41Sopenharmony_ci  return ((instr & kLdrStrInstrTypeMask) == kLdrRegFpNegOffsetPattern);
7291cb0ef41Sopenharmony_ci}
7301cb0ef41Sopenharmony_ci
7311cb0ef41Sopenharmony_cibool Assembler::IsLdrPcImmediateOffset(Instr instr) {
7321cb0ef41Sopenharmony_ci  // Check the instruction is indeed a
7331cb0ef41Sopenharmony_ci  // ldr<cond> <Rd>, [pc +/- offset_12].
7341cb0ef41Sopenharmony_ci  return (instr & kLdrPCImmedMask) == kLdrPCImmedPattern;
7351cb0ef41Sopenharmony_ci}
7361cb0ef41Sopenharmony_ci
7371cb0ef41Sopenharmony_cibool Assembler::IsBOrBlPcImmediateOffset(Instr instr) {
7381cb0ef41Sopenharmony_ci  return (instr & kBOrBlPCImmedMask) == kBOrBlPCImmedPattern;
7391cb0ef41Sopenharmony_ci}
7401cb0ef41Sopenharmony_ci
7411cb0ef41Sopenharmony_cibool Assembler::IsVldrDPcImmediateOffset(Instr instr) {
7421cb0ef41Sopenharmony_ci  // Check the instruction is indeed a
7431cb0ef41Sopenharmony_ci  // vldr<cond> <Dd>, [pc +/- offset_10].
7441cb0ef41Sopenharmony_ci  return (instr & kVldrDPCMask) == kVldrDPCPattern;
7451cb0ef41Sopenharmony_ci}
7461cb0ef41Sopenharmony_ci
7471cb0ef41Sopenharmony_cibool Assembler::IsBlxReg(Instr instr) {
7481cb0ef41Sopenharmony_ci  // Check the instruction is indeed a
7491cb0ef41Sopenharmony_ci  // blxcc <Rm>
7501cb0ef41Sopenharmony_ci  return (instr & kBlxRegMask) == kBlxRegPattern;
7511cb0ef41Sopenharmony_ci}
7521cb0ef41Sopenharmony_ci
7531cb0ef41Sopenharmony_cibool Assembler::IsBlxIp(Instr instr) {
7541cb0ef41Sopenharmony_ci  // Check the instruction is indeed a
7551cb0ef41Sopenharmony_ci  // blx ip
7561cb0ef41Sopenharmony_ci  return instr == kBlxIp;
7571cb0ef41Sopenharmony_ci}
7581cb0ef41Sopenharmony_ci
7591cb0ef41Sopenharmony_cibool Assembler::IsTstImmediate(Instr instr) {
7601cb0ef41Sopenharmony_ci  return (instr & (B27 | B26 | I | kOpCodeMask | S | kRdMask)) == (I | TST | S);
7611cb0ef41Sopenharmony_ci}
7621cb0ef41Sopenharmony_ci
7631cb0ef41Sopenharmony_cibool Assembler::IsCmpRegister(Instr instr) {
7641cb0ef41Sopenharmony_ci  return (instr & (B27 | B26 | I | kOpCodeMask | S | kRdMask | B4)) ==
7651cb0ef41Sopenharmony_ci         (CMP | S);
7661cb0ef41Sopenharmony_ci}
7671cb0ef41Sopenharmony_ci
7681cb0ef41Sopenharmony_cibool Assembler::IsCmpImmediate(Instr instr) {
7691cb0ef41Sopenharmony_ci  return (instr & (B27 | B26 | I | kOpCodeMask | S | kRdMask)) == (I | CMP | S);
7701cb0ef41Sopenharmony_ci}
7711cb0ef41Sopenharmony_ci
7721cb0ef41Sopenharmony_ciRegister Assembler::GetCmpImmediateRegister(Instr instr) {
7731cb0ef41Sopenharmony_ci  DCHECK(IsCmpImmediate(instr));
7741cb0ef41Sopenharmony_ci  return GetRn(instr);
7751cb0ef41Sopenharmony_ci}
7761cb0ef41Sopenharmony_ci
7771cb0ef41Sopenharmony_ciint Assembler::GetCmpImmediateRawImmediate(Instr instr) {
7781cb0ef41Sopenharmony_ci  DCHECK(IsCmpImmediate(instr));
7791cb0ef41Sopenharmony_ci  return instr & kOff12Mask;
7801cb0ef41Sopenharmony_ci}
7811cb0ef41Sopenharmony_ci
7821cb0ef41Sopenharmony_ci// Labels refer to positions in the (to be) generated code.
7831cb0ef41Sopenharmony_ci// There are bound, linked, and unused labels.
7841cb0ef41Sopenharmony_ci//
7851cb0ef41Sopenharmony_ci// Bound labels refer to known positions in the already
7861cb0ef41Sopenharmony_ci// generated code. pos() is the position the label refers to.
7871cb0ef41Sopenharmony_ci//
7881cb0ef41Sopenharmony_ci// Linked labels refer to unknown positions in the code
7891cb0ef41Sopenharmony_ci// to be generated; pos() is the position of the last
7901cb0ef41Sopenharmony_ci// instruction using the label.
7911cb0ef41Sopenharmony_ci//
7921cb0ef41Sopenharmony_ci// The linked labels form a link chain by making the branch offset
7931cb0ef41Sopenharmony_ci// in the instruction steam to point to the previous branch
7941cb0ef41Sopenharmony_ci// instruction using the same label.
7951cb0ef41Sopenharmony_ci//
7961cb0ef41Sopenharmony_ci// The link chain is terminated by a branch offset pointing to the
7971cb0ef41Sopenharmony_ci// same position.
7981cb0ef41Sopenharmony_ci
7991cb0ef41Sopenharmony_ciint Assembler::target_at(int pos) {
8001cb0ef41Sopenharmony_ci  Instr instr = instr_at(pos);
8011cb0ef41Sopenharmony_ci  if (is_uint24(instr)) {
8021cb0ef41Sopenharmony_ci    // Emitted link to a label, not part of a branch.
8031cb0ef41Sopenharmony_ci    return instr;
8041cb0ef41Sopenharmony_ci  }
8051cb0ef41Sopenharmony_ci  DCHECK_EQ(5 * B25, instr & 7 * B25);  // b, bl, or blx imm24
8061cb0ef41Sopenharmony_ci  int imm26 = ((instr & kImm24Mask) << 8) >> 6;
8071cb0ef41Sopenharmony_ci  if ((Instruction::ConditionField(instr) == kSpecialCondition) &&
8081cb0ef41Sopenharmony_ci      ((instr & B24) != 0)) {
8091cb0ef41Sopenharmony_ci    // blx uses bit 24 to encode bit 2 of imm26
8101cb0ef41Sopenharmony_ci    imm26 += 2;
8111cb0ef41Sopenharmony_ci  }
8121cb0ef41Sopenharmony_ci  return pos + Instruction::kPcLoadDelta + imm26;
8131cb0ef41Sopenharmony_ci}
8141cb0ef41Sopenharmony_ci
8151cb0ef41Sopenharmony_civoid Assembler::target_at_put(int pos, int target_pos) {
8161cb0ef41Sopenharmony_ci  Instr instr = instr_at(pos);
8171cb0ef41Sopenharmony_ci  if (is_uint24(instr)) {
8181cb0ef41Sopenharmony_ci    DCHECK(target_pos == pos || target_pos >= 0);
8191cb0ef41Sopenharmony_ci    // Emitted link to a label, not part of a branch.
8201cb0ef41Sopenharmony_ci    // Load the position of the label relative to the generated code object
8211cb0ef41Sopenharmony_ci    // pointer in a register.
8221cb0ef41Sopenharmony_ci
8231cb0ef41Sopenharmony_ci    // The existing code must be a single 24-bit label chain link, followed by
8241cb0ef41Sopenharmony_ci    // nops encoding the destination register. See mov_label_offset.
8251cb0ef41Sopenharmony_ci
8261cb0ef41Sopenharmony_ci    // Extract the destination register from the first nop instructions.
8271cb0ef41Sopenharmony_ci    Register dst =
8281cb0ef41Sopenharmony_ci        Register::from_code(Instruction::RmValue(instr_at(pos + kInstrSize)));
8291cb0ef41Sopenharmony_ci    // In addition to the 24-bit label chain link, we expect to find one nop for
8301cb0ef41Sopenharmony_ci    // ARMv7 and above, or two nops for ARMv6. See mov_label_offset.
8311cb0ef41Sopenharmony_ci    DCHECK(IsNop(instr_at(pos + kInstrSize), dst.code()));
8321cb0ef41Sopenharmony_ci    if (!CpuFeatures::IsSupported(ARMv7)) {
8331cb0ef41Sopenharmony_ci      DCHECK(IsNop(instr_at(pos + 2 * kInstrSize), dst.code()));
8341cb0ef41Sopenharmony_ci    }
8351cb0ef41Sopenharmony_ci
8361cb0ef41Sopenharmony_ci    // Here are the instructions we need to emit:
8371cb0ef41Sopenharmony_ci    //   For ARMv7: target24 => target16_1:target16_0
8381cb0ef41Sopenharmony_ci    //      movw dst, #target16_0
8391cb0ef41Sopenharmony_ci    //      movt dst, #target16_1
8401cb0ef41Sopenharmony_ci    //   For ARMv6: target24 => target8_2:target8_1:target8_0
8411cb0ef41Sopenharmony_ci    //      mov dst, #target8_0
8421cb0ef41Sopenharmony_ci    //      orr dst, dst, #target8_1 << 8
8431cb0ef41Sopenharmony_ci    //      orr dst, dst, #target8_2 << 16
8441cb0ef41Sopenharmony_ci
8451cb0ef41Sopenharmony_ci    uint32_t target24 = target_pos + (Code::kHeaderSize - kHeapObjectTag);
8461cb0ef41Sopenharmony_ci    CHECK(is_uint24(target24));
8471cb0ef41Sopenharmony_ci    if (is_uint8(target24)) {
8481cb0ef41Sopenharmony_ci      // If the target fits in a byte then only patch with a mov
8491cb0ef41Sopenharmony_ci      // instruction.
8501cb0ef41Sopenharmony_ci      PatchingAssembler patcher(
8511cb0ef41Sopenharmony_ci          options(), reinterpret_cast<byte*>(buffer_start_ + pos), 1);
8521cb0ef41Sopenharmony_ci      patcher.mov(dst, Operand(target24));
8531cb0ef41Sopenharmony_ci    } else {
8541cb0ef41Sopenharmony_ci      uint16_t target16_0 = target24 & kImm16Mask;
8551cb0ef41Sopenharmony_ci      uint16_t target16_1 = target24 >> 16;
8561cb0ef41Sopenharmony_ci      if (CpuFeatures::IsSupported(ARMv7)) {
8571cb0ef41Sopenharmony_ci        // Patch with movw/movt.
8581cb0ef41Sopenharmony_ci        if (target16_1 == 0) {
8591cb0ef41Sopenharmony_ci          PatchingAssembler patcher(
8601cb0ef41Sopenharmony_ci              options(), reinterpret_cast<byte*>(buffer_start_ + pos), 1);
8611cb0ef41Sopenharmony_ci          CpuFeatureScope scope(&patcher, ARMv7);
8621cb0ef41Sopenharmony_ci          patcher.movw(dst, target16_0);
8631cb0ef41Sopenharmony_ci        } else {
8641cb0ef41Sopenharmony_ci          PatchingAssembler patcher(
8651cb0ef41Sopenharmony_ci              options(), reinterpret_cast<byte*>(buffer_start_ + pos), 2);
8661cb0ef41Sopenharmony_ci          CpuFeatureScope scope(&patcher, ARMv7);
8671cb0ef41Sopenharmony_ci          patcher.movw(dst, target16_0);
8681cb0ef41Sopenharmony_ci          patcher.movt(dst, target16_1);
8691cb0ef41Sopenharmony_ci        }
8701cb0ef41Sopenharmony_ci      } else {
8711cb0ef41Sopenharmony_ci        // Patch with a sequence of mov/orr/orr instructions.
8721cb0ef41Sopenharmony_ci        uint8_t target8_0 = target16_0 & kImm8Mask;
8731cb0ef41Sopenharmony_ci        uint8_t target8_1 = target16_0 >> 8;
8741cb0ef41Sopenharmony_ci        uint8_t target8_2 = target16_1 & kImm8Mask;
8751cb0ef41Sopenharmony_ci        if (target8_2 == 0) {
8761cb0ef41Sopenharmony_ci          PatchingAssembler patcher(
8771cb0ef41Sopenharmony_ci              options(), reinterpret_cast<byte*>(buffer_start_ + pos), 2);
8781cb0ef41Sopenharmony_ci          patcher.mov(dst, Operand(target8_0));
8791cb0ef41Sopenharmony_ci          patcher.orr(dst, dst, Operand(target8_1 << 8));
8801cb0ef41Sopenharmony_ci        } else {
8811cb0ef41Sopenharmony_ci          PatchingAssembler patcher(
8821cb0ef41Sopenharmony_ci              options(), reinterpret_cast<byte*>(buffer_start_ + pos), 3);
8831cb0ef41Sopenharmony_ci          patcher.mov(dst, Operand(target8_0));
8841cb0ef41Sopenharmony_ci          patcher.orr(dst, dst, Operand(target8_1 << 8));
8851cb0ef41Sopenharmony_ci          patcher.orr(dst, dst, Operand(target8_2 << 16));
8861cb0ef41Sopenharmony_ci        }
8871cb0ef41Sopenharmony_ci      }
8881cb0ef41Sopenharmony_ci    }
8891cb0ef41Sopenharmony_ci    return;
8901cb0ef41Sopenharmony_ci  }
8911cb0ef41Sopenharmony_ci  int imm26 = target_pos - (pos + Instruction::kPcLoadDelta);
8921cb0ef41Sopenharmony_ci  DCHECK_EQ(5 * B25, instr & 7 * B25);  // b, bl, or blx imm24
8931cb0ef41Sopenharmony_ci  if (Instruction::ConditionField(instr) == kSpecialCondition) {
8941cb0ef41Sopenharmony_ci    // blx uses bit 24 to encode bit 2 of imm26
8951cb0ef41Sopenharmony_ci    DCHECK_EQ(0, imm26 & 1);
8961cb0ef41Sopenharmony_ci    instr = (instr & ~(B24 | kImm24Mask)) | ((imm26 & 2) >> 1) * B24;
8971cb0ef41Sopenharmony_ci  } else {
8981cb0ef41Sopenharmony_ci    DCHECK_EQ(0, imm26 & 3);
8991cb0ef41Sopenharmony_ci    instr &= ~kImm24Mask;
9001cb0ef41Sopenharmony_ci  }
9011cb0ef41Sopenharmony_ci  int imm24 = imm26 >> 2;
9021cb0ef41Sopenharmony_ci  CHECK(is_int24(imm24));
9031cb0ef41Sopenharmony_ci  instr_at_put(pos, instr | (imm24 & kImm24Mask));
9041cb0ef41Sopenharmony_ci}
9051cb0ef41Sopenharmony_ci
9061cb0ef41Sopenharmony_civoid Assembler::print(const Label* L) {
9071cb0ef41Sopenharmony_ci  if (L->is_unused()) {
9081cb0ef41Sopenharmony_ci    PrintF("unused label\n");
9091cb0ef41Sopenharmony_ci  } else if (L->is_bound()) {
9101cb0ef41Sopenharmony_ci    PrintF("bound label to %d\n", L->pos());
9111cb0ef41Sopenharmony_ci  } else if (L->is_linked()) {
9121cb0ef41Sopenharmony_ci    Label l;
9131cb0ef41Sopenharmony_ci    l.link_to(L->pos());
9141cb0ef41Sopenharmony_ci    PrintF("unbound label");
9151cb0ef41Sopenharmony_ci    while (l.is_linked()) {
9161cb0ef41Sopenharmony_ci      PrintF("@ %d ", l.pos());
9171cb0ef41Sopenharmony_ci      Instr instr = instr_at(l.pos());
9181cb0ef41Sopenharmony_ci      if ((instr & ~kImm24Mask) == 0) {
9191cb0ef41Sopenharmony_ci        PrintF("value\n");
9201cb0ef41Sopenharmony_ci      } else {
9211cb0ef41Sopenharmony_ci        DCHECK_EQ(instr & 7 * B25, 5 * B25);  // b, bl, or blx
9221cb0ef41Sopenharmony_ci        Condition cond = Instruction::ConditionField(instr);
9231cb0ef41Sopenharmony_ci        const char* b;
9241cb0ef41Sopenharmony_ci        const char* c;
9251cb0ef41Sopenharmony_ci        if (cond == kSpecialCondition) {
9261cb0ef41Sopenharmony_ci          b = "blx";
9271cb0ef41Sopenharmony_ci          c = "";
9281cb0ef41Sopenharmony_ci        } else {
9291cb0ef41Sopenharmony_ci          if ((instr & B24) != 0)
9301cb0ef41Sopenharmony_ci            b = "bl";
9311cb0ef41Sopenharmony_ci          else
9321cb0ef41Sopenharmony_ci            b = "b";
9331cb0ef41Sopenharmony_ci
9341cb0ef41Sopenharmony_ci          switch (cond) {
9351cb0ef41Sopenharmony_ci            case eq:
9361cb0ef41Sopenharmony_ci              c = "eq";
9371cb0ef41Sopenharmony_ci              break;
9381cb0ef41Sopenharmony_ci            case ne:
9391cb0ef41Sopenharmony_ci              c = "ne";
9401cb0ef41Sopenharmony_ci              break;
9411cb0ef41Sopenharmony_ci            case hs:
9421cb0ef41Sopenharmony_ci              c = "hs";
9431cb0ef41Sopenharmony_ci              break;
9441cb0ef41Sopenharmony_ci            case lo:
9451cb0ef41Sopenharmony_ci              c = "lo";
9461cb0ef41Sopenharmony_ci              break;
9471cb0ef41Sopenharmony_ci            case mi:
9481cb0ef41Sopenharmony_ci              c = "mi";
9491cb0ef41Sopenharmony_ci              break;
9501cb0ef41Sopenharmony_ci            case pl:
9511cb0ef41Sopenharmony_ci              c = "pl";
9521cb0ef41Sopenharmony_ci              break;
9531cb0ef41Sopenharmony_ci            case vs:
9541cb0ef41Sopenharmony_ci              c = "vs";
9551cb0ef41Sopenharmony_ci              break;
9561cb0ef41Sopenharmony_ci            case vc:
9571cb0ef41Sopenharmony_ci              c = "vc";
9581cb0ef41Sopenharmony_ci              break;
9591cb0ef41Sopenharmony_ci            case hi:
9601cb0ef41Sopenharmony_ci              c = "hi";
9611cb0ef41Sopenharmony_ci              break;
9621cb0ef41Sopenharmony_ci            case ls:
9631cb0ef41Sopenharmony_ci              c = "ls";
9641cb0ef41Sopenharmony_ci              break;
9651cb0ef41Sopenharmony_ci            case ge:
9661cb0ef41Sopenharmony_ci              c = "ge";
9671cb0ef41Sopenharmony_ci              break;
9681cb0ef41Sopenharmony_ci            case lt:
9691cb0ef41Sopenharmony_ci              c = "lt";
9701cb0ef41Sopenharmony_ci              break;
9711cb0ef41Sopenharmony_ci            case gt:
9721cb0ef41Sopenharmony_ci              c = "gt";
9731cb0ef41Sopenharmony_ci              break;
9741cb0ef41Sopenharmony_ci            case le:
9751cb0ef41Sopenharmony_ci              c = "le";
9761cb0ef41Sopenharmony_ci              break;
9771cb0ef41Sopenharmony_ci            case al:
9781cb0ef41Sopenharmony_ci              c = "";
9791cb0ef41Sopenharmony_ci              break;
9801cb0ef41Sopenharmony_ci            default:
9811cb0ef41Sopenharmony_ci              c = "";
9821cb0ef41Sopenharmony_ci              UNREACHABLE();
9831cb0ef41Sopenharmony_ci          }
9841cb0ef41Sopenharmony_ci        }
9851cb0ef41Sopenharmony_ci        PrintF("%s%s\n", b, c);
9861cb0ef41Sopenharmony_ci      }
9871cb0ef41Sopenharmony_ci      next(&l);
9881cb0ef41Sopenharmony_ci    }
9891cb0ef41Sopenharmony_ci  } else {
9901cb0ef41Sopenharmony_ci    PrintF("label in inconsistent state (pos = %d)\n", L->pos_);
9911cb0ef41Sopenharmony_ci  }
9921cb0ef41Sopenharmony_ci}
9931cb0ef41Sopenharmony_ci
9941cb0ef41Sopenharmony_civoid Assembler::bind_to(Label* L, int pos) {
9951cb0ef41Sopenharmony_ci  DCHECK(0 <= pos && pos <= pc_offset());  // must have a valid binding position
9961cb0ef41Sopenharmony_ci  while (L->is_linked()) {
9971cb0ef41Sopenharmony_ci    int fixup_pos = L->pos();
9981cb0ef41Sopenharmony_ci    next(L);  // call next before overwriting link with target at fixup_pos
9991cb0ef41Sopenharmony_ci    target_at_put(fixup_pos, pos);
10001cb0ef41Sopenharmony_ci  }
10011cb0ef41Sopenharmony_ci  L->bind_to(pos);
10021cb0ef41Sopenharmony_ci
10031cb0ef41Sopenharmony_ci  // Keep track of the last bound label so we don't eliminate any instructions
10041cb0ef41Sopenharmony_ci  // before a bound label.
10051cb0ef41Sopenharmony_ci  if (pos > last_bound_pos_) last_bound_pos_ = pos;
10061cb0ef41Sopenharmony_ci}
10071cb0ef41Sopenharmony_ci
10081cb0ef41Sopenharmony_civoid Assembler::bind(Label* L) {
10091cb0ef41Sopenharmony_ci  DCHECK(!L->is_bound());  // label can only be bound once
10101cb0ef41Sopenharmony_ci  bind_to(L, pc_offset());
10111cb0ef41Sopenharmony_ci}
10121cb0ef41Sopenharmony_ci
10131cb0ef41Sopenharmony_civoid Assembler::next(Label* L) {
10141cb0ef41Sopenharmony_ci  DCHECK(L->is_linked());
10151cb0ef41Sopenharmony_ci  int link = target_at(L->pos());
10161cb0ef41Sopenharmony_ci  if (link == L->pos()) {
10171cb0ef41Sopenharmony_ci    // Branch target points to the same instruction. This is the end of the link
10181cb0ef41Sopenharmony_ci    // chain.
10191cb0ef41Sopenharmony_ci    L->Unuse();
10201cb0ef41Sopenharmony_ci  } else {
10211cb0ef41Sopenharmony_ci    DCHECK_GE(link, 0);
10221cb0ef41Sopenharmony_ci    L->link_to(link);
10231cb0ef41Sopenharmony_ci  }
10241cb0ef41Sopenharmony_ci}
10251cb0ef41Sopenharmony_ci
10261cb0ef41Sopenharmony_cinamespace {
10271cb0ef41Sopenharmony_ci
10281cb0ef41Sopenharmony_ci// Low-level code emission routines depending on the addressing mode.
10291cb0ef41Sopenharmony_ci// If this returns true then you have to use the rotate_imm and immed_8
10301cb0ef41Sopenharmony_ci// that it returns, because it may have already changed the instruction
10311cb0ef41Sopenharmony_ci// to match them!
10321cb0ef41Sopenharmony_cibool FitsShifter(uint32_t imm32, uint32_t* rotate_imm, uint32_t* immed_8,
10331cb0ef41Sopenharmony_ci                 Instr* instr) {
10341cb0ef41Sopenharmony_ci  // imm32 must be unsigned.
10351cb0ef41Sopenharmony_ci  {
10361cb0ef41Sopenharmony_ci    // 32-bit immediates can be encoded as:
10371cb0ef41Sopenharmony_ci    //   (8-bit value, 2*N bit left rotation)
10381cb0ef41Sopenharmony_ci    // e.g. 0xab00 can be encoded as 0xab shifted left by 8 == 2*4, i.e.
10391cb0ef41Sopenharmony_ci    //   (0xab, 4)
10401cb0ef41Sopenharmony_ci    //
10411cb0ef41Sopenharmony_ci    // Check three categories which cover all possible shifter fits:
10421cb0ef41Sopenharmony_ci    //   1. 0x000000FF: The value is already 8-bit (no shifting necessary),
10431cb0ef41Sopenharmony_ci    //   2. 0x000FF000: The 8-bit value is somewhere in the middle of the 32-bit
10441cb0ef41Sopenharmony_ci    //                  value, and
10451cb0ef41Sopenharmony_ci    //   3. 0xF000000F: The 8-bit value is split over the beginning and end of
10461cb0ef41Sopenharmony_ci    //                  the 32-bit value.
10471cb0ef41Sopenharmony_ci
10481cb0ef41Sopenharmony_ci    // For 0x000000FF.
10491cb0ef41Sopenharmony_ci    if (imm32 <= 0xFF) {
10501cb0ef41Sopenharmony_ci      *rotate_imm = 0;
10511cb0ef41Sopenharmony_ci      *immed_8 = imm32;
10521cb0ef41Sopenharmony_ci      return true;
10531cb0ef41Sopenharmony_ci    }
10541cb0ef41Sopenharmony_ci    // For 0x000FF000, count trailing zeros and shift down to 0x000000FF. Note
10551cb0ef41Sopenharmony_ci    // that we have to round the trailing zeros down to the nearest multiple of
10561cb0ef41Sopenharmony_ci    // two, since we can only encode shifts of 2*N. Note also that we know that
10571cb0ef41Sopenharmony_ci    // imm32 isn't zero, since we already checked if it's less than 0xFF.
10581cb0ef41Sopenharmony_ci    int half_trailing_zeros = base::bits::CountTrailingZerosNonZero(imm32) / 2;
10591cb0ef41Sopenharmony_ci    uint32_t imm8 = imm32 >> (half_trailing_zeros * 2);
10601cb0ef41Sopenharmony_ci    if (imm8 <= 0xFF) {
10611cb0ef41Sopenharmony_ci      DCHECK_GT(half_trailing_zeros, 0);
10621cb0ef41Sopenharmony_ci      // Rotating right by trailing_zeros is equivalent to rotating left by
10631cb0ef41Sopenharmony_ci      // 32 - trailing_zeros. We return rotate_right / 2, so calculate
10641cb0ef41Sopenharmony_ci      // (32 - trailing_zeros)/2 == 16 - trailing_zeros/2.
10651cb0ef41Sopenharmony_ci      *rotate_imm = (16 - half_trailing_zeros);
10661cb0ef41Sopenharmony_ci      *immed_8 = imm8;
10671cb0ef41Sopenharmony_ci      return true;
10681cb0ef41Sopenharmony_ci    }
10691cb0ef41Sopenharmony_ci    // For 0xF000000F, rotate by 16 to get 0x000FF000 and continue as if it
10701cb0ef41Sopenharmony_ci    // were that case.
10711cb0ef41Sopenharmony_ci    uint32_t imm32_rot16 = base::bits::RotateLeft32(imm32, 16);
10721cb0ef41Sopenharmony_ci    half_trailing_zeros =
10731cb0ef41Sopenharmony_ci        base::bits::CountTrailingZerosNonZero(imm32_rot16) / 2;
10741cb0ef41Sopenharmony_ci    imm8 = imm32_rot16 >> (half_trailing_zeros * 2);
10751cb0ef41Sopenharmony_ci    if (imm8 <= 0xFF) {
10761cb0ef41Sopenharmony_ci      // We've rotated left by 2*8, so we can't have more than that many
10771cb0ef41Sopenharmony_ci      // trailing zeroes.
10781cb0ef41Sopenharmony_ci      DCHECK_LT(half_trailing_zeros, 8);
10791cb0ef41Sopenharmony_ci      // We've already rotated by 2*8, before calculating trailing_zeros/2,
10801cb0ef41Sopenharmony_ci      // so we need (32 - (16 + trailing_zeros))/2 == 8 - trailing_zeros/2.
10811cb0ef41Sopenharmony_ci      *rotate_imm = 8 - half_trailing_zeros;
10821cb0ef41Sopenharmony_ci      *immed_8 = imm8;
10831cb0ef41Sopenharmony_ci      return true;
10841cb0ef41Sopenharmony_ci    }
10851cb0ef41Sopenharmony_ci  }
10861cb0ef41Sopenharmony_ci  // If the opcode is one with a complementary version and the complementary
10871cb0ef41Sopenharmony_ci  // immediate fits, change the opcode.
10881cb0ef41Sopenharmony_ci  if (instr != nullptr) {
10891cb0ef41Sopenharmony_ci    if ((*instr & kMovMvnMask) == kMovMvnPattern) {
10901cb0ef41Sopenharmony_ci      if (FitsShifter(~imm32, rotate_imm, immed_8, nullptr)) {
10911cb0ef41Sopenharmony_ci        *instr ^= kMovMvnFlip;
10921cb0ef41Sopenharmony_ci        return true;
10931cb0ef41Sopenharmony_ci      } else if ((*instr & kMovLeaveCCMask) == kMovLeaveCCPattern) {
10941cb0ef41Sopenharmony_ci        if (CpuFeatures::IsSupported(ARMv7)) {
10951cb0ef41Sopenharmony_ci          if (imm32 < 0x10000) {
10961cb0ef41Sopenharmony_ci            *instr ^= kMovwLeaveCCFlip;
10971cb0ef41Sopenharmony_ci            *instr |= Assembler::EncodeMovwImmediate(imm32);
10981cb0ef41Sopenharmony_ci            *rotate_imm = *immed_8 = 0;  // Not used for movw.
10991cb0ef41Sopenharmony_ci            return true;
11001cb0ef41Sopenharmony_ci          }
11011cb0ef41Sopenharmony_ci        }
11021cb0ef41Sopenharmony_ci      }
11031cb0ef41Sopenharmony_ci    } else if ((*instr & kCmpCmnMask) == kCmpCmnPattern) {
11041cb0ef41Sopenharmony_ci      if (FitsShifter(-static_cast<int>(imm32), rotate_imm, immed_8, nullptr)) {
11051cb0ef41Sopenharmony_ci        *instr ^= kCmpCmnFlip;
11061cb0ef41Sopenharmony_ci        return true;
11071cb0ef41Sopenharmony_ci      }
11081cb0ef41Sopenharmony_ci    } else {
11091cb0ef41Sopenharmony_ci      Instr alu_insn = (*instr & kALUMask);
11101cb0ef41Sopenharmony_ci      if (alu_insn == ADD || alu_insn == SUB) {
11111cb0ef41Sopenharmony_ci        if (FitsShifter(-static_cast<int>(imm32), rotate_imm, immed_8,
11121cb0ef41Sopenharmony_ci                        nullptr)) {
11131cb0ef41Sopenharmony_ci          *instr ^= kAddSubFlip;
11141cb0ef41Sopenharmony_ci          return true;
11151cb0ef41Sopenharmony_ci        }
11161cb0ef41Sopenharmony_ci      } else if (alu_insn == AND || alu_insn == BIC) {
11171cb0ef41Sopenharmony_ci        if (FitsShifter(~imm32, rotate_imm, immed_8, nullptr)) {
11181cb0ef41Sopenharmony_ci          *instr ^= kAndBicFlip;
11191cb0ef41Sopenharmony_ci          return true;
11201cb0ef41Sopenharmony_ci        }
11211cb0ef41Sopenharmony_ci      }
11221cb0ef41Sopenharmony_ci    }
11231cb0ef41Sopenharmony_ci  }
11241cb0ef41Sopenharmony_ci  return false;
11251cb0ef41Sopenharmony_ci}
11261cb0ef41Sopenharmony_ci
11271cb0ef41Sopenharmony_ci// We have to use the temporary register for things that can be relocated even
11281cb0ef41Sopenharmony_ci// if they can be encoded in the ARM's 12 bits of immediate-offset instruction
11291cb0ef41Sopenharmony_ci// space.  There is no guarantee that the relocated location can be similarly
11301cb0ef41Sopenharmony_ci// encoded.
11311cb0ef41Sopenharmony_cibool MustOutputRelocInfo(RelocInfo::Mode rmode, const Assembler* assembler) {
11321cb0ef41Sopenharmony_ci  if (RelocInfo::IsOnlyForSerializer(rmode)) {
11331cb0ef41Sopenharmony_ci    if (assembler->predictable_code_size()) return true;
11341cb0ef41Sopenharmony_ci    return assembler->options().record_reloc_info_for_serialization;
11351cb0ef41Sopenharmony_ci  } else if (RelocInfo::IsNoInfo(rmode)) {
11361cb0ef41Sopenharmony_ci    return false;
11371cb0ef41Sopenharmony_ci  }
11381cb0ef41Sopenharmony_ci  return true;
11391cb0ef41Sopenharmony_ci}
11401cb0ef41Sopenharmony_ci
11411cb0ef41Sopenharmony_cibool UseMovImmediateLoad(const Operand& x, const Assembler* assembler) {
11421cb0ef41Sopenharmony_ci  DCHECK_NOT_NULL(assembler);
11431cb0ef41Sopenharmony_ci  if (x.MustOutputRelocInfo(assembler)) {
11441cb0ef41Sopenharmony_ci    // Prefer constant pool if data is likely to be patched.
11451cb0ef41Sopenharmony_ci    return false;
11461cb0ef41Sopenharmony_ci  } else {
11471cb0ef41Sopenharmony_ci    // Otherwise, use immediate load if movw / movt is available.
11481cb0ef41Sopenharmony_ci    return CpuFeatures::IsSupported(ARMv7);
11491cb0ef41Sopenharmony_ci  }
11501cb0ef41Sopenharmony_ci}
11511cb0ef41Sopenharmony_ci
11521cb0ef41Sopenharmony_ci}  // namespace
11531cb0ef41Sopenharmony_ci
11541cb0ef41Sopenharmony_cibool Operand::MustOutputRelocInfo(const Assembler* assembler) const {
11551cb0ef41Sopenharmony_ci  return v8::internal::MustOutputRelocInfo(rmode_, assembler);
11561cb0ef41Sopenharmony_ci}
11571cb0ef41Sopenharmony_ci
11581cb0ef41Sopenharmony_ciint Operand::InstructionsRequired(const Assembler* assembler,
11591cb0ef41Sopenharmony_ci                                  Instr instr) const {
11601cb0ef41Sopenharmony_ci  DCHECK_NOT_NULL(assembler);
11611cb0ef41Sopenharmony_ci  if (rm_.is_valid()) return 1;
11621cb0ef41Sopenharmony_ci  uint32_t dummy1, dummy2;
11631cb0ef41Sopenharmony_ci  if (MustOutputRelocInfo(assembler) ||
11641cb0ef41Sopenharmony_ci      !FitsShifter(immediate(), &dummy1, &dummy2, &instr)) {
11651cb0ef41Sopenharmony_ci    // The immediate operand cannot be encoded as a shifter operand, or use of
11661cb0ef41Sopenharmony_ci    // constant pool is required.  First account for the instructions required
11671cb0ef41Sopenharmony_ci    // for the constant pool or immediate load
11681cb0ef41Sopenharmony_ci    int instructions;
11691cb0ef41Sopenharmony_ci    if (UseMovImmediateLoad(*this, assembler)) {
11701cb0ef41Sopenharmony_ci      DCHECK(CpuFeatures::IsSupported(ARMv7));
11711cb0ef41Sopenharmony_ci      // A movw / movt immediate load.
11721cb0ef41Sopenharmony_ci      instructions = 2;
11731cb0ef41Sopenharmony_ci    } else {
11741cb0ef41Sopenharmony_ci      // A small constant pool load.
11751cb0ef41Sopenharmony_ci      instructions = 1;
11761cb0ef41Sopenharmony_ci    }
11771cb0ef41Sopenharmony_ci    if ((instr & ~kCondMask) != 13 * B21) {  // mov, S not set
11781cb0ef41Sopenharmony_ci      // For a mov or mvn instruction which doesn't set the condition
11791cb0ef41Sopenharmony_ci      // code, the constant pool or immediate load is enough, otherwise we need
11801cb0ef41Sopenharmony_ci      // to account for the actual instruction being requested.
11811cb0ef41Sopenharmony_ci      instructions += 1;
11821cb0ef41Sopenharmony_ci    }
11831cb0ef41Sopenharmony_ci    return instructions;
11841cb0ef41Sopenharmony_ci  } else {
11851cb0ef41Sopenharmony_ci    // No use of constant pool and the immediate operand can be encoded as a
11861cb0ef41Sopenharmony_ci    // shifter operand.
11871cb0ef41Sopenharmony_ci    return 1;
11881cb0ef41Sopenharmony_ci  }
11891cb0ef41Sopenharmony_ci}
11901cb0ef41Sopenharmony_ci
11911cb0ef41Sopenharmony_civoid Assembler::Move32BitImmediate(Register rd, const Operand& x,
11921cb0ef41Sopenharmony_ci                                   Condition cond) {
11931cb0ef41Sopenharmony_ci  if (UseMovImmediateLoad(x, this)) {
11941cb0ef41Sopenharmony_ci    CpuFeatureScope scope(this, ARMv7);
11951cb0ef41Sopenharmony_ci    // UseMovImmediateLoad should return false when we need to output
11961cb0ef41Sopenharmony_ci    // relocation info, since we prefer the constant pool for values that
11971cb0ef41Sopenharmony_ci    // can be patched.
11981cb0ef41Sopenharmony_ci    DCHECK(!x.MustOutputRelocInfo(this));
11991cb0ef41Sopenharmony_ci    UseScratchRegisterScope temps(this);
12001cb0ef41Sopenharmony_ci    // Re-use the destination register as a scratch if possible.
12011cb0ef41Sopenharmony_ci    Register target = rd != pc && rd != sp ? rd : temps.Acquire();
12021cb0ef41Sopenharmony_ci    uint32_t imm32 = static_cast<uint32_t>(x.immediate());
12031cb0ef41Sopenharmony_ci    movw(target, imm32 & 0xFFFF, cond);
12041cb0ef41Sopenharmony_ci    movt(target, imm32 >> 16, cond);
12051cb0ef41Sopenharmony_ci    if (target.code() != rd.code()) {
12061cb0ef41Sopenharmony_ci      mov(rd, target, LeaveCC, cond);
12071cb0ef41Sopenharmony_ci    }
12081cb0ef41Sopenharmony_ci  } else {
12091cb0ef41Sopenharmony_ci    int32_t immediate;
12101cb0ef41Sopenharmony_ci    if (x.IsHeapObjectRequest()) {
12111cb0ef41Sopenharmony_ci      RequestHeapObject(x.heap_object_request());
12121cb0ef41Sopenharmony_ci      immediate = 0;
12131cb0ef41Sopenharmony_ci    } else {
12141cb0ef41Sopenharmony_ci      immediate = x.immediate();
12151cb0ef41Sopenharmony_ci    }
12161cb0ef41Sopenharmony_ci    ConstantPoolAddEntry(pc_offset(), x.rmode_, immediate);
12171cb0ef41Sopenharmony_ci    ldr_pcrel(rd, 0, cond);
12181cb0ef41Sopenharmony_ci  }
12191cb0ef41Sopenharmony_ci}
12201cb0ef41Sopenharmony_ci
12211cb0ef41Sopenharmony_civoid Assembler::AddrMode1(Instr instr, Register rd, Register rn,
12221cb0ef41Sopenharmony_ci                          const Operand& x) {
12231cb0ef41Sopenharmony_ci  CheckBuffer();
12241cb0ef41Sopenharmony_ci  uint32_t opcode = instr & kOpCodeMask;
12251cb0ef41Sopenharmony_ci  bool set_flags = (instr & S) != 0;
12261cb0ef41Sopenharmony_ci  DCHECK((opcode == ADC) || (opcode == ADD) || (opcode == AND) ||
12271cb0ef41Sopenharmony_ci         (opcode == BIC) || (opcode == EOR) || (opcode == ORR) ||
12281cb0ef41Sopenharmony_ci         (opcode == RSB) || (opcode == RSC) || (opcode == SBC) ||
12291cb0ef41Sopenharmony_ci         (opcode == SUB) || (opcode == CMN) || (opcode == CMP) ||
12301cb0ef41Sopenharmony_ci         (opcode == TEQ) || (opcode == TST) || (opcode == MOV) ||
12311cb0ef41Sopenharmony_ci         (opcode == MVN));
12321cb0ef41Sopenharmony_ci  // For comparison instructions, rd is not defined.
12331cb0ef41Sopenharmony_ci  DCHECK(rd.is_valid() || (opcode == CMN) || (opcode == CMP) ||
12341cb0ef41Sopenharmony_ci         (opcode == TEQ) || (opcode == TST));
12351cb0ef41Sopenharmony_ci  // For move instructions, rn is not defined.
12361cb0ef41Sopenharmony_ci  DCHECK(rn.is_valid() || (opcode == MOV) || (opcode == MVN));
12371cb0ef41Sopenharmony_ci  DCHECK(rd.is_valid() || rn.is_valid());
12381cb0ef41Sopenharmony_ci  DCHECK_EQ(instr & ~(kCondMask | kOpCodeMask | S), 0);
12391cb0ef41Sopenharmony_ci  if (!AddrMode1TryEncodeOperand(&instr, x)) {
12401cb0ef41Sopenharmony_ci    DCHECK(x.IsImmediate());
12411cb0ef41Sopenharmony_ci    // Upon failure to encode, the opcode should not have changed.
12421cb0ef41Sopenharmony_ci    DCHECK(opcode == (instr & kOpCodeMask));
12431cb0ef41Sopenharmony_ci    UseScratchRegisterScope temps(this);
12441cb0ef41Sopenharmony_ci    Condition cond = Instruction::ConditionField(instr);
12451cb0ef41Sopenharmony_ci    if ((opcode == MOV) && !set_flags) {
12461cb0ef41Sopenharmony_ci      // Generate a sequence of mov instructions or a load from the constant
12471cb0ef41Sopenharmony_ci      // pool only for a MOV instruction which does not set the flags.
12481cb0ef41Sopenharmony_ci      DCHECK(!rn.is_valid());
12491cb0ef41Sopenharmony_ci      Move32BitImmediate(rd, x, cond);
12501cb0ef41Sopenharmony_ci    } else if ((opcode == ADD) && !set_flags && (rd == rn) &&
12511cb0ef41Sopenharmony_ci               !temps.CanAcquire()) {
12521cb0ef41Sopenharmony_ci      // Split the operation into a sequence of additions if we cannot use a
12531cb0ef41Sopenharmony_ci      // scratch register. In this case, we cannot re-use rn and the assembler
12541cb0ef41Sopenharmony_ci      // does not have any scratch registers to spare.
12551cb0ef41Sopenharmony_ci      uint32_t imm = x.immediate();
12561cb0ef41Sopenharmony_ci      do {
12571cb0ef41Sopenharmony_ci        // The immediate encoding format is composed of 8 bits of data and 4
12581cb0ef41Sopenharmony_ci        // bits encoding a rotation. Each of the 16 possible rotations accounts
12591cb0ef41Sopenharmony_ci        // for a rotation by an even number.
12601cb0ef41Sopenharmony_ci        //   4 bits -> 16 rotations possible
12611cb0ef41Sopenharmony_ci        //          -> 16 rotations of 2 bits each fits in a 32-bit value.
12621cb0ef41Sopenharmony_ci        // This means that finding the even number of trailing zeroes of the
12631cb0ef41Sopenharmony_ci        // immediate allows us to more efficiently split it:
12641cb0ef41Sopenharmony_ci        int trailing_zeroes = base::bits::CountTrailingZeros(imm) & ~1u;
12651cb0ef41Sopenharmony_ci        uint32_t mask = (0xFF << trailing_zeroes);
12661cb0ef41Sopenharmony_ci        add(rd, rd, Operand(imm & mask), LeaveCC, cond);
12671cb0ef41Sopenharmony_ci        imm = imm & ~mask;
12681cb0ef41Sopenharmony_ci      } while (!ImmediateFitsAddrMode1Instruction(imm));
12691cb0ef41Sopenharmony_ci      add(rd, rd, Operand(imm), LeaveCC, cond);
12701cb0ef41Sopenharmony_ci    } else {
12711cb0ef41Sopenharmony_ci      // The immediate operand cannot be encoded as a shifter operand, so load
12721cb0ef41Sopenharmony_ci      // it first to a scratch register and change the original instruction to
12731cb0ef41Sopenharmony_ci      // use it.
12741cb0ef41Sopenharmony_ci      // Re-use the destination register if possible.
12751cb0ef41Sopenharmony_ci      Register scratch = (rd.is_valid() && rd != rn && rd != pc && rd != sp)
12761cb0ef41Sopenharmony_ci                             ? rd
12771cb0ef41Sopenharmony_ci                             : temps.Acquire();
12781cb0ef41Sopenharmony_ci      mov(scratch, x, LeaveCC, cond);
12791cb0ef41Sopenharmony_ci      AddrMode1(instr, rd, rn, Operand(scratch));
12801cb0ef41Sopenharmony_ci    }
12811cb0ef41Sopenharmony_ci    return;
12821cb0ef41Sopenharmony_ci  }
12831cb0ef41Sopenharmony_ci  if (!rd.is_valid()) {
12841cb0ef41Sopenharmony_ci    // Emit a comparison instruction.
12851cb0ef41Sopenharmony_ci    emit(instr | rn.code() * B16);
12861cb0ef41Sopenharmony_ci  } else if (!rn.is_valid()) {
12871cb0ef41Sopenharmony_ci    // Emit a move instruction. If the operand is a register-shifted register,
12881cb0ef41Sopenharmony_ci    // then prevent the destination from being PC as this is unpredictable.
12891cb0ef41Sopenharmony_ci    DCHECK(!x.IsRegisterShiftedRegister() || rd != pc);
12901cb0ef41Sopenharmony_ci    emit(instr | rd.code() * B12);
12911cb0ef41Sopenharmony_ci  } else {
12921cb0ef41Sopenharmony_ci    emit(instr | rn.code() * B16 | rd.code() * B12);
12931cb0ef41Sopenharmony_ci  }
12941cb0ef41Sopenharmony_ci  if (rn == pc || x.rm_ == pc) {
12951cb0ef41Sopenharmony_ci    // Block constant pool emission for one instruction after reading pc.
12961cb0ef41Sopenharmony_ci    BlockConstPoolFor(1);
12971cb0ef41Sopenharmony_ci  }
12981cb0ef41Sopenharmony_ci}
12991cb0ef41Sopenharmony_ci
13001cb0ef41Sopenharmony_cibool Assembler::AddrMode1TryEncodeOperand(Instr* instr, const Operand& x) {
13011cb0ef41Sopenharmony_ci  if (x.IsImmediate()) {
13021cb0ef41Sopenharmony_ci    // Immediate.
13031cb0ef41Sopenharmony_ci    uint32_t rotate_imm;
13041cb0ef41Sopenharmony_ci    uint32_t immed_8;
13051cb0ef41Sopenharmony_ci    if (x.MustOutputRelocInfo(this) ||
13061cb0ef41Sopenharmony_ci        !FitsShifter(x.immediate(), &rotate_imm, &immed_8, instr)) {
13071cb0ef41Sopenharmony_ci      // Let the caller handle generating multiple instructions.
13081cb0ef41Sopenharmony_ci      return false;
13091cb0ef41Sopenharmony_ci    }
13101cb0ef41Sopenharmony_ci    *instr |= I | rotate_imm * B8 | immed_8;
13111cb0ef41Sopenharmony_ci  } else if (x.IsImmediateShiftedRegister()) {
13121cb0ef41Sopenharmony_ci    *instr |= x.shift_imm_ * B7 | x.shift_op_ | x.rm_.code();
13131cb0ef41Sopenharmony_ci  } else {
13141cb0ef41Sopenharmony_ci    DCHECK(x.IsRegisterShiftedRegister());
13151cb0ef41Sopenharmony_ci    // It is unpredictable to use the PC in this case.
13161cb0ef41Sopenharmony_ci    DCHECK(x.rm_ != pc && x.rs_ != pc);
13171cb0ef41Sopenharmony_ci    *instr |= x.rs_.code() * B8 | x.shift_op_ | B4 | x.rm_.code();
13181cb0ef41Sopenharmony_ci  }
13191cb0ef41Sopenharmony_ci
13201cb0ef41Sopenharmony_ci  return true;
13211cb0ef41Sopenharmony_ci}
13221cb0ef41Sopenharmony_ci
13231cb0ef41Sopenharmony_civoid Assembler::AddrMode2(Instr instr, Register rd, const MemOperand& x) {
13241cb0ef41Sopenharmony_ci  DCHECK((instr & ~(kCondMask | B | L)) == B26);
13251cb0ef41Sopenharmony_ci  // This method does not handle pc-relative addresses. ldr_pcrel() should be
13261cb0ef41Sopenharmony_ci  // used instead.
13271cb0ef41Sopenharmony_ci  DCHECK(x.rn_ != pc);
13281cb0ef41Sopenharmony_ci  int am = x.am_;
13291cb0ef41Sopenharmony_ci  if (!x.rm_.is_valid()) {
13301cb0ef41Sopenharmony_ci    // Immediate offset.
13311cb0ef41Sopenharmony_ci    int offset_12 = x.offset_;
13321cb0ef41Sopenharmony_ci    if (offset_12 < 0) {
13331cb0ef41Sopenharmony_ci      offset_12 = -offset_12;
13341cb0ef41Sopenharmony_ci      am ^= U;
13351cb0ef41Sopenharmony_ci    }
13361cb0ef41Sopenharmony_ci    if (!is_uint12(offset_12)) {
13371cb0ef41Sopenharmony_ci      // Immediate offset cannot be encoded, load it first to a scratch
13381cb0ef41Sopenharmony_ci      // register.
13391cb0ef41Sopenharmony_ci      UseScratchRegisterScope temps(this);
13401cb0ef41Sopenharmony_ci      // Allow re-using rd for load instructions if possible.
13411cb0ef41Sopenharmony_ci      bool is_load = (instr & L) == L;
13421cb0ef41Sopenharmony_ci      Register scratch = (is_load && rd != x.rn_ && rd != pc && rd != sp)
13431cb0ef41Sopenharmony_ci                             ? rd
13441cb0ef41Sopenharmony_ci                             : temps.Acquire();
13451cb0ef41Sopenharmony_ci      mov(scratch, Operand(x.offset_), LeaveCC,
13461cb0ef41Sopenharmony_ci          Instruction::ConditionField(instr));
13471cb0ef41Sopenharmony_ci      AddrMode2(instr, rd, MemOperand(x.rn_, scratch, x.am_));
13481cb0ef41Sopenharmony_ci      return;
13491cb0ef41Sopenharmony_ci    }
13501cb0ef41Sopenharmony_ci    DCHECK_GE(offset_12, 0);  // no masking needed
13511cb0ef41Sopenharmony_ci    instr |= offset_12;
13521cb0ef41Sopenharmony_ci  } else {
13531cb0ef41Sopenharmony_ci    // Register offset (shift_imm_ and shift_op_ are 0) or scaled
13541cb0ef41Sopenharmony_ci    // register offset the constructors make sure than both shift_imm_
13551cb0ef41Sopenharmony_ci    // and shift_op_ are initialized.
13561cb0ef41Sopenharmony_ci    DCHECK(x.rm_ != pc);
13571cb0ef41Sopenharmony_ci    instr |= B25 | x.shift_imm_ * B7 | x.shift_op_ | x.rm_.code();
13581cb0ef41Sopenharmony_ci  }
13591cb0ef41Sopenharmony_ci  DCHECK((am & (P | W)) == P || x.rn_ != pc);  // no pc base with writeback
13601cb0ef41Sopenharmony_ci  emit(instr | am | x.rn_.code() * B16 | rd.code() * B12);
13611cb0ef41Sopenharmony_ci}
13621cb0ef41Sopenharmony_ci
13631cb0ef41Sopenharmony_civoid Assembler::AddrMode3(Instr instr, Register rd, const MemOperand& x) {
13641cb0ef41Sopenharmony_ci  DCHECK((instr & ~(kCondMask | L | S6 | H)) == (B4 | B7));
13651cb0ef41Sopenharmony_ci  DCHECK(x.rn_.is_valid());
13661cb0ef41Sopenharmony_ci  // This method does not handle pc-relative addresses. ldr_pcrel() should be
13671cb0ef41Sopenharmony_ci  // used instead.
13681cb0ef41Sopenharmony_ci  DCHECK(x.rn_ != pc);
13691cb0ef41Sopenharmony_ci  int am = x.am_;
13701cb0ef41Sopenharmony_ci  bool is_load = (instr & L) == L;
13711cb0ef41Sopenharmony_ci  if (!x.rm_.is_valid()) {
13721cb0ef41Sopenharmony_ci    // Immediate offset.
13731cb0ef41Sopenharmony_ci    int offset_8 = x.offset_;
13741cb0ef41Sopenharmony_ci    if (offset_8 < 0) {
13751cb0ef41Sopenharmony_ci      offset_8 = -offset_8;
13761cb0ef41Sopenharmony_ci      am ^= U;
13771cb0ef41Sopenharmony_ci    }
13781cb0ef41Sopenharmony_ci    if (!is_uint8(offset_8)) {
13791cb0ef41Sopenharmony_ci      // Immediate offset cannot be encoded, load it first to a scratch
13801cb0ef41Sopenharmony_ci      // register.
13811cb0ef41Sopenharmony_ci      UseScratchRegisterScope temps(this);
13821cb0ef41Sopenharmony_ci      // Allow re-using rd for load instructions if possible.
13831cb0ef41Sopenharmony_ci      Register scratch = (is_load && rd != x.rn_ && rd != pc && rd != sp)
13841cb0ef41Sopenharmony_ci                             ? rd
13851cb0ef41Sopenharmony_ci                             : temps.Acquire();
13861cb0ef41Sopenharmony_ci      mov(scratch, Operand(x.offset_), LeaveCC,
13871cb0ef41Sopenharmony_ci          Instruction::ConditionField(instr));
13881cb0ef41Sopenharmony_ci      AddrMode3(instr, rd, MemOperand(x.rn_, scratch, x.am_));
13891cb0ef41Sopenharmony_ci      return;
13901cb0ef41Sopenharmony_ci    }
13911cb0ef41Sopenharmony_ci    DCHECK_GE(offset_8, 0);  // no masking needed
13921cb0ef41Sopenharmony_ci    instr |= B | (offset_8 >> 4) * B8 | (offset_8 & 0xF);
13931cb0ef41Sopenharmony_ci  } else if (x.shift_imm_ != 0) {
13941cb0ef41Sopenharmony_ci    // Scaled register offsets are not supported, compute the offset separately
13951cb0ef41Sopenharmony_ci    // to a scratch register.
13961cb0ef41Sopenharmony_ci    UseScratchRegisterScope temps(this);
13971cb0ef41Sopenharmony_ci    // Allow re-using rd for load instructions if possible.
13981cb0ef41Sopenharmony_ci    Register scratch =
13991cb0ef41Sopenharmony_ci        (is_load && rd != x.rn_ && rd != pc && rd != sp) ? rd : temps.Acquire();
14001cb0ef41Sopenharmony_ci    mov(scratch, Operand(x.rm_, x.shift_op_, x.shift_imm_), LeaveCC,
14011cb0ef41Sopenharmony_ci        Instruction::ConditionField(instr));
14021cb0ef41Sopenharmony_ci    AddrMode3(instr, rd, MemOperand(x.rn_, scratch, x.am_));
14031cb0ef41Sopenharmony_ci    return;
14041cb0ef41Sopenharmony_ci  } else {
14051cb0ef41Sopenharmony_ci    // Register offset.
14061cb0ef41Sopenharmony_ci    DCHECK((am & (P | W)) == P || x.rm_ != pc);  // no pc index with writeback
14071cb0ef41Sopenharmony_ci    instr |= x.rm_.code();
14081cb0ef41Sopenharmony_ci  }
14091cb0ef41Sopenharmony_ci  DCHECK((am & (P | W)) == P || x.rn_ != pc);  // no pc base with writeback
14101cb0ef41Sopenharmony_ci  emit(instr | am | x.rn_.code() * B16 | rd.code() * B12);
14111cb0ef41Sopenharmony_ci}
14121cb0ef41Sopenharmony_ci
14131cb0ef41Sopenharmony_civoid Assembler::AddrMode4(Instr instr, Register rn, RegList rl) {
14141cb0ef41Sopenharmony_ci  DCHECK((instr & ~(kCondMask | P | U | W | L)) == B27);
14151cb0ef41Sopenharmony_ci  DCHECK(!rl.is_empty());
14161cb0ef41Sopenharmony_ci  DCHECK(rn != pc);
14171cb0ef41Sopenharmony_ci  emit(instr | rn.code() * B16 | rl.bits());
14181cb0ef41Sopenharmony_ci}
14191cb0ef41Sopenharmony_ci
14201cb0ef41Sopenharmony_civoid Assembler::AddrMode5(Instr instr, CRegister crd, const MemOperand& x) {
14211cb0ef41Sopenharmony_ci  // Unindexed addressing is not encoded by this function.
14221cb0ef41Sopenharmony_ci  DCHECK_EQ((B27 | B26),
14231cb0ef41Sopenharmony_ci            (instr & ~(kCondMask | kCoprocessorMask | P | U | N | W | L)));
14241cb0ef41Sopenharmony_ci  DCHECK(x.rn_.is_valid() && !x.rm_.is_valid());
14251cb0ef41Sopenharmony_ci  int am = x.am_;
14261cb0ef41Sopenharmony_ci  int offset_8 = x.offset_;
14271cb0ef41Sopenharmony_ci  DCHECK_EQ(offset_8 & 3, 0);  // offset must be an aligned word offset
14281cb0ef41Sopenharmony_ci  offset_8 >>= 2;
14291cb0ef41Sopenharmony_ci  if (offset_8 < 0) {
14301cb0ef41Sopenharmony_ci    offset_8 = -offset_8;
14311cb0ef41Sopenharmony_ci    am ^= U;
14321cb0ef41Sopenharmony_ci  }
14331cb0ef41Sopenharmony_ci  DCHECK(is_uint8(offset_8));  // unsigned word offset must fit in a byte
14341cb0ef41Sopenharmony_ci  DCHECK((am & (P | W)) == P || x.rn_ != pc);  // no pc base with writeback
14351cb0ef41Sopenharmony_ci
14361cb0ef41Sopenharmony_ci  // Post-indexed addressing requires W == 1; different than in AddrMode2/3.
14371cb0ef41Sopenharmony_ci  if ((am & P) == 0) am |= W;
14381cb0ef41Sopenharmony_ci
14391cb0ef41Sopenharmony_ci  DCHECK_GE(offset_8, 0);  // no masking needed
14401cb0ef41Sopenharmony_ci  emit(instr | am | x.rn_.code() * B16 | crd.code() * B12 | offset_8);
14411cb0ef41Sopenharmony_ci}
14421cb0ef41Sopenharmony_ci
14431cb0ef41Sopenharmony_ciint Assembler::branch_offset(Label* L) {
14441cb0ef41Sopenharmony_ci  int target_pos;
14451cb0ef41Sopenharmony_ci  if (L->is_bound()) {
14461cb0ef41Sopenharmony_ci    target_pos = L->pos();
14471cb0ef41Sopenharmony_ci  } else {
14481cb0ef41Sopenharmony_ci    if (L->is_linked()) {
14491cb0ef41Sopenharmony_ci      // Point to previous instruction that uses the link.
14501cb0ef41Sopenharmony_ci      target_pos = L->pos();
14511cb0ef41Sopenharmony_ci    } else {
14521cb0ef41Sopenharmony_ci      // First entry of the link chain points to itself.
14531cb0ef41Sopenharmony_ci      target_pos = pc_offset();
14541cb0ef41Sopenharmony_ci    }
14551cb0ef41Sopenharmony_ci    L->link_to(pc_offset());
14561cb0ef41Sopenharmony_ci  }
14571cb0ef41Sopenharmony_ci
14581cb0ef41Sopenharmony_ci  return target_pos - (pc_offset() + Instruction::kPcLoadDelta);
14591cb0ef41Sopenharmony_ci}
14601cb0ef41Sopenharmony_ci
14611cb0ef41Sopenharmony_ci// Branch instructions.
14621cb0ef41Sopenharmony_civoid Assembler::b(int branch_offset, Condition cond, RelocInfo::Mode rmode) {
14631cb0ef41Sopenharmony_ci  if (!RelocInfo::IsNoInfo(rmode)) RecordRelocInfo(rmode);
14641cb0ef41Sopenharmony_ci  DCHECK_EQ(branch_offset & 3, 0);
14651cb0ef41Sopenharmony_ci  int imm24 = branch_offset >> 2;
14661cb0ef41Sopenharmony_ci  const bool b_imm_check = is_int24(imm24);
14671cb0ef41Sopenharmony_ci  CHECK(b_imm_check);
14681cb0ef41Sopenharmony_ci
14691cb0ef41Sopenharmony_ci  // Block the emission of the constant pool before the next instruction.
14701cb0ef41Sopenharmony_ci  // Otherwise the passed-in branch offset would be off.
14711cb0ef41Sopenharmony_ci  BlockConstPoolFor(1);
14721cb0ef41Sopenharmony_ci
14731cb0ef41Sopenharmony_ci  emit(cond | B27 | B25 | (imm24 & kImm24Mask));
14741cb0ef41Sopenharmony_ci
14751cb0ef41Sopenharmony_ci  if (cond == al) {
14761cb0ef41Sopenharmony_ci    // Dead code is a good location to emit the constant pool.
14771cb0ef41Sopenharmony_ci    CheckConstPool(false, false);
14781cb0ef41Sopenharmony_ci  }
14791cb0ef41Sopenharmony_ci}
14801cb0ef41Sopenharmony_ci
14811cb0ef41Sopenharmony_civoid Assembler::bl(int branch_offset, Condition cond, RelocInfo::Mode rmode) {
14821cb0ef41Sopenharmony_ci  if (!RelocInfo::IsNoInfo(rmode)) RecordRelocInfo(rmode);
14831cb0ef41Sopenharmony_ci  DCHECK_EQ(branch_offset & 3, 0);
14841cb0ef41Sopenharmony_ci  int imm24 = branch_offset >> 2;
14851cb0ef41Sopenharmony_ci  const bool bl_imm_check = is_int24(imm24);
14861cb0ef41Sopenharmony_ci  CHECK(bl_imm_check);
14871cb0ef41Sopenharmony_ci
14881cb0ef41Sopenharmony_ci  // Block the emission of the constant pool before the next instruction.
14891cb0ef41Sopenharmony_ci  // Otherwise the passed-in branch offset would be off.
14901cb0ef41Sopenharmony_ci  BlockConstPoolFor(1);
14911cb0ef41Sopenharmony_ci
14921cb0ef41Sopenharmony_ci  emit(cond | B27 | B25 | B24 | (imm24 & kImm24Mask));
14931cb0ef41Sopenharmony_ci}
14941cb0ef41Sopenharmony_ci
14951cb0ef41Sopenharmony_civoid Assembler::blx(int branch_offset) {
14961cb0ef41Sopenharmony_ci  DCHECK_EQ(branch_offset & 1, 0);
14971cb0ef41Sopenharmony_ci  int h = ((branch_offset & 2) >> 1) * B24;
14981cb0ef41Sopenharmony_ci  int imm24 = branch_offset >> 2;
14991cb0ef41Sopenharmony_ci  const bool blx_imm_check = is_int24(imm24);
15001cb0ef41Sopenharmony_ci  CHECK(blx_imm_check);
15011cb0ef41Sopenharmony_ci
15021cb0ef41Sopenharmony_ci  // Block the emission of the constant pool before the next instruction.
15031cb0ef41Sopenharmony_ci  // Otherwise the passed-in branch offset would be off.
15041cb0ef41Sopenharmony_ci  BlockConstPoolFor(1);
15051cb0ef41Sopenharmony_ci
15061cb0ef41Sopenharmony_ci  emit(kSpecialCondition | B27 | B25 | h | (imm24 & kImm24Mask));
15071cb0ef41Sopenharmony_ci}
15081cb0ef41Sopenharmony_ci
15091cb0ef41Sopenharmony_civoid Assembler::blx(Register target, Condition cond) {
15101cb0ef41Sopenharmony_ci  DCHECK(target != pc);
15111cb0ef41Sopenharmony_ci  emit(cond | B24 | B21 | 15 * B16 | 15 * B12 | 15 * B8 | BLX | target.code());
15121cb0ef41Sopenharmony_ci}
15131cb0ef41Sopenharmony_ci
15141cb0ef41Sopenharmony_civoid Assembler::bx(Register target, Condition cond) {
15151cb0ef41Sopenharmony_ci  DCHECK(target != pc);  // use of pc is actually allowed, but discouraged
15161cb0ef41Sopenharmony_ci  emit(cond | B24 | B21 | 15 * B16 | 15 * B12 | 15 * B8 | BX | target.code());
15171cb0ef41Sopenharmony_ci}
15181cb0ef41Sopenharmony_ci
15191cb0ef41Sopenharmony_civoid Assembler::b(Label* L, Condition cond) {
15201cb0ef41Sopenharmony_ci  CheckBuffer();
15211cb0ef41Sopenharmony_ci  b(branch_offset(L), cond);
15221cb0ef41Sopenharmony_ci}
15231cb0ef41Sopenharmony_ci
15241cb0ef41Sopenharmony_civoid Assembler::bl(Label* L, Condition cond) {
15251cb0ef41Sopenharmony_ci  CheckBuffer();
15261cb0ef41Sopenharmony_ci  bl(branch_offset(L), cond);
15271cb0ef41Sopenharmony_ci}
15281cb0ef41Sopenharmony_ci
15291cb0ef41Sopenharmony_civoid Assembler::blx(Label* L) {
15301cb0ef41Sopenharmony_ci  CheckBuffer();
15311cb0ef41Sopenharmony_ci  blx(branch_offset(L));
15321cb0ef41Sopenharmony_ci}
15331cb0ef41Sopenharmony_ci
15341cb0ef41Sopenharmony_ci// Data-processing instructions.
15351cb0ef41Sopenharmony_ci
15361cb0ef41Sopenharmony_civoid Assembler::and_(Register dst, Register src1, const Operand& src2, SBit s,
15371cb0ef41Sopenharmony_ci                     Condition cond) {
15381cb0ef41Sopenharmony_ci  AddrMode1(cond | AND | s, dst, src1, src2);
15391cb0ef41Sopenharmony_ci}
15401cb0ef41Sopenharmony_ci
15411cb0ef41Sopenharmony_civoid Assembler::and_(Register dst, Register src1, Register src2, SBit s,
15421cb0ef41Sopenharmony_ci                     Condition cond) {
15431cb0ef41Sopenharmony_ci  and_(dst, src1, Operand(src2), s, cond);
15441cb0ef41Sopenharmony_ci}
15451cb0ef41Sopenharmony_ci
15461cb0ef41Sopenharmony_civoid Assembler::eor(Register dst, Register src1, const Operand& src2, SBit s,
15471cb0ef41Sopenharmony_ci                    Condition cond) {
15481cb0ef41Sopenharmony_ci  AddrMode1(cond | EOR | s, dst, src1, src2);
15491cb0ef41Sopenharmony_ci}
15501cb0ef41Sopenharmony_ci
15511cb0ef41Sopenharmony_civoid Assembler::eor(Register dst, Register src1, Register src2, SBit s,
15521cb0ef41Sopenharmony_ci                    Condition cond) {
15531cb0ef41Sopenharmony_ci  AddrMode1(cond | EOR | s, dst, src1, Operand(src2));
15541cb0ef41Sopenharmony_ci}
15551cb0ef41Sopenharmony_ci
15561cb0ef41Sopenharmony_civoid Assembler::sub(Register dst, Register src1, const Operand& src2, SBit s,
15571cb0ef41Sopenharmony_ci                    Condition cond) {
15581cb0ef41Sopenharmony_ci  AddrMode1(cond | SUB | s, dst, src1, src2);
15591cb0ef41Sopenharmony_ci}
15601cb0ef41Sopenharmony_ci
15611cb0ef41Sopenharmony_civoid Assembler::sub(Register dst, Register src1, Register src2, SBit s,
15621cb0ef41Sopenharmony_ci                    Condition cond) {
15631cb0ef41Sopenharmony_ci  sub(dst, src1, Operand(src2), s, cond);
15641cb0ef41Sopenharmony_ci}
15651cb0ef41Sopenharmony_ci
15661cb0ef41Sopenharmony_civoid Assembler::rsb(Register dst, Register src1, const Operand& src2, SBit s,
15671cb0ef41Sopenharmony_ci                    Condition cond) {
15681cb0ef41Sopenharmony_ci  AddrMode1(cond | RSB | s, dst, src1, src2);
15691cb0ef41Sopenharmony_ci}
15701cb0ef41Sopenharmony_ci
15711cb0ef41Sopenharmony_civoid Assembler::add(Register dst, Register src1, const Operand& src2, SBit s,
15721cb0ef41Sopenharmony_ci                    Condition cond) {
15731cb0ef41Sopenharmony_ci  AddrMode1(cond | ADD | s, dst, src1, src2);
15741cb0ef41Sopenharmony_ci}
15751cb0ef41Sopenharmony_ci
15761cb0ef41Sopenharmony_civoid Assembler::add(Register dst, Register src1, Register src2, SBit s,
15771cb0ef41Sopenharmony_ci                    Condition cond) {
15781cb0ef41Sopenharmony_ci  add(dst, src1, Operand(src2), s, cond);
15791cb0ef41Sopenharmony_ci}
15801cb0ef41Sopenharmony_ci
15811cb0ef41Sopenharmony_civoid Assembler::adc(Register dst, Register src1, const Operand& src2, SBit s,
15821cb0ef41Sopenharmony_ci                    Condition cond) {
15831cb0ef41Sopenharmony_ci  AddrMode1(cond | ADC | s, dst, src1, src2);
15841cb0ef41Sopenharmony_ci}
15851cb0ef41Sopenharmony_ci
15861cb0ef41Sopenharmony_civoid Assembler::sbc(Register dst, Register src1, const Operand& src2, SBit s,
15871cb0ef41Sopenharmony_ci                    Condition cond) {
15881cb0ef41Sopenharmony_ci  AddrMode1(cond | SBC | s, dst, src1, src2);
15891cb0ef41Sopenharmony_ci}
15901cb0ef41Sopenharmony_ci
15911cb0ef41Sopenharmony_civoid Assembler::rsc(Register dst, Register src1, const Operand& src2, SBit s,
15921cb0ef41Sopenharmony_ci                    Condition cond) {
15931cb0ef41Sopenharmony_ci  AddrMode1(cond | RSC | s, dst, src1, src2);
15941cb0ef41Sopenharmony_ci}
15951cb0ef41Sopenharmony_ci
15961cb0ef41Sopenharmony_civoid Assembler::tst(Register src1, const Operand& src2, Condition cond) {
15971cb0ef41Sopenharmony_ci  AddrMode1(cond | TST | S, no_reg, src1, src2);
15981cb0ef41Sopenharmony_ci}
15991cb0ef41Sopenharmony_ci
16001cb0ef41Sopenharmony_civoid Assembler::tst(Register src1, Register src2, Condition cond) {
16011cb0ef41Sopenharmony_ci  tst(src1, Operand(src2), cond);
16021cb0ef41Sopenharmony_ci}
16031cb0ef41Sopenharmony_ci
16041cb0ef41Sopenharmony_civoid Assembler::teq(Register src1, const Operand& src2, Condition cond) {
16051cb0ef41Sopenharmony_ci  AddrMode1(cond | TEQ | S, no_reg, src1, src2);
16061cb0ef41Sopenharmony_ci}
16071cb0ef41Sopenharmony_ci
16081cb0ef41Sopenharmony_civoid Assembler::cmp(Register src1, const Operand& src2, Condition cond) {
16091cb0ef41Sopenharmony_ci  AddrMode1(cond | CMP | S, no_reg, src1, src2);
16101cb0ef41Sopenharmony_ci}
16111cb0ef41Sopenharmony_ci
16121cb0ef41Sopenharmony_civoid Assembler::cmp(Register src1, Register src2, Condition cond) {
16131cb0ef41Sopenharmony_ci  cmp(src1, Operand(src2), cond);
16141cb0ef41Sopenharmony_ci}
16151cb0ef41Sopenharmony_ci
16161cb0ef41Sopenharmony_civoid Assembler::cmp_raw_immediate(Register src, int raw_immediate,
16171cb0ef41Sopenharmony_ci                                  Condition cond) {
16181cb0ef41Sopenharmony_ci  DCHECK(is_uint12(raw_immediate));
16191cb0ef41Sopenharmony_ci  emit(cond | I | CMP | S | src.code() << 16 | raw_immediate);
16201cb0ef41Sopenharmony_ci}
16211cb0ef41Sopenharmony_ci
16221cb0ef41Sopenharmony_civoid Assembler::cmn(Register src1, const Operand& src2, Condition cond) {
16231cb0ef41Sopenharmony_ci  AddrMode1(cond | CMN | S, no_reg, src1, src2);
16241cb0ef41Sopenharmony_ci}
16251cb0ef41Sopenharmony_ci
16261cb0ef41Sopenharmony_civoid Assembler::orr(Register dst, Register src1, const Operand& src2, SBit s,
16271cb0ef41Sopenharmony_ci                    Condition cond) {
16281cb0ef41Sopenharmony_ci  AddrMode1(cond | ORR | s, dst, src1, src2);
16291cb0ef41Sopenharmony_ci}
16301cb0ef41Sopenharmony_ci
16311cb0ef41Sopenharmony_civoid Assembler::orr(Register dst, Register src1, Register src2, SBit s,
16321cb0ef41Sopenharmony_ci                    Condition cond) {
16331cb0ef41Sopenharmony_ci  orr(dst, src1, Operand(src2), s, cond);
16341cb0ef41Sopenharmony_ci}
16351cb0ef41Sopenharmony_ci
16361cb0ef41Sopenharmony_civoid Assembler::mov(Register dst, const Operand& src, SBit s, Condition cond) {
16371cb0ef41Sopenharmony_ci  // Don't allow nop instructions in the form mov rn, rn to be generated using
16381cb0ef41Sopenharmony_ci  // the mov instruction. They must be generated using nop(int/NopMarkerTypes).
16391cb0ef41Sopenharmony_ci  DCHECK(!(src.IsRegister() && src.rm() == dst && s == LeaveCC && cond == al));
16401cb0ef41Sopenharmony_ci  AddrMode1(cond | MOV | s, dst, no_reg, src);
16411cb0ef41Sopenharmony_ci}
16421cb0ef41Sopenharmony_ci
16431cb0ef41Sopenharmony_civoid Assembler::mov(Register dst, Register src, SBit s, Condition cond) {
16441cb0ef41Sopenharmony_ci  mov(dst, Operand(src), s, cond);
16451cb0ef41Sopenharmony_ci}
16461cb0ef41Sopenharmony_ci
16471cb0ef41Sopenharmony_civoid Assembler::mov_label_offset(Register dst, Label* label) {
16481cb0ef41Sopenharmony_ci  if (label->is_bound()) {
16491cb0ef41Sopenharmony_ci    mov(dst, Operand(label->pos() + (Code::kHeaderSize - kHeapObjectTag)));
16501cb0ef41Sopenharmony_ci  } else {
16511cb0ef41Sopenharmony_ci    // Emit the link to the label in the code stream followed by extra nop
16521cb0ef41Sopenharmony_ci    // instructions.
16531cb0ef41Sopenharmony_ci    // If the label is not linked, then start a new link chain by linking it to
16541cb0ef41Sopenharmony_ci    // itself, emitting pc_offset().
16551cb0ef41Sopenharmony_ci    int link = label->is_linked() ? label->pos() : pc_offset();
16561cb0ef41Sopenharmony_ci    label->link_to(pc_offset());
16571cb0ef41Sopenharmony_ci
16581cb0ef41Sopenharmony_ci    // When the label is bound, these instructions will be patched with a
16591cb0ef41Sopenharmony_ci    // sequence of movw/movt or mov/orr/orr instructions. They will load the
16601cb0ef41Sopenharmony_ci    // destination register with the position of the label from the beginning
16611cb0ef41Sopenharmony_ci    // of the code.
16621cb0ef41Sopenharmony_ci    //
16631cb0ef41Sopenharmony_ci    // The link will be extracted from the first instruction and the destination
16641cb0ef41Sopenharmony_ci    // register from the second.
16651cb0ef41Sopenharmony_ci    //   For ARMv7:
16661cb0ef41Sopenharmony_ci    //      link
16671cb0ef41Sopenharmony_ci    //      mov dst, dst
16681cb0ef41Sopenharmony_ci    //   For ARMv6:
16691cb0ef41Sopenharmony_ci    //      link
16701cb0ef41Sopenharmony_ci    //      mov dst, dst
16711cb0ef41Sopenharmony_ci    //      mov dst, dst
16721cb0ef41Sopenharmony_ci    //
16731cb0ef41Sopenharmony_ci    // When the label gets bound: target_at extracts the link and target_at_put
16741cb0ef41Sopenharmony_ci    // patches the instructions.
16751cb0ef41Sopenharmony_ci    CHECK(is_uint24(link));
16761cb0ef41Sopenharmony_ci    BlockConstPoolScope block_const_pool(this);
16771cb0ef41Sopenharmony_ci    emit(link);
16781cb0ef41Sopenharmony_ci    nop(dst.code());
16791cb0ef41Sopenharmony_ci    if (!CpuFeatures::IsSupported(ARMv7)) {
16801cb0ef41Sopenharmony_ci      nop(dst.code());
16811cb0ef41Sopenharmony_ci    }
16821cb0ef41Sopenharmony_ci  }
16831cb0ef41Sopenharmony_ci}
16841cb0ef41Sopenharmony_ci
16851cb0ef41Sopenharmony_civoid Assembler::movw(Register reg, uint32_t immediate, Condition cond) {
16861cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(ARMv7));
16871cb0ef41Sopenharmony_ci  emit(cond | 0x30 * B20 | reg.code() * B12 | EncodeMovwImmediate(immediate));
16881cb0ef41Sopenharmony_ci}
16891cb0ef41Sopenharmony_ci
16901cb0ef41Sopenharmony_civoid Assembler::movt(Register reg, uint32_t immediate, Condition cond) {
16911cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(ARMv7));
16921cb0ef41Sopenharmony_ci  emit(cond | 0x34 * B20 | reg.code() * B12 | EncodeMovwImmediate(immediate));
16931cb0ef41Sopenharmony_ci}
16941cb0ef41Sopenharmony_ci
16951cb0ef41Sopenharmony_civoid Assembler::bic(Register dst, Register src1, const Operand& src2, SBit s,
16961cb0ef41Sopenharmony_ci                    Condition cond) {
16971cb0ef41Sopenharmony_ci  AddrMode1(cond | BIC | s, dst, src1, src2);
16981cb0ef41Sopenharmony_ci}
16991cb0ef41Sopenharmony_ci
17001cb0ef41Sopenharmony_civoid Assembler::mvn(Register dst, const Operand& src, SBit s, Condition cond) {
17011cb0ef41Sopenharmony_ci  AddrMode1(cond | MVN | s, dst, no_reg, src);
17021cb0ef41Sopenharmony_ci}
17031cb0ef41Sopenharmony_ci
17041cb0ef41Sopenharmony_civoid Assembler::asr(Register dst, Register src1, const Operand& src2, SBit s,
17051cb0ef41Sopenharmony_ci                    Condition cond) {
17061cb0ef41Sopenharmony_ci  if (src2.IsRegister()) {
17071cb0ef41Sopenharmony_ci    mov(dst, Operand(src1, ASR, src2.rm()), s, cond);
17081cb0ef41Sopenharmony_ci  } else {
17091cb0ef41Sopenharmony_ci    mov(dst, Operand(src1, ASR, src2.immediate()), s, cond);
17101cb0ef41Sopenharmony_ci  }
17111cb0ef41Sopenharmony_ci}
17121cb0ef41Sopenharmony_ci
17131cb0ef41Sopenharmony_civoid Assembler::lsl(Register dst, Register src1, const Operand& src2, SBit s,
17141cb0ef41Sopenharmony_ci                    Condition cond) {
17151cb0ef41Sopenharmony_ci  if (src2.IsRegister()) {
17161cb0ef41Sopenharmony_ci    mov(dst, Operand(src1, LSL, src2.rm()), s, cond);
17171cb0ef41Sopenharmony_ci  } else {
17181cb0ef41Sopenharmony_ci    mov(dst, Operand(src1, LSL, src2.immediate()), s, cond);
17191cb0ef41Sopenharmony_ci  }
17201cb0ef41Sopenharmony_ci}
17211cb0ef41Sopenharmony_ci
17221cb0ef41Sopenharmony_civoid Assembler::lsr(Register dst, Register src1, const Operand& src2, SBit s,
17231cb0ef41Sopenharmony_ci                    Condition cond) {
17241cb0ef41Sopenharmony_ci  if (src2.IsRegister()) {
17251cb0ef41Sopenharmony_ci    mov(dst, Operand(src1, LSR, src2.rm()), s, cond);
17261cb0ef41Sopenharmony_ci  } else {
17271cb0ef41Sopenharmony_ci    mov(dst, Operand(src1, LSR, src2.immediate()), s, cond);
17281cb0ef41Sopenharmony_ci  }
17291cb0ef41Sopenharmony_ci}
17301cb0ef41Sopenharmony_ci
17311cb0ef41Sopenharmony_ci// Multiply instructions.
17321cb0ef41Sopenharmony_civoid Assembler::mla(Register dst, Register src1, Register src2, Register srcA,
17331cb0ef41Sopenharmony_ci                    SBit s, Condition cond) {
17341cb0ef41Sopenharmony_ci  DCHECK(dst != pc && src1 != pc && src2 != pc && srcA != pc);
17351cb0ef41Sopenharmony_ci  emit(cond | A | s | dst.code() * B16 | srcA.code() * B12 | src2.code() * B8 |
17361cb0ef41Sopenharmony_ci       B7 | B4 | src1.code());
17371cb0ef41Sopenharmony_ci}
17381cb0ef41Sopenharmony_ci
17391cb0ef41Sopenharmony_civoid Assembler::mls(Register dst, Register src1, Register src2, Register srcA,
17401cb0ef41Sopenharmony_ci                    Condition cond) {
17411cb0ef41Sopenharmony_ci  DCHECK(dst != pc && src1 != pc && src2 != pc && srcA != pc);
17421cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(ARMv7));
17431cb0ef41Sopenharmony_ci  emit(cond | B22 | B21 | dst.code() * B16 | srcA.code() * B12 |
17441cb0ef41Sopenharmony_ci       src2.code() * B8 | B7 | B4 | src1.code());
17451cb0ef41Sopenharmony_ci}
17461cb0ef41Sopenharmony_ci
17471cb0ef41Sopenharmony_civoid Assembler::sdiv(Register dst, Register src1, Register src2,
17481cb0ef41Sopenharmony_ci                     Condition cond) {
17491cb0ef41Sopenharmony_ci  DCHECK(dst != pc && src1 != pc && src2 != pc);
17501cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(SUDIV));
17511cb0ef41Sopenharmony_ci  emit(cond | B26 | B25 | B24 | B20 | dst.code() * B16 | 0xF * B12 |
17521cb0ef41Sopenharmony_ci       src2.code() * B8 | B4 | src1.code());
17531cb0ef41Sopenharmony_ci}
17541cb0ef41Sopenharmony_ci
17551cb0ef41Sopenharmony_civoid Assembler::udiv(Register dst, Register src1, Register src2,
17561cb0ef41Sopenharmony_ci                     Condition cond) {
17571cb0ef41Sopenharmony_ci  DCHECK(dst != pc && src1 != pc && src2 != pc);
17581cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(SUDIV));
17591cb0ef41Sopenharmony_ci  emit(cond | B26 | B25 | B24 | B21 | B20 | dst.code() * B16 | 0xF * B12 |
17601cb0ef41Sopenharmony_ci       src2.code() * B8 | B4 | src1.code());
17611cb0ef41Sopenharmony_ci}
17621cb0ef41Sopenharmony_ci
17631cb0ef41Sopenharmony_civoid Assembler::mul(Register dst, Register src1, Register src2, SBit s,
17641cb0ef41Sopenharmony_ci                    Condition cond) {
17651cb0ef41Sopenharmony_ci  DCHECK(dst != pc && src1 != pc && src2 != pc);
17661cb0ef41Sopenharmony_ci  // dst goes in bits 16-19 for this instruction!
17671cb0ef41Sopenharmony_ci  emit(cond | s | dst.code() * B16 | src2.code() * B8 | B7 | B4 | src1.code());
17681cb0ef41Sopenharmony_ci}
17691cb0ef41Sopenharmony_ci
17701cb0ef41Sopenharmony_civoid Assembler::smmla(Register dst, Register src1, Register src2, Register srcA,
17711cb0ef41Sopenharmony_ci                      Condition cond) {
17721cb0ef41Sopenharmony_ci  DCHECK(dst != pc && src1 != pc && src2 != pc && srcA != pc);
17731cb0ef41Sopenharmony_ci  emit(cond | B26 | B25 | B24 | B22 | B20 | dst.code() * B16 |
17741cb0ef41Sopenharmony_ci       srcA.code() * B12 | src2.code() * B8 | B4 | src1.code());
17751cb0ef41Sopenharmony_ci}
17761cb0ef41Sopenharmony_ci
17771cb0ef41Sopenharmony_civoid Assembler::smmul(Register dst, Register src1, Register src2,
17781cb0ef41Sopenharmony_ci                      Condition cond) {
17791cb0ef41Sopenharmony_ci  DCHECK(dst != pc && src1 != pc && src2 != pc);
17801cb0ef41Sopenharmony_ci  emit(cond | B26 | B25 | B24 | B22 | B20 | dst.code() * B16 | 0xF * B12 |
17811cb0ef41Sopenharmony_ci       src2.code() * B8 | B4 | src1.code());
17821cb0ef41Sopenharmony_ci}
17831cb0ef41Sopenharmony_ci
17841cb0ef41Sopenharmony_civoid Assembler::smlal(Register dstL, Register dstH, Register src1,
17851cb0ef41Sopenharmony_ci                      Register src2, SBit s, Condition cond) {
17861cb0ef41Sopenharmony_ci  DCHECK(dstL != pc && dstH != pc && src1 != pc && src2 != pc);
17871cb0ef41Sopenharmony_ci  DCHECK(dstL != dstH);
17881cb0ef41Sopenharmony_ci  emit(cond | B23 | B22 | A | s | dstH.code() * B16 | dstL.code() * B12 |
17891cb0ef41Sopenharmony_ci       src2.code() * B8 | B7 | B4 | src1.code());
17901cb0ef41Sopenharmony_ci}
17911cb0ef41Sopenharmony_ci
17921cb0ef41Sopenharmony_civoid Assembler::smull(Register dstL, Register dstH, Register src1,
17931cb0ef41Sopenharmony_ci                      Register src2, SBit s, Condition cond) {
17941cb0ef41Sopenharmony_ci  DCHECK(dstL != pc && dstH != pc && src1 != pc && src2 != pc);
17951cb0ef41Sopenharmony_ci  DCHECK(dstL != dstH);
17961cb0ef41Sopenharmony_ci  emit(cond | B23 | B22 | s | dstH.code() * B16 | dstL.code() * B12 |
17971cb0ef41Sopenharmony_ci       src2.code() * B8 | B7 | B4 | src1.code());
17981cb0ef41Sopenharmony_ci}
17991cb0ef41Sopenharmony_ci
18001cb0ef41Sopenharmony_civoid Assembler::umlal(Register dstL, Register dstH, Register src1,
18011cb0ef41Sopenharmony_ci                      Register src2, SBit s, Condition cond) {
18021cb0ef41Sopenharmony_ci  DCHECK(dstL != pc && dstH != pc && src1 != pc && src2 != pc);
18031cb0ef41Sopenharmony_ci  DCHECK(dstL != dstH);
18041cb0ef41Sopenharmony_ci  emit(cond | B23 | A | s | dstH.code() * B16 | dstL.code() * B12 |
18051cb0ef41Sopenharmony_ci       src2.code() * B8 | B7 | B4 | src1.code());
18061cb0ef41Sopenharmony_ci}
18071cb0ef41Sopenharmony_ci
18081cb0ef41Sopenharmony_civoid Assembler::umull(Register dstL, Register dstH, Register src1,
18091cb0ef41Sopenharmony_ci                      Register src2, SBit s, Condition cond) {
18101cb0ef41Sopenharmony_ci  DCHECK(dstL != pc && dstH != pc && src1 != pc && src2 != pc);
18111cb0ef41Sopenharmony_ci  DCHECK(dstL != dstH);
18121cb0ef41Sopenharmony_ci  emit(cond | B23 | s | dstH.code() * B16 | dstL.code() * B12 |
18131cb0ef41Sopenharmony_ci       src2.code() * B8 | B7 | B4 | src1.code());
18141cb0ef41Sopenharmony_ci}
18151cb0ef41Sopenharmony_ci
18161cb0ef41Sopenharmony_ci// Miscellaneous arithmetic instructions.
18171cb0ef41Sopenharmony_civoid Assembler::clz(Register dst, Register src, Condition cond) {
18181cb0ef41Sopenharmony_ci  DCHECK(dst != pc && src != pc);
18191cb0ef41Sopenharmony_ci  emit(cond | B24 | B22 | B21 | 15 * B16 | dst.code() * B12 | 15 * B8 | CLZ |
18201cb0ef41Sopenharmony_ci       src.code());
18211cb0ef41Sopenharmony_ci}
18221cb0ef41Sopenharmony_ci
18231cb0ef41Sopenharmony_ci// Saturating instructions.
18241cb0ef41Sopenharmony_ci
18251cb0ef41Sopenharmony_ci// Unsigned saturate.
18261cb0ef41Sopenharmony_civoid Assembler::usat(Register dst, int satpos, const Operand& src,
18271cb0ef41Sopenharmony_ci                     Condition cond) {
18281cb0ef41Sopenharmony_ci  DCHECK(dst != pc && src.rm_ != pc);
18291cb0ef41Sopenharmony_ci  DCHECK((satpos >= 0) && (satpos <= 31));
18301cb0ef41Sopenharmony_ci  DCHECK(src.IsImmediateShiftedRegister());
18311cb0ef41Sopenharmony_ci  DCHECK((src.shift_op_ == ASR) || (src.shift_op_ == LSL));
18321cb0ef41Sopenharmony_ci
18331cb0ef41Sopenharmony_ci  int sh = 0;
18341cb0ef41Sopenharmony_ci  if (src.shift_op_ == ASR) {
18351cb0ef41Sopenharmony_ci    sh = 1;
18361cb0ef41Sopenharmony_ci  }
18371cb0ef41Sopenharmony_ci
18381cb0ef41Sopenharmony_ci  emit(cond | 0x6 * B24 | 0xE * B20 | satpos * B16 | dst.code() * B12 |
18391cb0ef41Sopenharmony_ci       src.shift_imm_ * B7 | sh * B6 | 0x1 * B4 | src.rm_.code());
18401cb0ef41Sopenharmony_ci}
18411cb0ef41Sopenharmony_ci
18421cb0ef41Sopenharmony_ci// Bitfield manipulation instructions.
18431cb0ef41Sopenharmony_ci
18441cb0ef41Sopenharmony_ci// Unsigned bit field extract.
18451cb0ef41Sopenharmony_ci// Extracts #width adjacent bits from position #lsb in a register, and
18461cb0ef41Sopenharmony_ci// writes them to the low bits of a destination register.
18471cb0ef41Sopenharmony_ci//   ubfx dst, src, #lsb, #width
18481cb0ef41Sopenharmony_civoid Assembler::ubfx(Register dst, Register src, int lsb, int width,
18491cb0ef41Sopenharmony_ci                     Condition cond) {
18501cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(ARMv7));
18511cb0ef41Sopenharmony_ci  DCHECK(dst != pc && src != pc);
18521cb0ef41Sopenharmony_ci  DCHECK((lsb >= 0) && (lsb <= 31));
18531cb0ef41Sopenharmony_ci  DCHECK((width >= 1) && (width <= (32 - lsb)));
18541cb0ef41Sopenharmony_ci  emit(cond | 0xF * B23 | B22 | B21 | (width - 1) * B16 | dst.code() * B12 |
18551cb0ef41Sopenharmony_ci       lsb * B7 | B6 | B4 | src.code());
18561cb0ef41Sopenharmony_ci}
18571cb0ef41Sopenharmony_ci
18581cb0ef41Sopenharmony_ci// Signed bit field extract.
18591cb0ef41Sopenharmony_ci// Extracts #width adjacent bits from position #lsb in a register, and
18601cb0ef41Sopenharmony_ci// writes them to the low bits of a destination register. The extracted
18611cb0ef41Sopenharmony_ci// value is sign extended to fill the destination register.
18621cb0ef41Sopenharmony_ci//   sbfx dst, src, #lsb, #width
18631cb0ef41Sopenharmony_civoid Assembler::sbfx(Register dst, Register src, int lsb, int width,
18641cb0ef41Sopenharmony_ci                     Condition cond) {
18651cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(ARMv7));
18661cb0ef41Sopenharmony_ci  DCHECK(dst != pc && src != pc);
18671cb0ef41Sopenharmony_ci  DCHECK((lsb >= 0) && (lsb <= 31));
18681cb0ef41Sopenharmony_ci  DCHECK((width >= 1) && (width <= (32 - lsb)));
18691cb0ef41Sopenharmony_ci  emit(cond | 0xF * B23 | B21 | (width - 1) * B16 | dst.code() * B12 |
18701cb0ef41Sopenharmony_ci       lsb * B7 | B6 | B4 | src.code());
18711cb0ef41Sopenharmony_ci}
18721cb0ef41Sopenharmony_ci
18731cb0ef41Sopenharmony_ci// Bit field clear.
18741cb0ef41Sopenharmony_ci// Sets #width adjacent bits at position #lsb in the destination register
18751cb0ef41Sopenharmony_ci// to zero, preserving the value of the other bits.
18761cb0ef41Sopenharmony_ci//   bfc dst, #lsb, #width
18771cb0ef41Sopenharmony_civoid Assembler::bfc(Register dst, int lsb, int width, Condition cond) {
18781cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(ARMv7));
18791cb0ef41Sopenharmony_ci  DCHECK(dst != pc);
18801cb0ef41Sopenharmony_ci  DCHECK((lsb >= 0) && (lsb <= 31));
18811cb0ef41Sopenharmony_ci  DCHECK((width >= 1) && (width <= (32 - lsb)));
18821cb0ef41Sopenharmony_ci  int msb = lsb + width - 1;
18831cb0ef41Sopenharmony_ci  emit(cond | 0x1F * B22 | msb * B16 | dst.code() * B12 | lsb * B7 | B4 | 0xF);
18841cb0ef41Sopenharmony_ci}
18851cb0ef41Sopenharmony_ci
18861cb0ef41Sopenharmony_ci// Bit field insert.
18871cb0ef41Sopenharmony_ci// Inserts #width adjacent bits from the low bits of the source register
18881cb0ef41Sopenharmony_ci// into position #lsb of the destination register.
18891cb0ef41Sopenharmony_ci//   bfi dst, src, #lsb, #width
18901cb0ef41Sopenharmony_civoid Assembler::bfi(Register dst, Register src, int lsb, int width,
18911cb0ef41Sopenharmony_ci                    Condition cond) {
18921cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(ARMv7));
18931cb0ef41Sopenharmony_ci  DCHECK(dst != pc && src != pc);
18941cb0ef41Sopenharmony_ci  DCHECK((lsb >= 0) && (lsb <= 31));
18951cb0ef41Sopenharmony_ci  DCHECK((width >= 1) && (width <= (32 - lsb)));
18961cb0ef41Sopenharmony_ci  int msb = lsb + width - 1;
18971cb0ef41Sopenharmony_ci  emit(cond | 0x1F * B22 | msb * B16 | dst.code() * B12 | lsb * B7 | B4 |
18981cb0ef41Sopenharmony_ci       src.code());
18991cb0ef41Sopenharmony_ci}
19001cb0ef41Sopenharmony_ci
19011cb0ef41Sopenharmony_civoid Assembler::pkhbt(Register dst, Register src1, const Operand& src2,
19021cb0ef41Sopenharmony_ci                      Condition cond) {
19031cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8.8.125.
19041cb0ef41Sopenharmony_ci  // cond(31-28) | 01101000(27-20) | Rn(19-16) |
19051cb0ef41Sopenharmony_ci  // Rd(15-12) | imm5(11-7) | 0(6) | 01(5-4) | Rm(3-0)
19061cb0ef41Sopenharmony_ci  DCHECK(dst != pc);
19071cb0ef41Sopenharmony_ci  DCHECK(src1 != pc);
19081cb0ef41Sopenharmony_ci  DCHECK(src2.IsImmediateShiftedRegister());
19091cb0ef41Sopenharmony_ci  DCHECK(src2.rm() != pc);
19101cb0ef41Sopenharmony_ci  DCHECK((src2.shift_imm_ >= 0) && (src2.shift_imm_ <= 31));
19111cb0ef41Sopenharmony_ci  DCHECK(src2.shift_op() == LSL);
19121cb0ef41Sopenharmony_ci  emit(cond | 0x68 * B20 | src1.code() * B16 | dst.code() * B12 |
19131cb0ef41Sopenharmony_ci       src2.shift_imm_ * B7 | B4 | src2.rm().code());
19141cb0ef41Sopenharmony_ci}
19151cb0ef41Sopenharmony_ci
19161cb0ef41Sopenharmony_civoid Assembler::pkhtb(Register dst, Register src1, const Operand& src2,
19171cb0ef41Sopenharmony_ci                      Condition cond) {
19181cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8.8.125.
19191cb0ef41Sopenharmony_ci  // cond(31-28) | 01101000(27-20) | Rn(19-16) |
19201cb0ef41Sopenharmony_ci  // Rd(15-12) | imm5(11-7) | 1(6) | 01(5-4) | Rm(3-0)
19211cb0ef41Sopenharmony_ci  DCHECK(dst != pc);
19221cb0ef41Sopenharmony_ci  DCHECK(src1 != pc);
19231cb0ef41Sopenharmony_ci  DCHECK(src2.IsImmediateShiftedRegister());
19241cb0ef41Sopenharmony_ci  DCHECK(src2.rm() != pc);
19251cb0ef41Sopenharmony_ci  DCHECK((src2.shift_imm_ >= 1) && (src2.shift_imm_ <= 32));
19261cb0ef41Sopenharmony_ci  DCHECK(src2.shift_op() == ASR);
19271cb0ef41Sopenharmony_ci  int asr = (src2.shift_imm_ == 32) ? 0 : src2.shift_imm_;
19281cb0ef41Sopenharmony_ci  emit(cond | 0x68 * B20 | src1.code() * B16 | dst.code() * B12 | asr * B7 |
19291cb0ef41Sopenharmony_ci       B6 | B4 | src2.rm().code());
19301cb0ef41Sopenharmony_ci}
19311cb0ef41Sopenharmony_ci
19321cb0ef41Sopenharmony_civoid Assembler::sxtb(Register dst, Register src, int rotate, Condition cond) {
19331cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8.8.233.
19341cb0ef41Sopenharmony_ci  // cond(31-28) | 01101010(27-20) | 1111(19-16) |
19351cb0ef41Sopenharmony_ci  // Rd(15-12) | rotate(11-10) | 00(9-8)| 0111(7-4) | Rm(3-0)
19361cb0ef41Sopenharmony_ci  DCHECK(dst != pc);
19371cb0ef41Sopenharmony_ci  DCHECK(src != pc);
19381cb0ef41Sopenharmony_ci  DCHECK(rotate == 0 || rotate == 8 || rotate == 16 || rotate == 24);
19391cb0ef41Sopenharmony_ci  emit(cond | 0x6A * B20 | 0xF * B16 | dst.code() * B12 |
19401cb0ef41Sopenharmony_ci       ((rotate >> 1) & 0xC) * B8 | 7 * B4 | src.code());
19411cb0ef41Sopenharmony_ci}
19421cb0ef41Sopenharmony_ci
19431cb0ef41Sopenharmony_civoid Assembler::sxtab(Register dst, Register src1, Register src2, int rotate,
19441cb0ef41Sopenharmony_ci                      Condition cond) {
19451cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8.8.233.
19461cb0ef41Sopenharmony_ci  // cond(31-28) | 01101010(27-20) | Rn(19-16) |
19471cb0ef41Sopenharmony_ci  // Rd(15-12) | rotate(11-10) | 00(9-8)| 0111(7-4) | Rm(3-0)
19481cb0ef41Sopenharmony_ci  DCHECK(dst != pc);
19491cb0ef41Sopenharmony_ci  DCHECK(src1 != pc);
19501cb0ef41Sopenharmony_ci  DCHECK(src2 != pc);
19511cb0ef41Sopenharmony_ci  DCHECK(rotate == 0 || rotate == 8 || rotate == 16 || rotate == 24);
19521cb0ef41Sopenharmony_ci  emit(cond | 0x6A * B20 | src1.code() * B16 | dst.code() * B12 |
19531cb0ef41Sopenharmony_ci       ((rotate >> 1) & 0xC) * B8 | 7 * B4 | src2.code());
19541cb0ef41Sopenharmony_ci}
19551cb0ef41Sopenharmony_ci
19561cb0ef41Sopenharmony_civoid Assembler::sxth(Register dst, Register src, int rotate, Condition cond) {
19571cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8.8.235.
19581cb0ef41Sopenharmony_ci  // cond(31-28) | 01101011(27-20) | 1111(19-16) |
19591cb0ef41Sopenharmony_ci  // Rd(15-12) | rotate(11-10) | 00(9-8)| 0111(7-4) | Rm(3-0)
19601cb0ef41Sopenharmony_ci  DCHECK(dst != pc);
19611cb0ef41Sopenharmony_ci  DCHECK(src != pc);
19621cb0ef41Sopenharmony_ci  DCHECK(rotate == 0 || rotate == 8 || rotate == 16 || rotate == 24);
19631cb0ef41Sopenharmony_ci  emit(cond | 0x6B * B20 | 0xF * B16 | dst.code() * B12 |
19641cb0ef41Sopenharmony_ci       ((rotate >> 1) & 0xC) * B8 | 7 * B4 | src.code());
19651cb0ef41Sopenharmony_ci}
19661cb0ef41Sopenharmony_ci
19671cb0ef41Sopenharmony_civoid Assembler::sxtah(Register dst, Register src1, Register src2, int rotate,
19681cb0ef41Sopenharmony_ci                      Condition cond) {
19691cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8.8.235.
19701cb0ef41Sopenharmony_ci  // cond(31-28) | 01101011(27-20) | Rn(19-16) |
19711cb0ef41Sopenharmony_ci  // Rd(15-12) | rotate(11-10) | 00(9-8)| 0111(7-4) | Rm(3-0)
19721cb0ef41Sopenharmony_ci  DCHECK(dst != pc);
19731cb0ef41Sopenharmony_ci  DCHECK(src1 != pc);
19741cb0ef41Sopenharmony_ci  DCHECK(src2 != pc);
19751cb0ef41Sopenharmony_ci  DCHECK(rotate == 0 || rotate == 8 || rotate == 16 || rotate == 24);
19761cb0ef41Sopenharmony_ci  emit(cond | 0x6B * B20 | src1.code() * B16 | dst.code() * B12 |
19771cb0ef41Sopenharmony_ci       ((rotate >> 1) & 0xC) * B8 | 7 * B4 | src2.code());
19781cb0ef41Sopenharmony_ci}
19791cb0ef41Sopenharmony_ci
19801cb0ef41Sopenharmony_civoid Assembler::uxtb(Register dst, Register src, int rotate, Condition cond) {
19811cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8.8.274.
19821cb0ef41Sopenharmony_ci  // cond(31-28) | 01101110(27-20) | 1111(19-16) |
19831cb0ef41Sopenharmony_ci  // Rd(15-12) | rotate(11-10) | 00(9-8)| 0111(7-4) | Rm(3-0)
19841cb0ef41Sopenharmony_ci  DCHECK(dst != pc);
19851cb0ef41Sopenharmony_ci  DCHECK(src != pc);
19861cb0ef41Sopenharmony_ci  DCHECK(rotate == 0 || rotate == 8 || rotate == 16 || rotate == 24);
19871cb0ef41Sopenharmony_ci  emit(cond | 0x6E * B20 | 0xF * B16 | dst.code() * B12 |
19881cb0ef41Sopenharmony_ci       ((rotate >> 1) & 0xC) * B8 | 7 * B4 | src.code());
19891cb0ef41Sopenharmony_ci}
19901cb0ef41Sopenharmony_ci
19911cb0ef41Sopenharmony_civoid Assembler::uxtab(Register dst, Register src1, Register src2, int rotate,
19921cb0ef41Sopenharmony_ci                      Condition cond) {
19931cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8.8.271.
19941cb0ef41Sopenharmony_ci  // cond(31-28) | 01101110(27-20) | Rn(19-16) |
19951cb0ef41Sopenharmony_ci  // Rd(15-12) | rotate(11-10) | 00(9-8)| 0111(7-4) | Rm(3-0)
19961cb0ef41Sopenharmony_ci  DCHECK(dst != pc);
19971cb0ef41Sopenharmony_ci  DCHECK(src1 != pc);
19981cb0ef41Sopenharmony_ci  DCHECK(src2 != pc);
19991cb0ef41Sopenharmony_ci  DCHECK(rotate == 0 || rotate == 8 || rotate == 16 || rotate == 24);
20001cb0ef41Sopenharmony_ci  emit(cond | 0x6E * B20 | src1.code() * B16 | dst.code() * B12 |
20011cb0ef41Sopenharmony_ci       ((rotate >> 1) & 0xC) * B8 | 7 * B4 | src2.code());
20021cb0ef41Sopenharmony_ci}
20031cb0ef41Sopenharmony_ci
20041cb0ef41Sopenharmony_civoid Assembler::uxtb16(Register dst, Register src, int rotate, Condition cond) {
20051cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8.8.275.
20061cb0ef41Sopenharmony_ci  // cond(31-28) | 01101100(27-20) | 1111(19-16) |
20071cb0ef41Sopenharmony_ci  // Rd(15-12) | rotate(11-10) | 00(9-8)| 0111(7-4) | Rm(3-0)
20081cb0ef41Sopenharmony_ci  DCHECK(dst != pc);
20091cb0ef41Sopenharmony_ci  DCHECK(src != pc);
20101cb0ef41Sopenharmony_ci  DCHECK(rotate == 0 || rotate == 8 || rotate == 16 || rotate == 24);
20111cb0ef41Sopenharmony_ci  emit(cond | 0x6C * B20 | 0xF * B16 | dst.code() * B12 |
20121cb0ef41Sopenharmony_ci       ((rotate >> 1) & 0xC) * B8 | 7 * B4 | src.code());
20131cb0ef41Sopenharmony_ci}
20141cb0ef41Sopenharmony_ci
20151cb0ef41Sopenharmony_civoid Assembler::uxth(Register dst, Register src, int rotate, Condition cond) {
20161cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8.8.276.
20171cb0ef41Sopenharmony_ci  // cond(31-28) | 01101111(27-20) | 1111(19-16) |
20181cb0ef41Sopenharmony_ci  // Rd(15-12) | rotate(11-10) | 00(9-8)| 0111(7-4) | Rm(3-0)
20191cb0ef41Sopenharmony_ci  DCHECK(dst != pc);
20201cb0ef41Sopenharmony_ci  DCHECK(src != pc);
20211cb0ef41Sopenharmony_ci  DCHECK(rotate == 0 || rotate == 8 || rotate == 16 || rotate == 24);
20221cb0ef41Sopenharmony_ci  emit(cond | 0x6F * B20 | 0xF * B16 | dst.code() * B12 |
20231cb0ef41Sopenharmony_ci       ((rotate >> 1) & 0xC) * B8 | 7 * B4 | src.code());
20241cb0ef41Sopenharmony_ci}
20251cb0ef41Sopenharmony_ci
20261cb0ef41Sopenharmony_civoid Assembler::uxtah(Register dst, Register src1, Register src2, int rotate,
20271cb0ef41Sopenharmony_ci                      Condition cond) {
20281cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8.8.273.
20291cb0ef41Sopenharmony_ci  // cond(31-28) | 01101111(27-20) | Rn(19-16) |
20301cb0ef41Sopenharmony_ci  // Rd(15-12) | rotate(11-10) | 00(9-8)| 0111(7-4) | Rm(3-0)
20311cb0ef41Sopenharmony_ci  DCHECK(dst != pc);
20321cb0ef41Sopenharmony_ci  DCHECK(src1 != pc);
20331cb0ef41Sopenharmony_ci  DCHECK(src2 != pc);
20341cb0ef41Sopenharmony_ci  DCHECK(rotate == 0 || rotate == 8 || rotate == 16 || rotate == 24);
20351cb0ef41Sopenharmony_ci  emit(cond | 0x6F * B20 | src1.code() * B16 | dst.code() * B12 |
20361cb0ef41Sopenharmony_ci       ((rotate >> 1) & 0xC) * B8 | 7 * B4 | src2.code());
20371cb0ef41Sopenharmony_ci}
20381cb0ef41Sopenharmony_ci
20391cb0ef41Sopenharmony_civoid Assembler::rbit(Register dst, Register src, Condition cond) {
20401cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8.8.144.
20411cb0ef41Sopenharmony_ci  // cond(31-28) | 011011111111(27-16) | Rd(15-12) | 11110011(11-4) | Rm(3-0)
20421cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(ARMv7));
20431cb0ef41Sopenharmony_ci  DCHECK(dst != pc);
20441cb0ef41Sopenharmony_ci  DCHECK(src != pc);
20451cb0ef41Sopenharmony_ci  emit(cond | 0x6FF * B16 | dst.code() * B12 | 0xF3 * B4 | src.code());
20461cb0ef41Sopenharmony_ci}
20471cb0ef41Sopenharmony_ci
20481cb0ef41Sopenharmony_civoid Assembler::rev(Register dst, Register src, Condition cond) {
20491cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8.8.144.
20501cb0ef41Sopenharmony_ci  // cond(31-28) | 011010111111(27-16) | Rd(15-12) | 11110011(11-4) | Rm(3-0)
20511cb0ef41Sopenharmony_ci  DCHECK(dst != pc);
20521cb0ef41Sopenharmony_ci  DCHECK(src != pc);
20531cb0ef41Sopenharmony_ci  emit(cond | 0x6BF * B16 | dst.code() * B12 | 0xF3 * B4 | src.code());
20541cb0ef41Sopenharmony_ci}
20551cb0ef41Sopenharmony_ci
20561cb0ef41Sopenharmony_ci// Status register access instructions.
20571cb0ef41Sopenharmony_civoid Assembler::mrs(Register dst, SRegister s, Condition cond) {
20581cb0ef41Sopenharmony_ci  DCHECK(dst != pc);
20591cb0ef41Sopenharmony_ci  emit(cond | B24 | s | 15 * B16 | dst.code() * B12);
20601cb0ef41Sopenharmony_ci}
20611cb0ef41Sopenharmony_ci
20621cb0ef41Sopenharmony_civoid Assembler::msr(SRegisterFieldMask fields, const Operand& src,
20631cb0ef41Sopenharmony_ci                    Condition cond) {
20641cb0ef41Sopenharmony_ci  DCHECK_NE(fields & 0x000F0000, 0);  // At least one field must be set.
20651cb0ef41Sopenharmony_ci  DCHECK(((fields & 0xFFF0FFFF) == CPSR) || ((fields & 0xFFF0FFFF) == SPSR));
20661cb0ef41Sopenharmony_ci  Instr instr;
20671cb0ef41Sopenharmony_ci  if (src.IsImmediate()) {
20681cb0ef41Sopenharmony_ci    // Immediate.
20691cb0ef41Sopenharmony_ci    uint32_t rotate_imm;
20701cb0ef41Sopenharmony_ci    uint32_t immed_8;
20711cb0ef41Sopenharmony_ci    if (src.MustOutputRelocInfo(this) ||
20721cb0ef41Sopenharmony_ci        !FitsShifter(src.immediate(), &rotate_imm, &immed_8, nullptr)) {
20731cb0ef41Sopenharmony_ci      UseScratchRegisterScope temps(this);
20741cb0ef41Sopenharmony_ci      Register scratch = temps.Acquire();
20751cb0ef41Sopenharmony_ci      // Immediate operand cannot be encoded, load it first to a scratch
20761cb0ef41Sopenharmony_ci      // register.
20771cb0ef41Sopenharmony_ci      Move32BitImmediate(scratch, src);
20781cb0ef41Sopenharmony_ci      msr(fields, Operand(scratch), cond);
20791cb0ef41Sopenharmony_ci      return;
20801cb0ef41Sopenharmony_ci    }
20811cb0ef41Sopenharmony_ci    instr = I | rotate_imm * B8 | immed_8;
20821cb0ef41Sopenharmony_ci  } else {
20831cb0ef41Sopenharmony_ci    DCHECK(src.IsRegister());  // Only rm is allowed.
20841cb0ef41Sopenharmony_ci    instr = src.rm_.code();
20851cb0ef41Sopenharmony_ci  }
20861cb0ef41Sopenharmony_ci  emit(cond | instr | B24 | B21 | fields | 15 * B12);
20871cb0ef41Sopenharmony_ci}
20881cb0ef41Sopenharmony_ci
20891cb0ef41Sopenharmony_ci// Load/Store instructions.
20901cb0ef41Sopenharmony_civoid Assembler::ldr(Register dst, const MemOperand& src, Condition cond) {
20911cb0ef41Sopenharmony_ci  AddrMode2(cond | B26 | L, dst, src);
20921cb0ef41Sopenharmony_ci}
20931cb0ef41Sopenharmony_ci
20941cb0ef41Sopenharmony_civoid Assembler::str(Register src, const MemOperand& dst, Condition cond) {
20951cb0ef41Sopenharmony_ci  AddrMode2(cond | B26, src, dst);
20961cb0ef41Sopenharmony_ci}
20971cb0ef41Sopenharmony_ci
20981cb0ef41Sopenharmony_civoid Assembler::ldrb(Register dst, const MemOperand& src, Condition cond) {
20991cb0ef41Sopenharmony_ci  AddrMode2(cond | B26 | B | L, dst, src);
21001cb0ef41Sopenharmony_ci}
21011cb0ef41Sopenharmony_ci
21021cb0ef41Sopenharmony_civoid Assembler::strb(Register src, const MemOperand& dst, Condition cond) {
21031cb0ef41Sopenharmony_ci  AddrMode2(cond | B26 | B, src, dst);
21041cb0ef41Sopenharmony_ci}
21051cb0ef41Sopenharmony_ci
21061cb0ef41Sopenharmony_civoid Assembler::ldrh(Register dst, const MemOperand& src, Condition cond) {
21071cb0ef41Sopenharmony_ci  AddrMode3(cond | L | B7 | H | B4, dst, src);
21081cb0ef41Sopenharmony_ci}
21091cb0ef41Sopenharmony_ci
21101cb0ef41Sopenharmony_civoid Assembler::strh(Register src, const MemOperand& dst, Condition cond) {
21111cb0ef41Sopenharmony_ci  AddrMode3(cond | B7 | H | B4, src, dst);
21121cb0ef41Sopenharmony_ci}
21131cb0ef41Sopenharmony_ci
21141cb0ef41Sopenharmony_civoid Assembler::ldrsb(Register dst, const MemOperand& src, Condition cond) {
21151cb0ef41Sopenharmony_ci  AddrMode3(cond | L | B7 | S6 | B4, dst, src);
21161cb0ef41Sopenharmony_ci}
21171cb0ef41Sopenharmony_ci
21181cb0ef41Sopenharmony_civoid Assembler::ldrsh(Register dst, const MemOperand& src, Condition cond) {
21191cb0ef41Sopenharmony_ci  AddrMode3(cond | L | B7 | S6 | H | B4, dst, src);
21201cb0ef41Sopenharmony_ci}
21211cb0ef41Sopenharmony_ci
21221cb0ef41Sopenharmony_civoid Assembler::ldrd(Register dst1, Register dst2, const MemOperand& src,
21231cb0ef41Sopenharmony_ci                     Condition cond) {
21241cb0ef41Sopenharmony_ci  DCHECK(src.rm() == no_reg);
21251cb0ef41Sopenharmony_ci  DCHECK(dst1 != lr);  // r14.
21261cb0ef41Sopenharmony_ci  DCHECK_EQ(0, dst1.code() % 2);
21271cb0ef41Sopenharmony_ci  DCHECK_EQ(dst1.code() + 1, dst2.code());
21281cb0ef41Sopenharmony_ci  AddrMode3(cond | B7 | B6 | B4, dst1, src);
21291cb0ef41Sopenharmony_ci}
21301cb0ef41Sopenharmony_ci
21311cb0ef41Sopenharmony_civoid Assembler::strd(Register src1, Register src2, const MemOperand& dst,
21321cb0ef41Sopenharmony_ci                     Condition cond) {
21331cb0ef41Sopenharmony_ci  DCHECK(dst.rm() == no_reg);
21341cb0ef41Sopenharmony_ci  DCHECK(src1 != lr);  // r14.
21351cb0ef41Sopenharmony_ci  DCHECK_EQ(0, src1.code() % 2);
21361cb0ef41Sopenharmony_ci  DCHECK_EQ(src1.code() + 1, src2.code());
21371cb0ef41Sopenharmony_ci  AddrMode3(cond | B7 | B6 | B5 | B4, src1, dst);
21381cb0ef41Sopenharmony_ci}
21391cb0ef41Sopenharmony_ci
21401cb0ef41Sopenharmony_civoid Assembler::ldr_pcrel(Register dst, int imm12, Condition cond) {
21411cb0ef41Sopenharmony_ci  AddrMode am = Offset;
21421cb0ef41Sopenharmony_ci  if (imm12 < 0) {
21431cb0ef41Sopenharmony_ci    imm12 = -imm12;
21441cb0ef41Sopenharmony_ci    am = NegOffset;
21451cb0ef41Sopenharmony_ci  }
21461cb0ef41Sopenharmony_ci  DCHECK(is_uint12(imm12));
21471cb0ef41Sopenharmony_ci  emit(cond | B26 | am | L | pc.code() * B16 | dst.code() * B12 | imm12);
21481cb0ef41Sopenharmony_ci}
21491cb0ef41Sopenharmony_ci
21501cb0ef41Sopenharmony_ci// Load/Store exclusive instructions.
21511cb0ef41Sopenharmony_civoid Assembler::ldrex(Register dst, Register src, Condition cond) {
21521cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8.8.75.
21531cb0ef41Sopenharmony_ci  // cond(31-28) | 00011001(27-20) | Rn(19-16) | Rt(15-12) | 111110011111(11-0)
21541cb0ef41Sopenharmony_ci  DCHECK(dst != pc);
21551cb0ef41Sopenharmony_ci  DCHECK(src != pc);
21561cb0ef41Sopenharmony_ci  emit(cond | B24 | B23 | B20 | src.code() * B16 | dst.code() * B12 | 0xF9F);
21571cb0ef41Sopenharmony_ci}
21581cb0ef41Sopenharmony_ci
21591cb0ef41Sopenharmony_civoid Assembler::strex(Register src1, Register src2, Register dst,
21601cb0ef41Sopenharmony_ci                      Condition cond) {
21611cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8.8.212.
21621cb0ef41Sopenharmony_ci  // cond(31-28) | 00011000(27-20) | Rn(19-16) | Rd(15-12) | 11111001(11-4) |
21631cb0ef41Sopenharmony_ci  // Rt(3-0)
21641cb0ef41Sopenharmony_ci  DCHECK(dst != pc);
21651cb0ef41Sopenharmony_ci  DCHECK(src1 != pc);
21661cb0ef41Sopenharmony_ci  DCHECK(src2 != pc);
21671cb0ef41Sopenharmony_ci  DCHECK(src1 != dst);
21681cb0ef41Sopenharmony_ci  DCHECK(src1 != src2);
21691cb0ef41Sopenharmony_ci  emit(cond | B24 | B23 | dst.code() * B16 | src1.code() * B12 | 0xF9 * B4 |
21701cb0ef41Sopenharmony_ci       src2.code());
21711cb0ef41Sopenharmony_ci}
21721cb0ef41Sopenharmony_ci
21731cb0ef41Sopenharmony_civoid Assembler::ldrexb(Register dst, Register src, Condition cond) {
21741cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8.8.76.
21751cb0ef41Sopenharmony_ci  // cond(31-28) | 00011101(27-20) | Rn(19-16) | Rt(15-12) | 111110011111(11-0)
21761cb0ef41Sopenharmony_ci  DCHECK(dst != pc);
21771cb0ef41Sopenharmony_ci  DCHECK(src != pc);
21781cb0ef41Sopenharmony_ci  emit(cond | B24 | B23 | B22 | B20 | src.code() * B16 | dst.code() * B12 |
21791cb0ef41Sopenharmony_ci       0xF9F);
21801cb0ef41Sopenharmony_ci}
21811cb0ef41Sopenharmony_ci
21821cb0ef41Sopenharmony_civoid Assembler::strexb(Register src1, Register src2, Register dst,
21831cb0ef41Sopenharmony_ci                       Condition cond) {
21841cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8.8.213.
21851cb0ef41Sopenharmony_ci  // cond(31-28) | 00011100(27-20) | Rn(19-16) | Rd(15-12) | 11111001(11-4) |
21861cb0ef41Sopenharmony_ci  // Rt(3-0)
21871cb0ef41Sopenharmony_ci  DCHECK(dst != pc);
21881cb0ef41Sopenharmony_ci  DCHECK(src1 != pc);
21891cb0ef41Sopenharmony_ci  DCHECK(src2 != pc);
21901cb0ef41Sopenharmony_ci  DCHECK(src1 != dst);
21911cb0ef41Sopenharmony_ci  DCHECK(src1 != src2);
21921cb0ef41Sopenharmony_ci  emit(cond | B24 | B23 | B22 | dst.code() * B16 | src1.code() * B12 |
21931cb0ef41Sopenharmony_ci       0xF9 * B4 | src2.code());
21941cb0ef41Sopenharmony_ci}
21951cb0ef41Sopenharmony_ci
21961cb0ef41Sopenharmony_civoid Assembler::ldrexh(Register dst, Register src, Condition cond) {
21971cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8.8.78.
21981cb0ef41Sopenharmony_ci  // cond(31-28) | 00011111(27-20) | Rn(19-16) | Rt(15-12) | 111110011111(11-0)
21991cb0ef41Sopenharmony_ci  DCHECK(dst != pc);
22001cb0ef41Sopenharmony_ci  DCHECK(src != pc);
22011cb0ef41Sopenharmony_ci  emit(cond | B24 | B23 | B22 | B21 | B20 | src.code() * B16 |
22021cb0ef41Sopenharmony_ci       dst.code() * B12 | 0xF9F);
22031cb0ef41Sopenharmony_ci}
22041cb0ef41Sopenharmony_ci
22051cb0ef41Sopenharmony_civoid Assembler::strexh(Register src1, Register src2, Register dst,
22061cb0ef41Sopenharmony_ci                       Condition cond) {
22071cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8.8.215.
22081cb0ef41Sopenharmony_ci  // cond(31-28) | 00011110(27-20) | Rn(19-16) | Rd(15-12) | 11111001(11-4) |
22091cb0ef41Sopenharmony_ci  // Rt(3-0)
22101cb0ef41Sopenharmony_ci  DCHECK(dst != pc);
22111cb0ef41Sopenharmony_ci  DCHECK(src1 != pc);
22121cb0ef41Sopenharmony_ci  DCHECK(src2 != pc);
22131cb0ef41Sopenharmony_ci  DCHECK(src1 != dst);
22141cb0ef41Sopenharmony_ci  DCHECK(src1 != src2);
22151cb0ef41Sopenharmony_ci  emit(cond | B24 | B23 | B22 | B21 | dst.code() * B16 | src1.code() * B12 |
22161cb0ef41Sopenharmony_ci       0xF9 * B4 | src2.code());
22171cb0ef41Sopenharmony_ci}
22181cb0ef41Sopenharmony_ci
22191cb0ef41Sopenharmony_civoid Assembler::ldrexd(Register dst1, Register dst2, Register src,
22201cb0ef41Sopenharmony_ci                       Condition cond) {
22211cb0ef41Sopenharmony_ci  // cond(31-28) | 00011011(27-20) | Rn(19-16) | Rt(15-12) | 111110011111(11-0)
22221cb0ef41Sopenharmony_ci  DCHECK(dst1 != lr);  // r14.
22231cb0ef41Sopenharmony_ci  // The pair of destination registers is restricted to being an even-numbered
22241cb0ef41Sopenharmony_ci  // register and the odd-numbered register that immediately follows it.
22251cb0ef41Sopenharmony_ci  DCHECK_EQ(0, dst1.code() % 2);
22261cb0ef41Sopenharmony_ci  DCHECK_EQ(dst1.code() + 1, dst2.code());
22271cb0ef41Sopenharmony_ci  emit(cond | B24 | B23 | B21 | B20 | src.code() * B16 | dst1.code() * B12 |
22281cb0ef41Sopenharmony_ci       0xF9F);
22291cb0ef41Sopenharmony_ci}
22301cb0ef41Sopenharmony_ci
22311cb0ef41Sopenharmony_civoid Assembler::strexd(Register res, Register src1, Register src2, Register dst,
22321cb0ef41Sopenharmony_ci                       Condition cond) {
22331cb0ef41Sopenharmony_ci  // cond(31-28) | 00011010(27-20) | Rn(19-16) | Rt(15-12) | 111110011111(11-0)
22341cb0ef41Sopenharmony_ci  DCHECK(src1 != lr);  // r14.
22351cb0ef41Sopenharmony_ci  // The pair of source registers is restricted to being an even-numbered
22361cb0ef41Sopenharmony_ci  // register and the odd-numbered register that immediately follows it.
22371cb0ef41Sopenharmony_ci  DCHECK_EQ(0, src1.code() % 2);
22381cb0ef41Sopenharmony_ci  DCHECK_EQ(src1.code() + 1, src2.code());
22391cb0ef41Sopenharmony_ci  emit(cond | B24 | B23 | B21 | dst.code() * B16 | res.code() * B12 |
22401cb0ef41Sopenharmony_ci       0xF9 * B4 | src1.code());
22411cb0ef41Sopenharmony_ci}
22421cb0ef41Sopenharmony_ci
22431cb0ef41Sopenharmony_ci// Preload instructions.
22441cb0ef41Sopenharmony_civoid Assembler::pld(const MemOperand& address) {
22451cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8.8.128.
22461cb0ef41Sopenharmony_ci  // 1111(31-28) | 0111(27-24) | U(23) | R(22) | 01(21-20) | Rn(19-16) |
22471cb0ef41Sopenharmony_ci  // 1111(15-12) | imm5(11-07) | type(6-5) | 0(4)| Rm(3-0) |
22481cb0ef41Sopenharmony_ci  DCHECK(address.rm() == no_reg);
22491cb0ef41Sopenharmony_ci  DCHECK(address.am() == Offset);
22501cb0ef41Sopenharmony_ci  int U = B23;
22511cb0ef41Sopenharmony_ci  int offset = address.offset();
22521cb0ef41Sopenharmony_ci  if (offset < 0) {
22531cb0ef41Sopenharmony_ci    offset = -offset;
22541cb0ef41Sopenharmony_ci    U = 0;
22551cb0ef41Sopenharmony_ci  }
22561cb0ef41Sopenharmony_ci  DCHECK_LT(offset, 4096);
22571cb0ef41Sopenharmony_ci  emit(kSpecialCondition | B26 | B24 | U | B22 | B20 |
22581cb0ef41Sopenharmony_ci       address.rn().code() * B16 | 0xF * B12 | offset);
22591cb0ef41Sopenharmony_ci}
22601cb0ef41Sopenharmony_ci
22611cb0ef41Sopenharmony_ci// Load/Store multiple instructions.
22621cb0ef41Sopenharmony_civoid Assembler::ldm(BlockAddrMode am, Register base, RegList dst,
22631cb0ef41Sopenharmony_ci                    Condition cond) {
22641cb0ef41Sopenharmony_ci  // ABI stack constraint: ldmxx base, {..sp..}  base != sp  is not restartable.
22651cb0ef41Sopenharmony_ci  DCHECK(base == sp || !dst.has(sp));
22661cb0ef41Sopenharmony_ci
22671cb0ef41Sopenharmony_ci  AddrMode4(cond | B27 | am | L, base, dst);
22681cb0ef41Sopenharmony_ci
22691cb0ef41Sopenharmony_ci  // Emit the constant pool after a function return implemented by ldm ..{..pc}.
22701cb0ef41Sopenharmony_ci  if (cond == al && dst.has(pc)) {
22711cb0ef41Sopenharmony_ci    // There is a slight chance that the ldm instruction was actually a call,
22721cb0ef41Sopenharmony_ci    // in which case it would be wrong to return into the constant pool; we
22731cb0ef41Sopenharmony_ci    // recognize this case by checking if the emission of the pool was blocked
22741cb0ef41Sopenharmony_ci    // at the pc of the ldm instruction by a mov lr, pc instruction; if this is
22751cb0ef41Sopenharmony_ci    // the case, we emit a jump over the pool.
22761cb0ef41Sopenharmony_ci    CheckConstPool(true, no_const_pool_before_ == pc_offset() - kInstrSize);
22771cb0ef41Sopenharmony_ci  }
22781cb0ef41Sopenharmony_ci}
22791cb0ef41Sopenharmony_ci
22801cb0ef41Sopenharmony_civoid Assembler::stm(BlockAddrMode am, Register base, RegList src,
22811cb0ef41Sopenharmony_ci                    Condition cond) {
22821cb0ef41Sopenharmony_ci  AddrMode4(cond | B27 | am, base, src);
22831cb0ef41Sopenharmony_ci}
22841cb0ef41Sopenharmony_ci
22851cb0ef41Sopenharmony_ci// Exception-generating instructions and debugging support.
22861cb0ef41Sopenharmony_ci// Stops with a non-negative code less than kNumOfWatchedStops support
22871cb0ef41Sopenharmony_ci// enabling/disabling and a counter feature. See simulator-arm.h .
22881cb0ef41Sopenharmony_civoid Assembler::stop(Condition cond, int32_t code) {
22891cb0ef41Sopenharmony_ci#ifndef __arm__
22901cb0ef41Sopenharmony_ci  DCHECK_GE(code, kDefaultStopCode);
22911cb0ef41Sopenharmony_ci  {
22921cb0ef41Sopenharmony_ci    BlockConstPoolScope block_const_pool(this);
22931cb0ef41Sopenharmony_ci    if (code >= 0) {
22941cb0ef41Sopenharmony_ci      svc(kStopCode + code, cond);
22951cb0ef41Sopenharmony_ci    } else {
22961cb0ef41Sopenharmony_ci      svc(kStopCode + kMaxStopCode, cond);
22971cb0ef41Sopenharmony_ci    }
22981cb0ef41Sopenharmony_ci  }
22991cb0ef41Sopenharmony_ci#else   // def __arm__
23001cb0ef41Sopenharmony_ci  if (cond != al) {
23011cb0ef41Sopenharmony_ci    Label skip;
23021cb0ef41Sopenharmony_ci    b(&skip, NegateCondition(cond));
23031cb0ef41Sopenharmony_ci    bkpt(0);
23041cb0ef41Sopenharmony_ci    bind(&skip);
23051cb0ef41Sopenharmony_ci  } else {
23061cb0ef41Sopenharmony_ci    bkpt(0);
23071cb0ef41Sopenharmony_ci  }
23081cb0ef41Sopenharmony_ci#endif  // def __arm__
23091cb0ef41Sopenharmony_ci}
23101cb0ef41Sopenharmony_ci
23111cb0ef41Sopenharmony_civoid Assembler::bkpt(uint32_t imm16) {
23121cb0ef41Sopenharmony_ci  DCHECK(is_uint16(imm16));
23131cb0ef41Sopenharmony_ci  emit(al | B24 | B21 | (imm16 >> 4) * B8 | BKPT | (imm16 & 0xF));
23141cb0ef41Sopenharmony_ci}
23151cb0ef41Sopenharmony_ci
23161cb0ef41Sopenharmony_civoid Assembler::svc(uint32_t imm24, Condition cond) {
23171cb0ef41Sopenharmony_ci  CHECK(is_uint24(imm24));
23181cb0ef41Sopenharmony_ci  emit(cond | 15 * B24 | imm24);
23191cb0ef41Sopenharmony_ci}
23201cb0ef41Sopenharmony_ci
23211cb0ef41Sopenharmony_civoid Assembler::dmb(BarrierOption option) {
23221cb0ef41Sopenharmony_ci  if (CpuFeatures::IsSupported(ARMv7)) {
23231cb0ef41Sopenharmony_ci    // Details available in ARM DDI 0406C.b, A8-378.
23241cb0ef41Sopenharmony_ci    emit(kSpecialCondition | 0x57FF * B12 | 5 * B4 | option);
23251cb0ef41Sopenharmony_ci  } else {
23261cb0ef41Sopenharmony_ci    // Details available in ARM DDI 0406C.b, B3-1750.
23271cb0ef41Sopenharmony_ci    // CP15DMB: CRn=c7, opc1=0, CRm=c10, opc2=5, Rt is ignored.
23281cb0ef41Sopenharmony_ci    mcr(p15, 0, r0, cr7, cr10, 5);
23291cb0ef41Sopenharmony_ci  }
23301cb0ef41Sopenharmony_ci}
23311cb0ef41Sopenharmony_ci
23321cb0ef41Sopenharmony_civoid Assembler::dsb(BarrierOption option) {
23331cb0ef41Sopenharmony_ci  if (CpuFeatures::IsSupported(ARMv7)) {
23341cb0ef41Sopenharmony_ci    // Details available in ARM DDI 0406C.b, A8-380.
23351cb0ef41Sopenharmony_ci    emit(kSpecialCondition | 0x57FF * B12 | 4 * B4 | option);
23361cb0ef41Sopenharmony_ci  } else {
23371cb0ef41Sopenharmony_ci    // Details available in ARM DDI 0406C.b, B3-1750.
23381cb0ef41Sopenharmony_ci    // CP15DSB: CRn=c7, opc1=0, CRm=c10, opc2=4, Rt is ignored.
23391cb0ef41Sopenharmony_ci    mcr(p15, 0, r0, cr7, cr10, 4);
23401cb0ef41Sopenharmony_ci  }
23411cb0ef41Sopenharmony_ci}
23421cb0ef41Sopenharmony_ci
23431cb0ef41Sopenharmony_civoid Assembler::isb(BarrierOption option) {
23441cb0ef41Sopenharmony_ci  if (CpuFeatures::IsSupported(ARMv7)) {
23451cb0ef41Sopenharmony_ci    // Details available in ARM DDI 0406C.b, A8-389.
23461cb0ef41Sopenharmony_ci    emit(kSpecialCondition | 0x57FF * B12 | 6 * B4 | option);
23471cb0ef41Sopenharmony_ci  } else {
23481cb0ef41Sopenharmony_ci    // Details available in ARM DDI 0406C.b, B3-1750.
23491cb0ef41Sopenharmony_ci    // CP15ISB: CRn=c7, opc1=0, CRm=c5, opc2=4, Rt is ignored.
23501cb0ef41Sopenharmony_ci    mcr(p15, 0, r0, cr7, cr5, 4);
23511cb0ef41Sopenharmony_ci  }
23521cb0ef41Sopenharmony_ci}
23531cb0ef41Sopenharmony_ci
23541cb0ef41Sopenharmony_civoid Assembler::csdb() {
23551cb0ef41Sopenharmony_ci  // Details available in Arm Cache Speculation Side-channels white paper,
23561cb0ef41Sopenharmony_ci  // version 1.1, page 4.
23571cb0ef41Sopenharmony_ci  emit(0xE320F014);
23581cb0ef41Sopenharmony_ci}
23591cb0ef41Sopenharmony_ci
23601cb0ef41Sopenharmony_ci// Coprocessor instructions.
23611cb0ef41Sopenharmony_civoid Assembler::cdp(Coprocessor coproc, int opcode_1, CRegister crd,
23621cb0ef41Sopenharmony_ci                    CRegister crn, CRegister crm, int opcode_2,
23631cb0ef41Sopenharmony_ci                    Condition cond) {
23641cb0ef41Sopenharmony_ci  DCHECK(is_uint4(opcode_1) && is_uint3(opcode_2));
23651cb0ef41Sopenharmony_ci  emit(cond | B27 | B26 | B25 | (opcode_1 & 15) * B20 | crn.code() * B16 |
23661cb0ef41Sopenharmony_ci       crd.code() * B12 | coproc * B8 | (opcode_2 & 7) * B5 | crm.code());
23671cb0ef41Sopenharmony_ci}
23681cb0ef41Sopenharmony_ci
23691cb0ef41Sopenharmony_civoid Assembler::cdp2(Coprocessor coproc, int opcode_1, CRegister crd,
23701cb0ef41Sopenharmony_ci                     CRegister crn, CRegister crm, int opcode_2) {
23711cb0ef41Sopenharmony_ci  cdp(coproc, opcode_1, crd, crn, crm, opcode_2, kSpecialCondition);
23721cb0ef41Sopenharmony_ci}
23731cb0ef41Sopenharmony_ci
23741cb0ef41Sopenharmony_civoid Assembler::mcr(Coprocessor coproc, int opcode_1, Register rd,
23751cb0ef41Sopenharmony_ci                    CRegister crn, CRegister crm, int opcode_2,
23761cb0ef41Sopenharmony_ci                    Condition cond) {
23771cb0ef41Sopenharmony_ci  DCHECK(is_uint3(opcode_1) && is_uint3(opcode_2));
23781cb0ef41Sopenharmony_ci  emit(cond | B27 | B26 | B25 | (opcode_1 & 7) * B21 | crn.code() * B16 |
23791cb0ef41Sopenharmony_ci       rd.code() * B12 | coproc * B8 | (opcode_2 & 7) * B5 | B4 | crm.code());
23801cb0ef41Sopenharmony_ci}
23811cb0ef41Sopenharmony_ci
23821cb0ef41Sopenharmony_civoid Assembler::mcr2(Coprocessor coproc, int opcode_1, Register rd,
23831cb0ef41Sopenharmony_ci                     CRegister crn, CRegister crm, int opcode_2) {
23841cb0ef41Sopenharmony_ci  mcr(coproc, opcode_1, rd, crn, crm, opcode_2, kSpecialCondition);
23851cb0ef41Sopenharmony_ci}
23861cb0ef41Sopenharmony_ci
23871cb0ef41Sopenharmony_civoid Assembler::mrc(Coprocessor coproc, int opcode_1, Register rd,
23881cb0ef41Sopenharmony_ci                    CRegister crn, CRegister crm, int opcode_2,
23891cb0ef41Sopenharmony_ci                    Condition cond) {
23901cb0ef41Sopenharmony_ci  DCHECK(is_uint3(opcode_1) && is_uint3(opcode_2));
23911cb0ef41Sopenharmony_ci  emit(cond | B27 | B26 | B25 | (opcode_1 & 7) * B21 | L | crn.code() * B16 |
23921cb0ef41Sopenharmony_ci       rd.code() * B12 | coproc * B8 | (opcode_2 & 7) * B5 | B4 | crm.code());
23931cb0ef41Sopenharmony_ci}
23941cb0ef41Sopenharmony_ci
23951cb0ef41Sopenharmony_civoid Assembler::mrc2(Coprocessor coproc, int opcode_1, Register rd,
23961cb0ef41Sopenharmony_ci                     CRegister crn, CRegister crm, int opcode_2) {
23971cb0ef41Sopenharmony_ci  mrc(coproc, opcode_1, rd, crn, crm, opcode_2, kSpecialCondition);
23981cb0ef41Sopenharmony_ci}
23991cb0ef41Sopenharmony_ci
24001cb0ef41Sopenharmony_civoid Assembler::ldc(Coprocessor coproc, CRegister crd, const MemOperand& src,
24011cb0ef41Sopenharmony_ci                    LFlag l, Condition cond) {
24021cb0ef41Sopenharmony_ci  AddrMode5(cond | B27 | B26 | l | L | coproc * B8, crd, src);
24031cb0ef41Sopenharmony_ci}
24041cb0ef41Sopenharmony_ci
24051cb0ef41Sopenharmony_civoid Assembler::ldc(Coprocessor coproc, CRegister crd, Register rn, int option,
24061cb0ef41Sopenharmony_ci                    LFlag l, Condition cond) {
24071cb0ef41Sopenharmony_ci  // Unindexed addressing.
24081cb0ef41Sopenharmony_ci  DCHECK(is_uint8(option));
24091cb0ef41Sopenharmony_ci  emit(cond | B27 | B26 | U | l | L | rn.code() * B16 | crd.code() * B12 |
24101cb0ef41Sopenharmony_ci       coproc * B8 | (option & 255));
24111cb0ef41Sopenharmony_ci}
24121cb0ef41Sopenharmony_ci
24131cb0ef41Sopenharmony_civoid Assembler::ldc2(Coprocessor coproc, CRegister crd, const MemOperand& src,
24141cb0ef41Sopenharmony_ci                     LFlag l) {
24151cb0ef41Sopenharmony_ci  ldc(coproc, crd, src, l, kSpecialCondition);
24161cb0ef41Sopenharmony_ci}
24171cb0ef41Sopenharmony_ci
24181cb0ef41Sopenharmony_civoid Assembler::ldc2(Coprocessor coproc, CRegister crd, Register rn, int option,
24191cb0ef41Sopenharmony_ci                     LFlag l) {
24201cb0ef41Sopenharmony_ci  ldc(coproc, crd, rn, option, l, kSpecialCondition);
24211cb0ef41Sopenharmony_ci}
24221cb0ef41Sopenharmony_ci
24231cb0ef41Sopenharmony_ci// Support for VFP.
24241cb0ef41Sopenharmony_ci
24251cb0ef41Sopenharmony_civoid Assembler::vldr(const DwVfpRegister dst, const Register base, int offset,
24261cb0ef41Sopenharmony_ci                     const Condition cond) {
24271cb0ef41Sopenharmony_ci  // Ddst = MEM(Rbase + offset).
24281cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-924.
24291cb0ef41Sopenharmony_ci  // cond(31-28) | 1101(27-24)| U(23) | D(22) | 01(21-20) | Rbase(19-16) |
24301cb0ef41Sopenharmony_ci  // Vd(15-12) | 1011(11-8) | offset
24311cb0ef41Sopenharmony_ci  DCHECK(VfpRegisterIsAvailable(dst));
24321cb0ef41Sopenharmony_ci  int u = 1;
24331cb0ef41Sopenharmony_ci  if (offset < 0) {
24341cb0ef41Sopenharmony_ci    CHECK_NE(offset, kMinInt);
24351cb0ef41Sopenharmony_ci    offset = -offset;
24361cb0ef41Sopenharmony_ci    u = 0;
24371cb0ef41Sopenharmony_ci  }
24381cb0ef41Sopenharmony_ci  int vd, d;
24391cb0ef41Sopenharmony_ci  dst.split_code(&vd, &d);
24401cb0ef41Sopenharmony_ci
24411cb0ef41Sopenharmony_ci  DCHECK_GE(offset, 0);
24421cb0ef41Sopenharmony_ci  if ((offset % 4) == 0 && (offset / 4) < 256) {
24431cb0ef41Sopenharmony_ci    emit(cond | 0xD * B24 | u * B23 | d * B22 | B20 | base.code() * B16 |
24441cb0ef41Sopenharmony_ci         vd * B12 | 0xB * B8 | ((offset / 4) & 255));
24451cb0ef41Sopenharmony_ci  } else {
24461cb0ef41Sopenharmony_ci    UseScratchRegisterScope temps(this);
24471cb0ef41Sopenharmony_ci    Register scratch = temps.Acquire();
24481cb0ef41Sopenharmony_ci    // Larger offsets must be handled by computing the correct address in a
24491cb0ef41Sopenharmony_ci    // scratch register.
24501cb0ef41Sopenharmony_ci    DCHECK(base != scratch);
24511cb0ef41Sopenharmony_ci    if (u == 1) {
24521cb0ef41Sopenharmony_ci      add(scratch, base, Operand(offset));
24531cb0ef41Sopenharmony_ci    } else {
24541cb0ef41Sopenharmony_ci      sub(scratch, base, Operand(offset));
24551cb0ef41Sopenharmony_ci    }
24561cb0ef41Sopenharmony_ci    emit(cond | 0xD * B24 | d * B22 | B20 | scratch.code() * B16 | vd * B12 |
24571cb0ef41Sopenharmony_ci         0xB * B8);
24581cb0ef41Sopenharmony_ci  }
24591cb0ef41Sopenharmony_ci}
24601cb0ef41Sopenharmony_ci
24611cb0ef41Sopenharmony_civoid Assembler::vldr(const DwVfpRegister dst, const MemOperand& operand,
24621cb0ef41Sopenharmony_ci                     const Condition cond) {
24631cb0ef41Sopenharmony_ci  DCHECK(VfpRegisterIsAvailable(dst));
24641cb0ef41Sopenharmony_ci  DCHECK(operand.am_ == Offset);
24651cb0ef41Sopenharmony_ci  if (operand.rm().is_valid()) {
24661cb0ef41Sopenharmony_ci    UseScratchRegisterScope temps(this);
24671cb0ef41Sopenharmony_ci    Register scratch = temps.Acquire();
24681cb0ef41Sopenharmony_ci    add(scratch, operand.rn(),
24691cb0ef41Sopenharmony_ci        Operand(operand.rm(), operand.shift_op_, operand.shift_imm_));
24701cb0ef41Sopenharmony_ci    vldr(dst, scratch, 0, cond);
24711cb0ef41Sopenharmony_ci  } else {
24721cb0ef41Sopenharmony_ci    vldr(dst, operand.rn(), operand.offset(), cond);
24731cb0ef41Sopenharmony_ci  }
24741cb0ef41Sopenharmony_ci}
24751cb0ef41Sopenharmony_ci
24761cb0ef41Sopenharmony_civoid Assembler::vldr(const SwVfpRegister dst, const Register base, int offset,
24771cb0ef41Sopenharmony_ci                     const Condition cond) {
24781cb0ef41Sopenharmony_ci  // Sdst = MEM(Rbase + offset).
24791cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406A, A8-628.
24801cb0ef41Sopenharmony_ci  // cond(31-28) | 1101(27-24)| U001(23-20) | Rbase(19-16) |
24811cb0ef41Sopenharmony_ci  // Vdst(15-12) | 1010(11-8) | offset
24821cb0ef41Sopenharmony_ci  int u = 1;
24831cb0ef41Sopenharmony_ci  if (offset < 0) {
24841cb0ef41Sopenharmony_ci    offset = -offset;
24851cb0ef41Sopenharmony_ci    u = 0;
24861cb0ef41Sopenharmony_ci  }
24871cb0ef41Sopenharmony_ci  int sd, d;
24881cb0ef41Sopenharmony_ci  dst.split_code(&sd, &d);
24891cb0ef41Sopenharmony_ci  DCHECK_GE(offset, 0);
24901cb0ef41Sopenharmony_ci
24911cb0ef41Sopenharmony_ci  if ((offset % 4) == 0 && (offset / 4) < 256) {
24921cb0ef41Sopenharmony_ci    emit(cond | u * B23 | d * B22 | 0xD1 * B20 | base.code() * B16 | sd * B12 |
24931cb0ef41Sopenharmony_ci         0xA * B8 | ((offset / 4) & 255));
24941cb0ef41Sopenharmony_ci  } else {
24951cb0ef41Sopenharmony_ci    // Larger offsets must be handled by computing the correct address in a
24961cb0ef41Sopenharmony_ci    // scratch register.
24971cb0ef41Sopenharmony_ci    UseScratchRegisterScope temps(this);
24981cb0ef41Sopenharmony_ci    Register scratch = temps.Acquire();
24991cb0ef41Sopenharmony_ci    DCHECK(base != scratch);
25001cb0ef41Sopenharmony_ci    if (u == 1) {
25011cb0ef41Sopenharmony_ci      add(scratch, base, Operand(offset));
25021cb0ef41Sopenharmony_ci    } else {
25031cb0ef41Sopenharmony_ci      sub(scratch, base, Operand(offset));
25041cb0ef41Sopenharmony_ci    }
25051cb0ef41Sopenharmony_ci    emit(cond | d * B22 | 0xD1 * B20 | scratch.code() * B16 | sd * B12 |
25061cb0ef41Sopenharmony_ci         0xA * B8);
25071cb0ef41Sopenharmony_ci  }
25081cb0ef41Sopenharmony_ci}
25091cb0ef41Sopenharmony_ci
25101cb0ef41Sopenharmony_civoid Assembler::vldr(const SwVfpRegister dst, const MemOperand& operand,
25111cb0ef41Sopenharmony_ci                     const Condition cond) {
25121cb0ef41Sopenharmony_ci  DCHECK(operand.am_ == Offset);
25131cb0ef41Sopenharmony_ci  if (operand.rm().is_valid()) {
25141cb0ef41Sopenharmony_ci    UseScratchRegisterScope temps(this);
25151cb0ef41Sopenharmony_ci    Register scratch = temps.Acquire();
25161cb0ef41Sopenharmony_ci    add(scratch, operand.rn(),
25171cb0ef41Sopenharmony_ci        Operand(operand.rm(), operand.shift_op_, operand.shift_imm_));
25181cb0ef41Sopenharmony_ci    vldr(dst, scratch, 0, cond);
25191cb0ef41Sopenharmony_ci  } else {
25201cb0ef41Sopenharmony_ci    vldr(dst, operand.rn(), operand.offset(), cond);
25211cb0ef41Sopenharmony_ci  }
25221cb0ef41Sopenharmony_ci}
25231cb0ef41Sopenharmony_ci
25241cb0ef41Sopenharmony_civoid Assembler::vstr(const DwVfpRegister src, const Register base, int offset,
25251cb0ef41Sopenharmony_ci                     const Condition cond) {
25261cb0ef41Sopenharmony_ci  // MEM(Rbase + offset) = Dsrc.
25271cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-1082.
25281cb0ef41Sopenharmony_ci  // cond(31-28) | 1101(27-24)| U(23) | D(22) | 00(21-20) | Rbase(19-16) |
25291cb0ef41Sopenharmony_ci  // Vd(15-12) | 1011(11-8) | (offset/4)
25301cb0ef41Sopenharmony_ci  DCHECK(VfpRegisterIsAvailable(src));
25311cb0ef41Sopenharmony_ci  int u = 1;
25321cb0ef41Sopenharmony_ci  if (offset < 0) {
25331cb0ef41Sopenharmony_ci    CHECK_NE(offset, kMinInt);
25341cb0ef41Sopenharmony_ci    offset = -offset;
25351cb0ef41Sopenharmony_ci    u = 0;
25361cb0ef41Sopenharmony_ci  }
25371cb0ef41Sopenharmony_ci  DCHECK_GE(offset, 0);
25381cb0ef41Sopenharmony_ci  int vd, d;
25391cb0ef41Sopenharmony_ci  src.split_code(&vd, &d);
25401cb0ef41Sopenharmony_ci
25411cb0ef41Sopenharmony_ci  if ((offset % 4) == 0 && (offset / 4) < 256) {
25421cb0ef41Sopenharmony_ci    emit(cond | 0xD * B24 | u * B23 | d * B22 | base.code() * B16 | vd * B12 |
25431cb0ef41Sopenharmony_ci         0xB * B8 | ((offset / 4) & 255));
25441cb0ef41Sopenharmony_ci  } else {
25451cb0ef41Sopenharmony_ci    // Larger offsets must be handled by computing the correct address in the a
25461cb0ef41Sopenharmony_ci    // scratch register.
25471cb0ef41Sopenharmony_ci    UseScratchRegisterScope temps(this);
25481cb0ef41Sopenharmony_ci    Register scratch = temps.Acquire();
25491cb0ef41Sopenharmony_ci    DCHECK(base != scratch);
25501cb0ef41Sopenharmony_ci    if (u == 1) {
25511cb0ef41Sopenharmony_ci      add(scratch, base, Operand(offset));
25521cb0ef41Sopenharmony_ci    } else {
25531cb0ef41Sopenharmony_ci      sub(scratch, base, Operand(offset));
25541cb0ef41Sopenharmony_ci    }
25551cb0ef41Sopenharmony_ci    emit(cond | 0xD * B24 | d * B22 | scratch.code() * B16 | vd * B12 |
25561cb0ef41Sopenharmony_ci         0xB * B8);
25571cb0ef41Sopenharmony_ci  }
25581cb0ef41Sopenharmony_ci}
25591cb0ef41Sopenharmony_ci
25601cb0ef41Sopenharmony_civoid Assembler::vstr(const DwVfpRegister src, const MemOperand& operand,
25611cb0ef41Sopenharmony_ci                     const Condition cond) {
25621cb0ef41Sopenharmony_ci  DCHECK(VfpRegisterIsAvailable(src));
25631cb0ef41Sopenharmony_ci  DCHECK(operand.am_ == Offset);
25641cb0ef41Sopenharmony_ci  if (operand.rm().is_valid()) {
25651cb0ef41Sopenharmony_ci    UseScratchRegisterScope temps(this);
25661cb0ef41Sopenharmony_ci    Register scratch = temps.Acquire();
25671cb0ef41Sopenharmony_ci    add(scratch, operand.rn(),
25681cb0ef41Sopenharmony_ci        Operand(operand.rm(), operand.shift_op_, operand.shift_imm_));
25691cb0ef41Sopenharmony_ci    vstr(src, scratch, 0, cond);
25701cb0ef41Sopenharmony_ci  } else {
25711cb0ef41Sopenharmony_ci    vstr(src, operand.rn(), operand.offset(), cond);
25721cb0ef41Sopenharmony_ci  }
25731cb0ef41Sopenharmony_ci}
25741cb0ef41Sopenharmony_ci
25751cb0ef41Sopenharmony_civoid Assembler::vstr(const SwVfpRegister src, const Register base, int offset,
25761cb0ef41Sopenharmony_ci                     const Condition cond) {
25771cb0ef41Sopenharmony_ci  // MEM(Rbase + offset) = SSrc.
25781cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406A, A8-786.
25791cb0ef41Sopenharmony_ci  // cond(31-28) | 1101(27-24)| U000(23-20) | Rbase(19-16) |
25801cb0ef41Sopenharmony_ci  // Vdst(15-12) | 1010(11-8) | (offset/4)
25811cb0ef41Sopenharmony_ci  int u = 1;
25821cb0ef41Sopenharmony_ci  if (offset < 0) {
25831cb0ef41Sopenharmony_ci    CHECK_NE(offset, kMinInt);
25841cb0ef41Sopenharmony_ci    offset = -offset;
25851cb0ef41Sopenharmony_ci    u = 0;
25861cb0ef41Sopenharmony_ci  }
25871cb0ef41Sopenharmony_ci  int sd, d;
25881cb0ef41Sopenharmony_ci  src.split_code(&sd, &d);
25891cb0ef41Sopenharmony_ci  DCHECK_GE(offset, 0);
25901cb0ef41Sopenharmony_ci  if ((offset % 4) == 0 && (offset / 4) < 256) {
25911cb0ef41Sopenharmony_ci    emit(cond | u * B23 | d * B22 | 0xD0 * B20 | base.code() * B16 | sd * B12 |
25921cb0ef41Sopenharmony_ci         0xA * B8 | ((offset / 4) & 255));
25931cb0ef41Sopenharmony_ci  } else {
25941cb0ef41Sopenharmony_ci    // Larger offsets must be handled by computing the correct address in a
25951cb0ef41Sopenharmony_ci    // scratch register.
25961cb0ef41Sopenharmony_ci    UseScratchRegisterScope temps(this);
25971cb0ef41Sopenharmony_ci    Register scratch = temps.Acquire();
25981cb0ef41Sopenharmony_ci    DCHECK(base != scratch);
25991cb0ef41Sopenharmony_ci    if (u == 1) {
26001cb0ef41Sopenharmony_ci      add(scratch, base, Operand(offset));
26011cb0ef41Sopenharmony_ci    } else {
26021cb0ef41Sopenharmony_ci      sub(scratch, base, Operand(offset));
26031cb0ef41Sopenharmony_ci    }
26041cb0ef41Sopenharmony_ci    emit(cond | d * B22 | 0xD0 * B20 | scratch.code() * B16 | sd * B12 |
26051cb0ef41Sopenharmony_ci         0xA * B8);
26061cb0ef41Sopenharmony_ci  }
26071cb0ef41Sopenharmony_ci}
26081cb0ef41Sopenharmony_ci
26091cb0ef41Sopenharmony_civoid Assembler::vstr(const SwVfpRegister src, const MemOperand& operand,
26101cb0ef41Sopenharmony_ci                     const Condition cond) {
26111cb0ef41Sopenharmony_ci  DCHECK(operand.am_ == Offset);
26121cb0ef41Sopenharmony_ci  if (operand.rm().is_valid()) {
26131cb0ef41Sopenharmony_ci    UseScratchRegisterScope temps(this);
26141cb0ef41Sopenharmony_ci    Register scratch = temps.Acquire();
26151cb0ef41Sopenharmony_ci    add(scratch, operand.rn(),
26161cb0ef41Sopenharmony_ci        Operand(operand.rm(), operand.shift_op_, operand.shift_imm_));
26171cb0ef41Sopenharmony_ci    vstr(src, scratch, 0, cond);
26181cb0ef41Sopenharmony_ci  } else {
26191cb0ef41Sopenharmony_ci    vstr(src, operand.rn(), operand.offset(), cond);
26201cb0ef41Sopenharmony_ci  }
26211cb0ef41Sopenharmony_ci}
26221cb0ef41Sopenharmony_ci
26231cb0ef41Sopenharmony_civoid Assembler::vldm(BlockAddrMode am, Register base, DwVfpRegister first,
26241cb0ef41Sopenharmony_ci                     DwVfpRegister last, Condition cond) {
26251cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-922.
26261cb0ef41Sopenharmony_ci  // cond(31-28) | 110(27-25)| PUDW1(24-20) | Rbase(19-16) |
26271cb0ef41Sopenharmony_ci  // first(15-12) | 1011(11-8) | (count * 2)
26281cb0ef41Sopenharmony_ci  DCHECK_LE(first.code(), last.code());
26291cb0ef41Sopenharmony_ci  DCHECK(VfpRegisterIsAvailable(last));
26301cb0ef41Sopenharmony_ci  DCHECK(am == ia || am == ia_w || am == db_w);
26311cb0ef41Sopenharmony_ci  DCHECK(base != pc);
26321cb0ef41Sopenharmony_ci
26331cb0ef41Sopenharmony_ci  int sd, d;
26341cb0ef41Sopenharmony_ci  first.split_code(&sd, &d);
26351cb0ef41Sopenharmony_ci  int count = last.code() - first.code() + 1;
26361cb0ef41Sopenharmony_ci  DCHECK_LE(count, 16);
26371cb0ef41Sopenharmony_ci  emit(cond | B27 | B26 | am | d * B22 | B20 | base.code() * B16 | sd * B12 |
26381cb0ef41Sopenharmony_ci       0xB * B8 | count * 2);
26391cb0ef41Sopenharmony_ci}
26401cb0ef41Sopenharmony_ci
26411cb0ef41Sopenharmony_civoid Assembler::vstm(BlockAddrMode am, Register base, DwVfpRegister first,
26421cb0ef41Sopenharmony_ci                     DwVfpRegister last, Condition cond) {
26431cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-1080.
26441cb0ef41Sopenharmony_ci  // cond(31-28) | 110(27-25)| PUDW0(24-20) | Rbase(19-16) |
26451cb0ef41Sopenharmony_ci  // first(15-12) | 1011(11-8) | (count * 2)
26461cb0ef41Sopenharmony_ci  DCHECK_LE(first.code(), last.code());
26471cb0ef41Sopenharmony_ci  DCHECK(VfpRegisterIsAvailable(last));
26481cb0ef41Sopenharmony_ci  DCHECK(am == ia || am == ia_w || am == db_w);
26491cb0ef41Sopenharmony_ci  DCHECK(base != pc);
26501cb0ef41Sopenharmony_ci
26511cb0ef41Sopenharmony_ci  int sd, d;
26521cb0ef41Sopenharmony_ci  first.split_code(&sd, &d);
26531cb0ef41Sopenharmony_ci  int count = last.code() - first.code() + 1;
26541cb0ef41Sopenharmony_ci  DCHECK_LE(count, 16);
26551cb0ef41Sopenharmony_ci  emit(cond | B27 | B26 | am | d * B22 | base.code() * B16 | sd * B12 |
26561cb0ef41Sopenharmony_ci       0xB * B8 | count * 2);
26571cb0ef41Sopenharmony_ci}
26581cb0ef41Sopenharmony_ci
26591cb0ef41Sopenharmony_civoid Assembler::vldm(BlockAddrMode am, Register base, SwVfpRegister first,
26601cb0ef41Sopenharmony_ci                     SwVfpRegister last, Condition cond) {
26611cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406A, A8-626.
26621cb0ef41Sopenharmony_ci  // cond(31-28) | 110(27-25)| PUDW1(24-20) | Rbase(19-16) |
26631cb0ef41Sopenharmony_ci  // first(15-12) | 1010(11-8) | (count/2)
26641cb0ef41Sopenharmony_ci  DCHECK_LE(first.code(), last.code());
26651cb0ef41Sopenharmony_ci  DCHECK(am == ia || am == ia_w || am == db_w);
26661cb0ef41Sopenharmony_ci  DCHECK(base != pc);
26671cb0ef41Sopenharmony_ci
26681cb0ef41Sopenharmony_ci  int sd, d;
26691cb0ef41Sopenharmony_ci  first.split_code(&sd, &d);
26701cb0ef41Sopenharmony_ci  int count = last.code() - first.code() + 1;
26711cb0ef41Sopenharmony_ci  emit(cond | B27 | B26 | am | d * B22 | B20 | base.code() * B16 | sd * B12 |
26721cb0ef41Sopenharmony_ci       0xA * B8 | count);
26731cb0ef41Sopenharmony_ci}
26741cb0ef41Sopenharmony_ci
26751cb0ef41Sopenharmony_civoid Assembler::vstm(BlockAddrMode am, Register base, SwVfpRegister first,
26761cb0ef41Sopenharmony_ci                     SwVfpRegister last, Condition cond) {
26771cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406A, A8-784.
26781cb0ef41Sopenharmony_ci  // cond(31-28) | 110(27-25)| PUDW0(24-20) | Rbase(19-16) |
26791cb0ef41Sopenharmony_ci  // first(15-12) | 1011(11-8) | (count/2)
26801cb0ef41Sopenharmony_ci  DCHECK_LE(first.code(), last.code());
26811cb0ef41Sopenharmony_ci  DCHECK(am == ia || am == ia_w || am == db_w);
26821cb0ef41Sopenharmony_ci  DCHECK(base != pc);
26831cb0ef41Sopenharmony_ci
26841cb0ef41Sopenharmony_ci  int sd, d;
26851cb0ef41Sopenharmony_ci  first.split_code(&sd, &d);
26861cb0ef41Sopenharmony_ci  int count = last.code() - first.code() + 1;
26871cb0ef41Sopenharmony_ci  emit(cond | B27 | B26 | am | d * B22 | base.code() * B16 | sd * B12 |
26881cb0ef41Sopenharmony_ci       0xA * B8 | count);
26891cb0ef41Sopenharmony_ci}
26901cb0ef41Sopenharmony_ci
26911cb0ef41Sopenharmony_cistatic void DoubleAsTwoUInt32(base::Double d, uint32_t* lo, uint32_t* hi) {
26921cb0ef41Sopenharmony_ci  uint64_t i = d.AsUint64();
26931cb0ef41Sopenharmony_ci
26941cb0ef41Sopenharmony_ci  *lo = i & 0xFFFFFFFF;
26951cb0ef41Sopenharmony_ci  *hi = i >> 32;
26961cb0ef41Sopenharmony_ci}
26971cb0ef41Sopenharmony_ci
26981cb0ef41Sopenharmony_cistatic void WriteVmovIntImmEncoding(uint8_t imm, uint32_t* encoding) {
26991cb0ef41Sopenharmony_ci  // Integer promotion from uint8_t to int makes these all okay.
27001cb0ef41Sopenharmony_ci  *encoding = ((imm & 0x80) << (24 - 7));   // a
27011cb0ef41Sopenharmony_ci  *encoding |= ((imm & 0x70) << (16 - 4));  // bcd
27021cb0ef41Sopenharmony_ci  *encoding |= (imm & 0x0f);                //  efgh
27031cb0ef41Sopenharmony_ci}
27041cb0ef41Sopenharmony_ci
27051cb0ef41Sopenharmony_ci// This checks if imm can be encoded into an immediate for vmov.
27061cb0ef41Sopenharmony_ci// See Table A7-15 in ARM DDI 0406C.d.
27071cb0ef41Sopenharmony_ci// Currently only supports the first row and op=0 && cmode=1110.
27081cb0ef41Sopenharmony_cistatic bool FitsVmovIntImm(uint64_t imm, uint32_t* encoding, uint8_t* cmode) {
27091cb0ef41Sopenharmony_ci  uint32_t lo = imm & 0xFFFFFFFF;
27101cb0ef41Sopenharmony_ci  uint32_t hi = imm >> 32;
27111cb0ef41Sopenharmony_ci  if ((lo == hi && ((lo & 0xffffff00) == 0))) {
27121cb0ef41Sopenharmony_ci    WriteVmovIntImmEncoding(imm & 0xff, encoding);
27131cb0ef41Sopenharmony_ci    *cmode = 0;
27141cb0ef41Sopenharmony_ci    return true;
27151cb0ef41Sopenharmony_ci  } else if ((lo == hi) && ((lo & 0xffff) == (lo >> 16)) &&
27161cb0ef41Sopenharmony_ci             ((lo & 0xff) == (lo >> 24))) {
27171cb0ef41Sopenharmony_ci    // Check that all bytes in imm are the same.
27181cb0ef41Sopenharmony_ci    WriteVmovIntImmEncoding(imm & 0xff, encoding);
27191cb0ef41Sopenharmony_ci    *cmode = 0xe;
27201cb0ef41Sopenharmony_ci    return true;
27211cb0ef41Sopenharmony_ci  }
27221cb0ef41Sopenharmony_ci
27231cb0ef41Sopenharmony_ci  return false;
27241cb0ef41Sopenharmony_ci}
27251cb0ef41Sopenharmony_ci
27261cb0ef41Sopenharmony_civoid Assembler::vmov(const DwVfpRegister dst, uint64_t imm) {
27271cb0ef41Sopenharmony_ci  uint32_t enc;
27281cb0ef41Sopenharmony_ci  uint8_t cmode;
27291cb0ef41Sopenharmony_ci  uint8_t op = 0;
27301cb0ef41Sopenharmony_ci  if (CpuFeatures::IsSupported(NEON) && FitsVmovIntImm(imm, &enc, &cmode)) {
27311cb0ef41Sopenharmony_ci    CpuFeatureScope scope(this, NEON);
27321cb0ef41Sopenharmony_ci    // Instruction details available in ARM DDI 0406C.b, A8-937.
27331cb0ef41Sopenharmony_ci    // 001i1(27-23) | D(22) | 000(21-19) | imm3(18-16) | Vd(15-12) | cmode(11-8)
27341cb0ef41Sopenharmony_ci    // | 0(7) | 0(6) | op(5) | 4(1) | imm4(3-0)
27351cb0ef41Sopenharmony_ci    int vd, d;
27361cb0ef41Sopenharmony_ci    dst.split_code(&vd, &d);
27371cb0ef41Sopenharmony_ci    emit(kSpecialCondition | 0x05 * B23 | d * B22 | vd * B12 | cmode * B8 |
27381cb0ef41Sopenharmony_ci         op * B5 | 0x1 * B4 | enc);
27391cb0ef41Sopenharmony_ci  } else {
27401cb0ef41Sopenharmony_ci    UNIMPLEMENTED();
27411cb0ef41Sopenharmony_ci  }
27421cb0ef41Sopenharmony_ci}
27431cb0ef41Sopenharmony_ci
27441cb0ef41Sopenharmony_civoid Assembler::vmov(const QwNeonRegister dst, uint64_t imm) {
27451cb0ef41Sopenharmony_ci  uint32_t enc;
27461cb0ef41Sopenharmony_ci  uint8_t cmode;
27471cb0ef41Sopenharmony_ci  uint8_t op = 0;
27481cb0ef41Sopenharmony_ci  if (CpuFeatures::IsSupported(NEON) && FitsVmovIntImm(imm, &enc, &cmode)) {
27491cb0ef41Sopenharmony_ci    CpuFeatureScope scope(this, NEON);
27501cb0ef41Sopenharmony_ci    // Instruction details available in ARM DDI 0406C.b, A8-937.
27511cb0ef41Sopenharmony_ci    // 001i1(27-23) | D(22) | 000(21-19) | imm3(18-16) | Vd(15-12) | cmode(11-8)
27521cb0ef41Sopenharmony_ci    // | 0(7) | Q(6) | op(5) | 4(1) | imm4(3-0)
27531cb0ef41Sopenharmony_ci    int vd, d;
27541cb0ef41Sopenharmony_ci    dst.split_code(&vd, &d);
27551cb0ef41Sopenharmony_ci    emit(kSpecialCondition | 0x05 * B23 | d * B22 | vd * B12 | cmode * B8 |
27561cb0ef41Sopenharmony_ci         0x1 * B6 | op * B5 | 0x1 * B4 | enc);
27571cb0ef41Sopenharmony_ci  } else {
27581cb0ef41Sopenharmony_ci    UNIMPLEMENTED();
27591cb0ef41Sopenharmony_ci  }
27601cb0ef41Sopenharmony_ci}
27611cb0ef41Sopenharmony_ci
27621cb0ef41Sopenharmony_ci// Only works for little endian floating point formats.
27631cb0ef41Sopenharmony_ci// We don't support VFP on the mixed endian floating point platform.
27641cb0ef41Sopenharmony_cistatic bool FitsVmovFPImmediate(base::Double d, uint32_t* encoding) {
27651cb0ef41Sopenharmony_ci  // VMOV can accept an immediate of the form:
27661cb0ef41Sopenharmony_ci  //
27671cb0ef41Sopenharmony_ci  //  +/- m * 2^(-n) where 16 <= m <= 31 and 0 <= n <= 7
27681cb0ef41Sopenharmony_ci  //
27691cb0ef41Sopenharmony_ci  // The immediate is encoded using an 8-bit quantity, comprised of two
27701cb0ef41Sopenharmony_ci  // 4-bit fields. For an 8-bit immediate of the form:
27711cb0ef41Sopenharmony_ci  //
27721cb0ef41Sopenharmony_ci  //  [abcdefgh]
27731cb0ef41Sopenharmony_ci  //
27741cb0ef41Sopenharmony_ci  // where a is the MSB and h is the LSB, an immediate 64-bit double can be
27751cb0ef41Sopenharmony_ci  // created of the form:
27761cb0ef41Sopenharmony_ci  //
27771cb0ef41Sopenharmony_ci  //  [aBbbbbbb,bbcdefgh,00000000,00000000,
27781cb0ef41Sopenharmony_ci  //      00000000,00000000,00000000,00000000]
27791cb0ef41Sopenharmony_ci  //
27801cb0ef41Sopenharmony_ci  // where B = ~b.
27811cb0ef41Sopenharmony_ci  //
27821cb0ef41Sopenharmony_ci
27831cb0ef41Sopenharmony_ci  uint32_t lo, hi;
27841cb0ef41Sopenharmony_ci  DoubleAsTwoUInt32(d, &lo, &hi);
27851cb0ef41Sopenharmony_ci
27861cb0ef41Sopenharmony_ci  // The most obvious constraint is the long block of zeroes.
27871cb0ef41Sopenharmony_ci  if ((lo != 0) || ((hi & 0xFFFF) != 0)) {
27881cb0ef41Sopenharmony_ci    return false;
27891cb0ef41Sopenharmony_ci  }
27901cb0ef41Sopenharmony_ci
27911cb0ef41Sopenharmony_ci  // Bits 61:54 must be all clear or all set.
27921cb0ef41Sopenharmony_ci  if (((hi & 0x3FC00000) != 0) && ((hi & 0x3FC00000) != 0x3FC00000)) {
27931cb0ef41Sopenharmony_ci    return false;
27941cb0ef41Sopenharmony_ci  }
27951cb0ef41Sopenharmony_ci
27961cb0ef41Sopenharmony_ci  // Bit 62 must be NOT bit 61.
27971cb0ef41Sopenharmony_ci  if (((hi ^ (hi << 1)) & (0x40000000)) == 0) {
27981cb0ef41Sopenharmony_ci    return false;
27991cb0ef41Sopenharmony_ci  }
28001cb0ef41Sopenharmony_ci
28011cb0ef41Sopenharmony_ci  // Create the encoded immediate in the form:
28021cb0ef41Sopenharmony_ci  //  [00000000,0000abcd,00000000,0000efgh]
28031cb0ef41Sopenharmony_ci  *encoding = (hi >> 16) & 0xF;       // Low nybble.
28041cb0ef41Sopenharmony_ci  *encoding |= (hi >> 4) & 0x70000;   // Low three bits of the high nybble.
28051cb0ef41Sopenharmony_ci  *encoding |= (hi >> 12) & 0x80000;  // Top bit of the high nybble.
28061cb0ef41Sopenharmony_ci
28071cb0ef41Sopenharmony_ci  return true;
28081cb0ef41Sopenharmony_ci}
28091cb0ef41Sopenharmony_ci
28101cb0ef41Sopenharmony_civoid Assembler::vmov(const SwVfpRegister dst, Float32 imm) {
28111cb0ef41Sopenharmony_ci  uint32_t enc;
28121cb0ef41Sopenharmony_ci  if (CpuFeatures::IsSupported(VFPv3) &&
28131cb0ef41Sopenharmony_ci      FitsVmovFPImmediate(base::Double(imm.get_scalar()), &enc)) {
28141cb0ef41Sopenharmony_ci    CpuFeatureScope scope(this, VFPv3);
28151cb0ef41Sopenharmony_ci    // The float can be encoded in the instruction.
28161cb0ef41Sopenharmony_ci    //
28171cb0ef41Sopenharmony_ci    // Sd = immediate
28181cb0ef41Sopenharmony_ci    // Instruction details available in ARM DDI 0406C.b, A8-936.
28191cb0ef41Sopenharmony_ci    // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | imm4H(19-16) |
28201cb0ef41Sopenharmony_ci    // Vd(15-12) | 101(11-9) | sz=0(8) | imm4L(3-0)
28211cb0ef41Sopenharmony_ci    int vd, d;
28221cb0ef41Sopenharmony_ci    dst.split_code(&vd, &d);
28231cb0ef41Sopenharmony_ci    emit(al | 0x1D * B23 | d * B22 | 0x3 * B20 | vd * B12 | 0x5 * B9 | enc);
28241cb0ef41Sopenharmony_ci  } else {
28251cb0ef41Sopenharmony_ci    UseScratchRegisterScope temps(this);
28261cb0ef41Sopenharmony_ci    Register scratch = temps.Acquire();
28271cb0ef41Sopenharmony_ci    mov(scratch, Operand(imm.get_bits()));
28281cb0ef41Sopenharmony_ci    vmov(dst, scratch);
28291cb0ef41Sopenharmony_ci  }
28301cb0ef41Sopenharmony_ci}
28311cb0ef41Sopenharmony_ci
28321cb0ef41Sopenharmony_civoid Assembler::vmov(const DwVfpRegister dst, base::Double imm,
28331cb0ef41Sopenharmony_ci                     const Register extra_scratch) {
28341cb0ef41Sopenharmony_ci  DCHECK(VfpRegisterIsAvailable(dst));
28351cb0ef41Sopenharmony_ci  uint32_t enc;
28361cb0ef41Sopenharmony_ci  if (CpuFeatures::IsSupported(VFPv3) && FitsVmovFPImmediate(imm, &enc)) {
28371cb0ef41Sopenharmony_ci    CpuFeatureScope scope(this, VFPv3);
28381cb0ef41Sopenharmony_ci    // The double can be encoded in the instruction.
28391cb0ef41Sopenharmony_ci    //
28401cb0ef41Sopenharmony_ci    // Dd = immediate
28411cb0ef41Sopenharmony_ci    // Instruction details available in ARM DDI 0406C.b, A8-936.
28421cb0ef41Sopenharmony_ci    // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | imm4H(19-16) |
28431cb0ef41Sopenharmony_ci    // Vd(15-12) | 101(11-9) | sz=1(8) | imm4L(3-0)
28441cb0ef41Sopenharmony_ci    int vd, d;
28451cb0ef41Sopenharmony_ci    dst.split_code(&vd, &d);
28461cb0ef41Sopenharmony_ci    emit(al | 0x1D * B23 | d * B22 | 0x3 * B20 | vd * B12 | 0x5 * B9 | B8 |
28471cb0ef41Sopenharmony_ci         enc);
28481cb0ef41Sopenharmony_ci  } else {
28491cb0ef41Sopenharmony_ci    // Synthesise the double from ARM immediates.
28501cb0ef41Sopenharmony_ci    uint32_t lo, hi;
28511cb0ef41Sopenharmony_ci    DoubleAsTwoUInt32(imm, &lo, &hi);
28521cb0ef41Sopenharmony_ci    UseScratchRegisterScope temps(this);
28531cb0ef41Sopenharmony_ci    Register scratch = temps.Acquire();
28541cb0ef41Sopenharmony_ci
28551cb0ef41Sopenharmony_ci    if (lo == hi) {
28561cb0ef41Sopenharmony_ci      // Move the low and high parts of the double to a D register in one
28571cb0ef41Sopenharmony_ci      // instruction.
28581cb0ef41Sopenharmony_ci      mov(scratch, Operand(lo));
28591cb0ef41Sopenharmony_ci      vmov(dst, scratch, scratch);
28601cb0ef41Sopenharmony_ci    } else if (extra_scratch == no_reg) {
28611cb0ef41Sopenharmony_ci      // We only have one spare scratch register.
28621cb0ef41Sopenharmony_ci      mov(scratch, Operand(lo));
28631cb0ef41Sopenharmony_ci      vmov(NeonS32, dst, 0, scratch);
28641cb0ef41Sopenharmony_ci      if (((lo & 0xFFFF) == (hi & 0xFFFF)) && CpuFeatures::IsSupported(ARMv7)) {
28651cb0ef41Sopenharmony_ci        CpuFeatureScope scope(this, ARMv7);
28661cb0ef41Sopenharmony_ci        movt(scratch, hi >> 16);
28671cb0ef41Sopenharmony_ci      } else {
28681cb0ef41Sopenharmony_ci        mov(scratch, Operand(hi));
28691cb0ef41Sopenharmony_ci      }
28701cb0ef41Sopenharmony_ci      vmov(NeonS32, dst, 1, scratch);
28711cb0ef41Sopenharmony_ci    } else {
28721cb0ef41Sopenharmony_ci      // Move the low and high parts of the double to a D register in one
28731cb0ef41Sopenharmony_ci      // instruction.
28741cb0ef41Sopenharmony_ci      mov(scratch, Operand(lo));
28751cb0ef41Sopenharmony_ci      mov(extra_scratch, Operand(hi));
28761cb0ef41Sopenharmony_ci      vmov(dst, scratch, extra_scratch);
28771cb0ef41Sopenharmony_ci    }
28781cb0ef41Sopenharmony_ci  }
28791cb0ef41Sopenharmony_ci}
28801cb0ef41Sopenharmony_ci
28811cb0ef41Sopenharmony_civoid Assembler::vmov(const SwVfpRegister dst, const SwVfpRegister src,
28821cb0ef41Sopenharmony_ci                     const Condition cond) {
28831cb0ef41Sopenharmony_ci  // Sd = Sm
28841cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406B, A8-642.
28851cb0ef41Sopenharmony_ci  int sd, d, sm, m;
28861cb0ef41Sopenharmony_ci  dst.split_code(&sd, &d);
28871cb0ef41Sopenharmony_ci  src.split_code(&sm, &m);
28881cb0ef41Sopenharmony_ci  emit(cond | 0xE * B24 | d * B22 | 0xB * B20 | sd * B12 | 0xA * B8 | B6 |
28891cb0ef41Sopenharmony_ci       m * B5 | sm);
28901cb0ef41Sopenharmony_ci}
28911cb0ef41Sopenharmony_ci
28921cb0ef41Sopenharmony_civoid Assembler::vmov(const DwVfpRegister dst, const DwVfpRegister src,
28931cb0ef41Sopenharmony_ci                     const Condition cond) {
28941cb0ef41Sopenharmony_ci  // Dd = Dm
28951cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-938.
28961cb0ef41Sopenharmony_ci  // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | 0000(19-16) | Vd(15-12) |
28971cb0ef41Sopenharmony_ci  // 101(11-9) | sz=1(8) | 0(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
28981cb0ef41Sopenharmony_ci  DCHECK(VfpRegisterIsAvailable(dst));
28991cb0ef41Sopenharmony_ci  DCHECK(VfpRegisterIsAvailable(src));
29001cb0ef41Sopenharmony_ci  int vd, d;
29011cb0ef41Sopenharmony_ci  dst.split_code(&vd, &d);
29021cb0ef41Sopenharmony_ci  int vm, m;
29031cb0ef41Sopenharmony_ci  src.split_code(&vm, &m);
29041cb0ef41Sopenharmony_ci  emit(cond | 0x1D * B23 | d * B22 | 0x3 * B20 | vd * B12 | 0x5 * B9 | B8 | B6 |
29051cb0ef41Sopenharmony_ci       m * B5 | vm);
29061cb0ef41Sopenharmony_ci}
29071cb0ef41Sopenharmony_ci
29081cb0ef41Sopenharmony_civoid Assembler::vmov(const DwVfpRegister dst, const Register src1,
29091cb0ef41Sopenharmony_ci                     const Register src2, const Condition cond) {
29101cb0ef41Sopenharmony_ci  // Dm = <Rt,Rt2>.
29111cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-948.
29121cb0ef41Sopenharmony_ci  // cond(31-28) | 1100(27-24)| 010(23-21) | op=0(20) | Rt2(19-16) |
29131cb0ef41Sopenharmony_ci  // Rt(15-12) | 1011(11-8) | 00(7-6) | M(5) | 1(4) | Vm
29141cb0ef41Sopenharmony_ci  DCHECK(VfpRegisterIsAvailable(dst));
29151cb0ef41Sopenharmony_ci  DCHECK(src1 != pc && src2 != pc);
29161cb0ef41Sopenharmony_ci  int vm, m;
29171cb0ef41Sopenharmony_ci  dst.split_code(&vm, &m);
29181cb0ef41Sopenharmony_ci  emit(cond | 0xC * B24 | B22 | src2.code() * B16 | src1.code() * B12 |
29191cb0ef41Sopenharmony_ci       0xB * B8 | m * B5 | B4 | vm);
29201cb0ef41Sopenharmony_ci}
29211cb0ef41Sopenharmony_ci
29221cb0ef41Sopenharmony_civoid Assembler::vmov(const Register dst1, const Register dst2,
29231cb0ef41Sopenharmony_ci                     const DwVfpRegister src, const Condition cond) {
29241cb0ef41Sopenharmony_ci  // <Rt,Rt2> = Dm.
29251cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-948.
29261cb0ef41Sopenharmony_ci  // cond(31-28) | 1100(27-24)| 010(23-21) | op=1(20) | Rt2(19-16) |
29271cb0ef41Sopenharmony_ci  // Rt(15-12) | 1011(11-8) | 00(7-6) | M(5) | 1(4) | Vm
29281cb0ef41Sopenharmony_ci  DCHECK(VfpRegisterIsAvailable(src));
29291cb0ef41Sopenharmony_ci  DCHECK(dst1 != pc && dst2 != pc);
29301cb0ef41Sopenharmony_ci  int vm, m;
29311cb0ef41Sopenharmony_ci  src.split_code(&vm, &m);
29321cb0ef41Sopenharmony_ci  emit(cond | 0xC * B24 | B22 | B20 | dst2.code() * B16 | dst1.code() * B12 |
29331cb0ef41Sopenharmony_ci       0xB * B8 | m * B5 | B4 | vm);
29341cb0ef41Sopenharmony_ci}
29351cb0ef41Sopenharmony_ci
29361cb0ef41Sopenharmony_civoid Assembler::vmov(const SwVfpRegister dst, const Register src,
29371cb0ef41Sopenharmony_ci                     const Condition cond) {
29381cb0ef41Sopenharmony_ci  // Sn = Rt.
29391cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406A, A8-642.
29401cb0ef41Sopenharmony_ci  // cond(31-28) | 1110(27-24)| 000(23-21) | op=0(20) | Vn(19-16) |
29411cb0ef41Sopenharmony_ci  // Rt(15-12) | 1010(11-8) | N(7)=0 | 00(6-5) | 1(4) | 0000(3-0)
29421cb0ef41Sopenharmony_ci  DCHECK(src != pc);
29431cb0ef41Sopenharmony_ci  int sn, n;
29441cb0ef41Sopenharmony_ci  dst.split_code(&sn, &n);
29451cb0ef41Sopenharmony_ci  emit(cond | 0xE * B24 | sn * B16 | src.code() * B12 | 0xA * B8 | n * B7 | B4);
29461cb0ef41Sopenharmony_ci}
29471cb0ef41Sopenharmony_ci
29481cb0ef41Sopenharmony_civoid Assembler::vmov(const Register dst, const SwVfpRegister src,
29491cb0ef41Sopenharmony_ci                     const Condition cond) {
29501cb0ef41Sopenharmony_ci  // Rt = Sn.
29511cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406A, A8-642.
29521cb0ef41Sopenharmony_ci  // cond(31-28) | 1110(27-24)| 000(23-21) | op=1(20) | Vn(19-16) |
29531cb0ef41Sopenharmony_ci  // Rt(15-12) | 1010(11-8) | N(7)=0 | 00(6-5) | 1(4) | 0000(3-0)
29541cb0ef41Sopenharmony_ci  DCHECK(dst != pc);
29551cb0ef41Sopenharmony_ci  int sn, n;
29561cb0ef41Sopenharmony_ci  src.split_code(&sn, &n);
29571cb0ef41Sopenharmony_ci  emit(cond | 0xE * B24 | B20 | sn * B16 | dst.code() * B12 | 0xA * B8 |
29581cb0ef41Sopenharmony_ci       n * B7 | B4);
29591cb0ef41Sopenharmony_ci}
29601cb0ef41Sopenharmony_ci
29611cb0ef41Sopenharmony_ci// Type of data to read from or write to VFP register.
29621cb0ef41Sopenharmony_ci// Used as specifier in generic vcvt instruction.
29631cb0ef41Sopenharmony_cienum VFPType { S32, U32, F32, F64 };
29641cb0ef41Sopenharmony_ci
29651cb0ef41Sopenharmony_cistatic bool IsSignedVFPType(VFPType type) {
29661cb0ef41Sopenharmony_ci  switch (type) {
29671cb0ef41Sopenharmony_ci    case S32:
29681cb0ef41Sopenharmony_ci      return true;
29691cb0ef41Sopenharmony_ci    case U32:
29701cb0ef41Sopenharmony_ci      return false;
29711cb0ef41Sopenharmony_ci    default:
29721cb0ef41Sopenharmony_ci      UNREACHABLE();
29731cb0ef41Sopenharmony_ci  }
29741cb0ef41Sopenharmony_ci}
29751cb0ef41Sopenharmony_ci
29761cb0ef41Sopenharmony_cistatic bool IsIntegerVFPType(VFPType type) {
29771cb0ef41Sopenharmony_ci  switch (type) {
29781cb0ef41Sopenharmony_ci    case S32:
29791cb0ef41Sopenharmony_ci    case U32:
29801cb0ef41Sopenharmony_ci      return true;
29811cb0ef41Sopenharmony_ci    case F32:
29821cb0ef41Sopenharmony_ci    case F64:
29831cb0ef41Sopenharmony_ci      return false;
29841cb0ef41Sopenharmony_ci    default:
29851cb0ef41Sopenharmony_ci      UNREACHABLE();
29861cb0ef41Sopenharmony_ci  }
29871cb0ef41Sopenharmony_ci}
29881cb0ef41Sopenharmony_ci
29891cb0ef41Sopenharmony_cistatic bool IsDoubleVFPType(VFPType type) {
29901cb0ef41Sopenharmony_ci  switch (type) {
29911cb0ef41Sopenharmony_ci    case F32:
29921cb0ef41Sopenharmony_ci      return false;
29931cb0ef41Sopenharmony_ci    case F64:
29941cb0ef41Sopenharmony_ci      return true;
29951cb0ef41Sopenharmony_ci    default:
29961cb0ef41Sopenharmony_ci      UNREACHABLE();
29971cb0ef41Sopenharmony_ci  }
29981cb0ef41Sopenharmony_ci}
29991cb0ef41Sopenharmony_ci
30001cb0ef41Sopenharmony_ci// Split five bit reg_code based on size of reg_type.
30011cb0ef41Sopenharmony_ci//  32-bit register codes are Vm:M
30021cb0ef41Sopenharmony_ci//  64-bit register codes are M:Vm
30031cb0ef41Sopenharmony_ci// where Vm is four bits, and M is a single bit.
30041cb0ef41Sopenharmony_cistatic void SplitRegCode(VFPType reg_type, int reg_code, int* vm, int* m) {
30051cb0ef41Sopenharmony_ci  DCHECK((reg_code >= 0) && (reg_code <= 31));
30061cb0ef41Sopenharmony_ci  if (IsIntegerVFPType(reg_type) || !IsDoubleVFPType(reg_type)) {
30071cb0ef41Sopenharmony_ci    SwVfpRegister::split_code(reg_code, vm, m);
30081cb0ef41Sopenharmony_ci  } else {
30091cb0ef41Sopenharmony_ci    DwVfpRegister::split_code(reg_code, vm, m);
30101cb0ef41Sopenharmony_ci  }
30111cb0ef41Sopenharmony_ci}
30121cb0ef41Sopenharmony_ci
30131cb0ef41Sopenharmony_ci// Encode vcvt.src_type.dst_type instruction.
30141cb0ef41Sopenharmony_cistatic Instr EncodeVCVT(const VFPType dst_type, const int dst_code,
30151cb0ef41Sopenharmony_ci                        const VFPType src_type, const int src_code,
30161cb0ef41Sopenharmony_ci                        VFPConversionMode mode, const Condition cond) {
30171cb0ef41Sopenharmony_ci  DCHECK(src_type != dst_type);
30181cb0ef41Sopenharmony_ci  int D, Vd, M, Vm;
30191cb0ef41Sopenharmony_ci  SplitRegCode(src_type, src_code, &Vm, &M);
30201cb0ef41Sopenharmony_ci  SplitRegCode(dst_type, dst_code, &Vd, &D);
30211cb0ef41Sopenharmony_ci
30221cb0ef41Sopenharmony_ci  if (IsIntegerVFPType(dst_type) || IsIntegerVFPType(src_type)) {
30231cb0ef41Sopenharmony_ci    // Conversion between IEEE floating point and 32-bit integer.
30241cb0ef41Sopenharmony_ci    // Instruction details available in ARM DDI 0406B, A8.6.295.
30251cb0ef41Sopenharmony_ci    // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 1(19) | opc2(18-16) |
30261cb0ef41Sopenharmony_ci    // Vd(15-12) | 101(11-9) | sz(8) | op(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
30271cb0ef41Sopenharmony_ci    DCHECK(!IsIntegerVFPType(dst_type) || !IsIntegerVFPType(src_type));
30281cb0ef41Sopenharmony_ci
30291cb0ef41Sopenharmony_ci    int sz, opc2, op;
30301cb0ef41Sopenharmony_ci
30311cb0ef41Sopenharmony_ci    if (IsIntegerVFPType(dst_type)) {
30321cb0ef41Sopenharmony_ci      opc2 = IsSignedVFPType(dst_type) ? 0x5 : 0x4;
30331cb0ef41Sopenharmony_ci      sz = IsDoubleVFPType(src_type) ? 0x1 : 0x0;
30341cb0ef41Sopenharmony_ci      op = mode;
30351cb0ef41Sopenharmony_ci    } else {
30361cb0ef41Sopenharmony_ci      DCHECK(IsIntegerVFPType(src_type));
30371cb0ef41Sopenharmony_ci      opc2 = 0x0;
30381cb0ef41Sopenharmony_ci      sz = IsDoubleVFPType(dst_type) ? 0x1 : 0x0;
30391cb0ef41Sopenharmony_ci      op = IsSignedVFPType(src_type) ? 0x1 : 0x0;
30401cb0ef41Sopenharmony_ci    }
30411cb0ef41Sopenharmony_ci
30421cb0ef41Sopenharmony_ci    return (cond | 0xE * B24 | B23 | D * B22 | 0x3 * B20 | B19 | opc2 * B16 |
30431cb0ef41Sopenharmony_ci            Vd * B12 | 0x5 * B9 | sz * B8 | op * B7 | B6 | M * B5 | Vm);
30441cb0ef41Sopenharmony_ci  } else {
30451cb0ef41Sopenharmony_ci    // Conversion between IEEE double and single precision.
30461cb0ef41Sopenharmony_ci    // Instruction details available in ARM DDI 0406B, A8.6.298.
30471cb0ef41Sopenharmony_ci    // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 0111(19-16) |
30481cb0ef41Sopenharmony_ci    // Vd(15-12) | 101(11-9) | sz(8) | 1(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
30491cb0ef41Sopenharmony_ci    int sz = IsDoubleVFPType(src_type) ? 0x1 : 0x0;
30501cb0ef41Sopenharmony_ci    return (cond | 0xE * B24 | B23 | D * B22 | 0x3 * B20 | 0x7 * B16 |
30511cb0ef41Sopenharmony_ci            Vd * B12 | 0x5 * B9 | sz * B8 | B7 | B6 | M * B5 | Vm);
30521cb0ef41Sopenharmony_ci  }
30531cb0ef41Sopenharmony_ci}
30541cb0ef41Sopenharmony_ci
30551cb0ef41Sopenharmony_civoid Assembler::vcvt_f64_s32(const DwVfpRegister dst, const SwVfpRegister src,
30561cb0ef41Sopenharmony_ci                             VFPConversionMode mode, const Condition cond) {
30571cb0ef41Sopenharmony_ci  DCHECK(VfpRegisterIsAvailable(dst));
30581cb0ef41Sopenharmony_ci  emit(EncodeVCVT(F64, dst.code(), S32, src.code(), mode, cond));
30591cb0ef41Sopenharmony_ci}
30601cb0ef41Sopenharmony_ci
30611cb0ef41Sopenharmony_civoid Assembler::vcvt_f32_s32(const SwVfpRegister dst, const SwVfpRegister src,
30621cb0ef41Sopenharmony_ci                             VFPConversionMode mode, const Condition cond) {
30631cb0ef41Sopenharmony_ci  emit(EncodeVCVT(F32, dst.code(), S32, src.code(), mode, cond));
30641cb0ef41Sopenharmony_ci}
30651cb0ef41Sopenharmony_ci
30661cb0ef41Sopenharmony_civoid Assembler::vcvt_f64_u32(const DwVfpRegister dst, const SwVfpRegister src,
30671cb0ef41Sopenharmony_ci                             VFPConversionMode mode, const Condition cond) {
30681cb0ef41Sopenharmony_ci  DCHECK(VfpRegisterIsAvailable(dst));
30691cb0ef41Sopenharmony_ci  emit(EncodeVCVT(F64, dst.code(), U32, src.code(), mode, cond));
30701cb0ef41Sopenharmony_ci}
30711cb0ef41Sopenharmony_ci
30721cb0ef41Sopenharmony_civoid Assembler::vcvt_f32_u32(const SwVfpRegister dst, const SwVfpRegister src,
30731cb0ef41Sopenharmony_ci                             VFPConversionMode mode, const Condition cond) {
30741cb0ef41Sopenharmony_ci  emit(EncodeVCVT(F32, dst.code(), U32, src.code(), mode, cond));
30751cb0ef41Sopenharmony_ci}
30761cb0ef41Sopenharmony_ci
30771cb0ef41Sopenharmony_civoid Assembler::vcvt_s32_f32(const SwVfpRegister dst, const SwVfpRegister src,
30781cb0ef41Sopenharmony_ci                             VFPConversionMode mode, const Condition cond) {
30791cb0ef41Sopenharmony_ci  emit(EncodeVCVT(S32, dst.code(), F32, src.code(), mode, cond));
30801cb0ef41Sopenharmony_ci}
30811cb0ef41Sopenharmony_ci
30821cb0ef41Sopenharmony_civoid Assembler::vcvt_u32_f32(const SwVfpRegister dst, const SwVfpRegister src,
30831cb0ef41Sopenharmony_ci                             VFPConversionMode mode, const Condition cond) {
30841cb0ef41Sopenharmony_ci  emit(EncodeVCVT(U32, dst.code(), F32, src.code(), mode, cond));
30851cb0ef41Sopenharmony_ci}
30861cb0ef41Sopenharmony_ci
30871cb0ef41Sopenharmony_civoid Assembler::vcvt_s32_f64(const SwVfpRegister dst, const DwVfpRegister src,
30881cb0ef41Sopenharmony_ci                             VFPConversionMode mode, const Condition cond) {
30891cb0ef41Sopenharmony_ci  DCHECK(VfpRegisterIsAvailable(src));
30901cb0ef41Sopenharmony_ci  emit(EncodeVCVT(S32, dst.code(), F64, src.code(), mode, cond));
30911cb0ef41Sopenharmony_ci}
30921cb0ef41Sopenharmony_ci
30931cb0ef41Sopenharmony_civoid Assembler::vcvt_u32_f64(const SwVfpRegister dst, const DwVfpRegister src,
30941cb0ef41Sopenharmony_ci                             VFPConversionMode mode, const Condition cond) {
30951cb0ef41Sopenharmony_ci  DCHECK(VfpRegisterIsAvailable(src));
30961cb0ef41Sopenharmony_ci  emit(EncodeVCVT(U32, dst.code(), F64, src.code(), mode, cond));
30971cb0ef41Sopenharmony_ci}
30981cb0ef41Sopenharmony_ci
30991cb0ef41Sopenharmony_civoid Assembler::vcvt_f64_f32(const DwVfpRegister dst, const SwVfpRegister src,
31001cb0ef41Sopenharmony_ci                             VFPConversionMode mode, const Condition cond) {
31011cb0ef41Sopenharmony_ci  DCHECK(VfpRegisterIsAvailable(dst));
31021cb0ef41Sopenharmony_ci  emit(EncodeVCVT(F64, dst.code(), F32, src.code(), mode, cond));
31031cb0ef41Sopenharmony_ci}
31041cb0ef41Sopenharmony_ci
31051cb0ef41Sopenharmony_civoid Assembler::vcvt_f32_f64(const SwVfpRegister dst, const DwVfpRegister src,
31061cb0ef41Sopenharmony_ci                             VFPConversionMode mode, const Condition cond) {
31071cb0ef41Sopenharmony_ci  DCHECK(VfpRegisterIsAvailable(src));
31081cb0ef41Sopenharmony_ci  emit(EncodeVCVT(F32, dst.code(), F64, src.code(), mode, cond));
31091cb0ef41Sopenharmony_ci}
31101cb0ef41Sopenharmony_ci
31111cb0ef41Sopenharmony_civoid Assembler::vcvt_f64_s32(const DwVfpRegister dst, int fraction_bits,
31121cb0ef41Sopenharmony_ci                             const Condition cond) {
31131cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-874.
31141cb0ef41Sopenharmony_ci  // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | 1010(19-16) | Vd(15-12) |
31151cb0ef41Sopenharmony_ci  // 101(11-9) | sf=1(8) | sx=1(7) | 1(6) | i(5) | 0(4) | imm4(3-0)
31161cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(VFPv3));
31171cb0ef41Sopenharmony_ci  DCHECK(VfpRegisterIsAvailable(dst));
31181cb0ef41Sopenharmony_ci  DCHECK(fraction_bits > 0 && fraction_bits <= 32);
31191cb0ef41Sopenharmony_ci  int vd, d;
31201cb0ef41Sopenharmony_ci  dst.split_code(&vd, &d);
31211cb0ef41Sopenharmony_ci  int imm5 = 32 - fraction_bits;
31221cb0ef41Sopenharmony_ci  int i = imm5 & 1;
31231cb0ef41Sopenharmony_ci  int imm4 = (imm5 >> 1) & 0xF;
31241cb0ef41Sopenharmony_ci  emit(cond | 0xE * B24 | B23 | d * B22 | 0x3 * B20 | B19 | 0x2 * B16 |
31251cb0ef41Sopenharmony_ci       vd * B12 | 0x5 * B9 | B8 | B7 | B6 | i * B5 | imm4);
31261cb0ef41Sopenharmony_ci}
31271cb0ef41Sopenharmony_ci
31281cb0ef41Sopenharmony_civoid Assembler::vneg(const DwVfpRegister dst, const DwVfpRegister src,
31291cb0ef41Sopenharmony_ci                     const Condition cond) {
31301cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-968.
31311cb0ef41Sopenharmony_ci  // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | 0001(19-16) | Vd(15-12) |
31321cb0ef41Sopenharmony_ci  // 101(11-9) | sz=1(8) | 0(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
31331cb0ef41Sopenharmony_ci  DCHECK(VfpRegisterIsAvailable(dst));
31341cb0ef41Sopenharmony_ci  DCHECK(VfpRegisterIsAvailable(src));
31351cb0ef41Sopenharmony_ci  int vd, d;
31361cb0ef41Sopenharmony_ci  dst.split_code(&vd, &d);
31371cb0ef41Sopenharmony_ci  int vm, m;
31381cb0ef41Sopenharmony_ci  src.split_code(&vm, &m);
31391cb0ef41Sopenharmony_ci
31401cb0ef41Sopenharmony_ci  emit(cond | 0x1D * B23 | d * B22 | 0x3 * B20 | B16 | vd * B12 | 0x5 * B9 |
31411cb0ef41Sopenharmony_ci       B8 | B6 | m * B5 | vm);
31421cb0ef41Sopenharmony_ci}
31431cb0ef41Sopenharmony_ci
31441cb0ef41Sopenharmony_civoid Assembler::vneg(const SwVfpRegister dst, const SwVfpRegister src,
31451cb0ef41Sopenharmony_ci                     const Condition cond) {
31461cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-968.
31471cb0ef41Sopenharmony_ci  // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | 0001(19-16) | Vd(15-12) |
31481cb0ef41Sopenharmony_ci  // 101(11-9) | sz=0(8) | 0(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
31491cb0ef41Sopenharmony_ci  int vd, d;
31501cb0ef41Sopenharmony_ci  dst.split_code(&vd, &d);
31511cb0ef41Sopenharmony_ci  int vm, m;
31521cb0ef41Sopenharmony_ci  src.split_code(&vm, &m);
31531cb0ef41Sopenharmony_ci
31541cb0ef41Sopenharmony_ci  emit(cond | 0x1D * B23 | d * B22 | 0x3 * B20 | B16 | vd * B12 | 0x5 * B9 |
31551cb0ef41Sopenharmony_ci       B6 | m * B5 | vm);
31561cb0ef41Sopenharmony_ci}
31571cb0ef41Sopenharmony_ci
31581cb0ef41Sopenharmony_civoid Assembler::vabs(const DwVfpRegister dst, const DwVfpRegister src,
31591cb0ef41Sopenharmony_ci                     const Condition cond) {
31601cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-524.
31611cb0ef41Sopenharmony_ci  // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | 0000(19-16) | Vd(15-12) |
31621cb0ef41Sopenharmony_ci  // 101(11-9) | sz=1(8) | 1(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
31631cb0ef41Sopenharmony_ci  DCHECK(VfpRegisterIsAvailable(dst));
31641cb0ef41Sopenharmony_ci  DCHECK(VfpRegisterIsAvailable(src));
31651cb0ef41Sopenharmony_ci  int vd, d;
31661cb0ef41Sopenharmony_ci  dst.split_code(&vd, &d);
31671cb0ef41Sopenharmony_ci  int vm, m;
31681cb0ef41Sopenharmony_ci  src.split_code(&vm, &m);
31691cb0ef41Sopenharmony_ci  emit(cond | 0x1D * B23 | d * B22 | 0x3 * B20 | vd * B12 | 0x5 * B9 | B8 | B7 |
31701cb0ef41Sopenharmony_ci       B6 | m * B5 | vm);
31711cb0ef41Sopenharmony_ci}
31721cb0ef41Sopenharmony_ci
31731cb0ef41Sopenharmony_civoid Assembler::vabs(const SwVfpRegister dst, const SwVfpRegister src,
31741cb0ef41Sopenharmony_ci                     const Condition cond) {
31751cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-524.
31761cb0ef41Sopenharmony_ci  // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | 0000(19-16) | Vd(15-12) |
31771cb0ef41Sopenharmony_ci  // 101(11-9) | sz=0(8) | 1(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
31781cb0ef41Sopenharmony_ci  int vd, d;
31791cb0ef41Sopenharmony_ci  dst.split_code(&vd, &d);
31801cb0ef41Sopenharmony_ci  int vm, m;
31811cb0ef41Sopenharmony_ci  src.split_code(&vm, &m);
31821cb0ef41Sopenharmony_ci  emit(cond | 0x1D * B23 | d * B22 | 0x3 * B20 | vd * B12 | 0x5 * B9 | B7 | B6 |
31831cb0ef41Sopenharmony_ci       m * B5 | vm);
31841cb0ef41Sopenharmony_ci}
31851cb0ef41Sopenharmony_ci
31861cb0ef41Sopenharmony_civoid Assembler::vadd(const DwVfpRegister dst, const DwVfpRegister src1,
31871cb0ef41Sopenharmony_ci                     const DwVfpRegister src2, const Condition cond) {
31881cb0ef41Sopenharmony_ci  // Dd = vadd(Dn, Dm) double precision floating point addition.
31891cb0ef41Sopenharmony_ci  // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm.
31901cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-830.
31911cb0ef41Sopenharmony_ci  // cond(31-28) | 11100(27-23)| D(22) | 11(21-20) | Vn(19-16) |
31921cb0ef41Sopenharmony_ci  // Vd(15-12) | 101(11-9) | sz=1(8) | N(7) | 0(6) | M(5) | 0(4) | Vm(3-0)
31931cb0ef41Sopenharmony_ci  DCHECK(VfpRegisterIsAvailable(dst));
31941cb0ef41Sopenharmony_ci  DCHECK(VfpRegisterIsAvailable(src1));
31951cb0ef41Sopenharmony_ci  DCHECK(VfpRegisterIsAvailable(src2));
31961cb0ef41Sopenharmony_ci  int vd, d;
31971cb0ef41Sopenharmony_ci  dst.split_code(&vd, &d);
31981cb0ef41Sopenharmony_ci  int vn, n;
31991cb0ef41Sopenharmony_ci  src1.split_code(&vn, &n);
32001cb0ef41Sopenharmony_ci  int vm, m;
32011cb0ef41Sopenharmony_ci  src2.split_code(&vm, &m);
32021cb0ef41Sopenharmony_ci  emit(cond | 0x1C * B23 | d * B22 | 0x3 * B20 | vn * B16 | vd * B12 |
32031cb0ef41Sopenharmony_ci       0x5 * B9 | B8 | n * B7 | m * B5 | vm);
32041cb0ef41Sopenharmony_ci}
32051cb0ef41Sopenharmony_ci
32061cb0ef41Sopenharmony_civoid Assembler::vadd(const SwVfpRegister dst, const SwVfpRegister src1,
32071cb0ef41Sopenharmony_ci                     const SwVfpRegister src2, const Condition cond) {
32081cb0ef41Sopenharmony_ci  // Sd = vadd(Sn, Sm) single precision floating point addition.
32091cb0ef41Sopenharmony_ci  // Sd = D:Vd; Sm=M:Vm; Sn=N:Vm.
32101cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-830.
32111cb0ef41Sopenharmony_ci  // cond(31-28) | 11100(27-23)| D(22) | 11(21-20) | Vn(19-16) |
32121cb0ef41Sopenharmony_ci  // Vd(15-12) | 101(11-9) | sz=0(8) | N(7) | 0(6) | M(5) | 0(4) | Vm(3-0)
32131cb0ef41Sopenharmony_ci  int vd, d;
32141cb0ef41Sopenharmony_ci  dst.split_code(&vd, &d);
32151cb0ef41Sopenharmony_ci  int vn, n;
32161cb0ef41Sopenharmony_ci  src1.split_code(&vn, &n);
32171cb0ef41Sopenharmony_ci  int vm, m;
32181cb0ef41Sopenharmony_ci  src2.split_code(&vm, &m);
32191cb0ef41Sopenharmony_ci  emit(cond | 0x1C * B23 | d * B22 | 0x3 * B20 | vn * B16 | vd * B12 |
32201cb0ef41Sopenharmony_ci       0x5 * B9 | n * B7 | m * B5 | vm);
32211cb0ef41Sopenharmony_ci}
32221cb0ef41Sopenharmony_ci
32231cb0ef41Sopenharmony_civoid Assembler::vsub(const DwVfpRegister dst, const DwVfpRegister src1,
32241cb0ef41Sopenharmony_ci                     const DwVfpRegister src2, const Condition cond) {
32251cb0ef41Sopenharmony_ci  // Dd = vsub(Dn, Dm) double precision floating point subtraction.
32261cb0ef41Sopenharmony_ci  // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm.
32271cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-1086.
32281cb0ef41Sopenharmony_ci  // cond(31-28) | 11100(27-23)| D(22) | 11(21-20) | Vn(19-16) |
32291cb0ef41Sopenharmony_ci  // Vd(15-12) | 101(11-9) | sz=1(8) | N(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
32301cb0ef41Sopenharmony_ci  DCHECK(VfpRegisterIsAvailable(dst));
32311cb0ef41Sopenharmony_ci  DCHECK(VfpRegisterIsAvailable(src1));
32321cb0ef41Sopenharmony_ci  DCHECK(VfpRegisterIsAvailable(src2));
32331cb0ef41Sopenharmony_ci  int vd, d;
32341cb0ef41Sopenharmony_ci  dst.split_code(&vd, &d);
32351cb0ef41Sopenharmony_ci  int vn, n;
32361cb0ef41Sopenharmony_ci  src1.split_code(&vn, &n);
32371cb0ef41Sopenharmony_ci  int vm, m;
32381cb0ef41Sopenharmony_ci  src2.split_code(&vm, &m);
32391cb0ef41Sopenharmony_ci  emit(cond | 0x1C * B23 | d * B22 | 0x3 * B20 | vn * B16 | vd * B12 |
32401cb0ef41Sopenharmony_ci       0x5 * B9 | B8 | n * B7 | B6 | m * B5 | vm);
32411cb0ef41Sopenharmony_ci}
32421cb0ef41Sopenharmony_ci
32431cb0ef41Sopenharmony_civoid Assembler::vsub(const SwVfpRegister dst, const SwVfpRegister src1,
32441cb0ef41Sopenharmony_ci                     const SwVfpRegister src2, const Condition cond) {
32451cb0ef41Sopenharmony_ci  // Sd = vsub(Sn, Sm) single precision floating point subtraction.
32461cb0ef41Sopenharmony_ci  // Sd = D:Vd; Sm=M:Vm; Sn=N:Vm.
32471cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-1086.
32481cb0ef41Sopenharmony_ci  // cond(31-28) | 11100(27-23)| D(22) | 11(21-20) | Vn(19-16) |
32491cb0ef41Sopenharmony_ci  // Vd(15-12) | 101(11-9) | sz=0(8) | N(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
32501cb0ef41Sopenharmony_ci  int vd, d;
32511cb0ef41Sopenharmony_ci  dst.split_code(&vd, &d);
32521cb0ef41Sopenharmony_ci  int vn, n;
32531cb0ef41Sopenharmony_ci  src1.split_code(&vn, &n);
32541cb0ef41Sopenharmony_ci  int vm, m;
32551cb0ef41Sopenharmony_ci  src2.split_code(&vm, &m);
32561cb0ef41Sopenharmony_ci  emit(cond | 0x1C * B23 | d * B22 | 0x3 * B20 | vn * B16 | vd * B12 |
32571cb0ef41Sopenharmony_ci       0x5 * B9 | n * B7 | B6 | m * B5 | vm);
32581cb0ef41Sopenharmony_ci}
32591cb0ef41Sopenharmony_ci
32601cb0ef41Sopenharmony_civoid Assembler::vmul(const DwVfpRegister dst, const DwVfpRegister src1,
32611cb0ef41Sopenharmony_ci                     const DwVfpRegister src2, const Condition cond) {
32621cb0ef41Sopenharmony_ci  // Dd = vmul(Dn, Dm) double precision floating point multiplication.
32631cb0ef41Sopenharmony_ci  // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm.
32641cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-960.
32651cb0ef41Sopenharmony_ci  // cond(31-28) | 11100(27-23)| D(22) | 10(21-20) | Vn(19-16) |
32661cb0ef41Sopenharmony_ci  // Vd(15-12) | 101(11-9) | sz=1(8) | N(7) | 0(6) | M(5) | 0(4) | Vm(3-0)
32671cb0ef41Sopenharmony_ci  DCHECK(VfpRegisterIsAvailable(dst));
32681cb0ef41Sopenharmony_ci  DCHECK(VfpRegisterIsAvailable(src1));
32691cb0ef41Sopenharmony_ci  DCHECK(VfpRegisterIsAvailable(src2));
32701cb0ef41Sopenharmony_ci  int vd, d;
32711cb0ef41Sopenharmony_ci  dst.split_code(&vd, &d);
32721cb0ef41Sopenharmony_ci  int vn, n;
32731cb0ef41Sopenharmony_ci  src1.split_code(&vn, &n);
32741cb0ef41Sopenharmony_ci  int vm, m;
32751cb0ef41Sopenharmony_ci  src2.split_code(&vm, &m);
32761cb0ef41Sopenharmony_ci  emit(cond | 0x1C * B23 | d * B22 | 0x2 * B20 | vn * B16 | vd * B12 |
32771cb0ef41Sopenharmony_ci       0x5 * B9 | B8 | n * B7 | m * B5 | vm);
32781cb0ef41Sopenharmony_ci}
32791cb0ef41Sopenharmony_ci
32801cb0ef41Sopenharmony_civoid Assembler::vmul(const SwVfpRegister dst, const SwVfpRegister src1,
32811cb0ef41Sopenharmony_ci                     const SwVfpRegister src2, const Condition cond) {
32821cb0ef41Sopenharmony_ci  // Sd = vmul(Sn, Sm) single precision floating point multiplication.
32831cb0ef41Sopenharmony_ci  // Sd = D:Vd; Sm=M:Vm; Sn=N:Vm.
32841cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-960.
32851cb0ef41Sopenharmony_ci  // cond(31-28) | 11100(27-23)| D(22) | 10(21-20) | Vn(19-16) |
32861cb0ef41Sopenharmony_ci  // Vd(15-12) | 101(11-9) | sz=0(8) | N(7) | 0(6) | M(5) | 0(4) | Vm(3-0)
32871cb0ef41Sopenharmony_ci  int vd, d;
32881cb0ef41Sopenharmony_ci  dst.split_code(&vd, &d);
32891cb0ef41Sopenharmony_ci  int vn, n;
32901cb0ef41Sopenharmony_ci  src1.split_code(&vn, &n);
32911cb0ef41Sopenharmony_ci  int vm, m;
32921cb0ef41Sopenharmony_ci  src2.split_code(&vm, &m);
32931cb0ef41Sopenharmony_ci  emit(cond | 0x1C * B23 | d * B22 | 0x2 * B20 | vn * B16 | vd * B12 |
32941cb0ef41Sopenharmony_ci       0x5 * B9 | n * B7 | m * B5 | vm);
32951cb0ef41Sopenharmony_ci}
32961cb0ef41Sopenharmony_ci
32971cb0ef41Sopenharmony_civoid Assembler::vmla(const DwVfpRegister dst, const DwVfpRegister src1,
32981cb0ef41Sopenharmony_ci                     const DwVfpRegister src2, const Condition cond) {
32991cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-932.
33001cb0ef41Sopenharmony_ci  // cond(31-28) | 11100(27-23) | D(22) | 00(21-20) | Vn(19-16) |
33011cb0ef41Sopenharmony_ci  // Vd(15-12) | 101(11-9) | sz=1(8) | N(7) | op=0(6) | M(5) | 0(4) | Vm(3-0)
33021cb0ef41Sopenharmony_ci  DCHECK(VfpRegisterIsAvailable(dst));
33031cb0ef41Sopenharmony_ci  DCHECK(VfpRegisterIsAvailable(src1));
33041cb0ef41Sopenharmony_ci  DCHECK(VfpRegisterIsAvailable(src2));
33051cb0ef41Sopenharmony_ci  int vd, d;
33061cb0ef41Sopenharmony_ci  dst.split_code(&vd, &d);
33071cb0ef41Sopenharmony_ci  int vn, n;
33081cb0ef41Sopenharmony_ci  src1.split_code(&vn, &n);
33091cb0ef41Sopenharmony_ci  int vm, m;
33101cb0ef41Sopenharmony_ci  src2.split_code(&vm, &m);
33111cb0ef41Sopenharmony_ci  emit(cond | 0x1C * B23 | d * B22 | vn * B16 | vd * B12 | 0x5 * B9 | B8 |
33121cb0ef41Sopenharmony_ci       n * B7 | m * B5 | vm);
33131cb0ef41Sopenharmony_ci}
33141cb0ef41Sopenharmony_ci
33151cb0ef41Sopenharmony_civoid Assembler::vmla(const SwVfpRegister dst, const SwVfpRegister src1,
33161cb0ef41Sopenharmony_ci                     const SwVfpRegister src2, const Condition cond) {
33171cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-932.
33181cb0ef41Sopenharmony_ci  // cond(31-28) | 11100(27-23) | D(22) | 00(21-20) | Vn(19-16) |
33191cb0ef41Sopenharmony_ci  // Vd(15-12) | 101(11-9) | sz=0(8) | N(7) | op=0(6) | M(5) | 0(4) | Vm(3-0)
33201cb0ef41Sopenharmony_ci  int vd, d;
33211cb0ef41Sopenharmony_ci  dst.split_code(&vd, &d);
33221cb0ef41Sopenharmony_ci  int vn, n;
33231cb0ef41Sopenharmony_ci  src1.split_code(&vn, &n);
33241cb0ef41Sopenharmony_ci  int vm, m;
33251cb0ef41Sopenharmony_ci  src2.split_code(&vm, &m);
33261cb0ef41Sopenharmony_ci  emit(cond | 0x1C * B23 | d * B22 | vn * B16 | vd * B12 | 0x5 * B9 | n * B7 |
33271cb0ef41Sopenharmony_ci       m * B5 | vm);
33281cb0ef41Sopenharmony_ci}
33291cb0ef41Sopenharmony_ci
33301cb0ef41Sopenharmony_civoid Assembler::vmls(const DwVfpRegister dst, const DwVfpRegister src1,
33311cb0ef41Sopenharmony_ci                     const DwVfpRegister src2, const Condition cond) {
33321cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-932.
33331cb0ef41Sopenharmony_ci  // cond(31-28) | 11100(27-23) | D(22) | 00(21-20) | Vn(19-16) |
33341cb0ef41Sopenharmony_ci  // Vd(15-12) | 101(11-9) | sz=1(8) | N(7) | op=1(6) | M(5) | 0(4) | Vm(3-0)
33351cb0ef41Sopenharmony_ci  DCHECK(VfpRegisterIsAvailable(dst));
33361cb0ef41Sopenharmony_ci  DCHECK(VfpRegisterIsAvailable(src1));
33371cb0ef41Sopenharmony_ci  DCHECK(VfpRegisterIsAvailable(src2));
33381cb0ef41Sopenharmony_ci  int vd, d;
33391cb0ef41Sopenharmony_ci  dst.split_code(&vd, &d);
33401cb0ef41Sopenharmony_ci  int vn, n;
33411cb0ef41Sopenharmony_ci  src1.split_code(&vn, &n);
33421cb0ef41Sopenharmony_ci  int vm, m;
33431cb0ef41Sopenharmony_ci  src2.split_code(&vm, &m);
33441cb0ef41Sopenharmony_ci  emit(cond | 0x1C * B23 | d * B22 | vn * B16 | vd * B12 | 0x5 * B9 | B8 |
33451cb0ef41Sopenharmony_ci       n * B7 | B6 | m * B5 | vm);
33461cb0ef41Sopenharmony_ci}
33471cb0ef41Sopenharmony_ci
33481cb0ef41Sopenharmony_civoid Assembler::vmls(const SwVfpRegister dst, const SwVfpRegister src1,
33491cb0ef41Sopenharmony_ci                     const SwVfpRegister src2, const Condition cond) {
33501cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-932.
33511cb0ef41Sopenharmony_ci  // cond(31-28) | 11100(27-23) | D(22) | 00(21-20) | Vn(19-16) |
33521cb0ef41Sopenharmony_ci  // Vd(15-12) | 101(11-9) | sz=0(8) | N(7) | op=1(6) | M(5) | 0(4) | Vm(3-0)
33531cb0ef41Sopenharmony_ci  int vd, d;
33541cb0ef41Sopenharmony_ci  dst.split_code(&vd, &d);
33551cb0ef41Sopenharmony_ci  int vn, n;
33561cb0ef41Sopenharmony_ci  src1.split_code(&vn, &n);
33571cb0ef41Sopenharmony_ci  int vm, m;
33581cb0ef41Sopenharmony_ci  src2.split_code(&vm, &m);
33591cb0ef41Sopenharmony_ci  emit(cond | 0x1C * B23 | d * B22 | vn * B16 | vd * B12 | 0x5 * B9 | n * B7 |
33601cb0ef41Sopenharmony_ci       B6 | m * B5 | vm);
33611cb0ef41Sopenharmony_ci}
33621cb0ef41Sopenharmony_ci
33631cb0ef41Sopenharmony_civoid Assembler::vdiv(const DwVfpRegister dst, const DwVfpRegister src1,
33641cb0ef41Sopenharmony_ci                     const DwVfpRegister src2, const Condition cond) {
33651cb0ef41Sopenharmony_ci  // Dd = vdiv(Dn, Dm) double precision floating point division.
33661cb0ef41Sopenharmony_ci  // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm.
33671cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-882.
33681cb0ef41Sopenharmony_ci  // cond(31-28) | 11101(27-23)| D(22) | 00(21-20) | Vn(19-16) |
33691cb0ef41Sopenharmony_ci  // Vd(15-12) | 101(11-9) | sz=1(8) | N(7) | 0(6) | M(5) | 0(4) | Vm(3-0)
33701cb0ef41Sopenharmony_ci  DCHECK(VfpRegisterIsAvailable(dst));
33711cb0ef41Sopenharmony_ci  DCHECK(VfpRegisterIsAvailable(src1));
33721cb0ef41Sopenharmony_ci  DCHECK(VfpRegisterIsAvailable(src2));
33731cb0ef41Sopenharmony_ci  int vd, d;
33741cb0ef41Sopenharmony_ci  dst.split_code(&vd, &d);
33751cb0ef41Sopenharmony_ci  int vn, n;
33761cb0ef41Sopenharmony_ci  src1.split_code(&vn, &n);
33771cb0ef41Sopenharmony_ci  int vm, m;
33781cb0ef41Sopenharmony_ci  src2.split_code(&vm, &m);
33791cb0ef41Sopenharmony_ci  emit(cond | 0x1D * B23 | d * B22 | vn * B16 | vd * B12 | 0x5 * B9 | B8 |
33801cb0ef41Sopenharmony_ci       n * B7 | m * B5 | vm);
33811cb0ef41Sopenharmony_ci}
33821cb0ef41Sopenharmony_ci
33831cb0ef41Sopenharmony_civoid Assembler::vdiv(const SwVfpRegister dst, const SwVfpRegister src1,
33841cb0ef41Sopenharmony_ci                     const SwVfpRegister src2, const Condition cond) {
33851cb0ef41Sopenharmony_ci  // Sd = vdiv(Sn, Sm) single precision floating point division.
33861cb0ef41Sopenharmony_ci  // Sd = D:Vd; Sm=M:Vm; Sn=N:Vm.
33871cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-882.
33881cb0ef41Sopenharmony_ci  // cond(31-28) | 11101(27-23)| D(22) | 00(21-20) | Vn(19-16) |
33891cb0ef41Sopenharmony_ci  // Vd(15-12) | 101(11-9) | sz=0(8) | N(7) | 0(6) | M(5) | 0(4) | Vm(3-0)
33901cb0ef41Sopenharmony_ci  int vd, d;
33911cb0ef41Sopenharmony_ci  dst.split_code(&vd, &d);
33921cb0ef41Sopenharmony_ci  int vn, n;
33931cb0ef41Sopenharmony_ci  src1.split_code(&vn, &n);
33941cb0ef41Sopenharmony_ci  int vm, m;
33951cb0ef41Sopenharmony_ci  src2.split_code(&vm, &m);
33961cb0ef41Sopenharmony_ci  emit(cond | 0x1D * B23 | d * B22 | vn * B16 | vd * B12 | 0x5 * B9 | n * B7 |
33971cb0ef41Sopenharmony_ci       m * B5 | vm);
33981cb0ef41Sopenharmony_ci}
33991cb0ef41Sopenharmony_ci
34001cb0ef41Sopenharmony_civoid Assembler::vcmp(const DwVfpRegister src1, const DwVfpRegister src2,
34011cb0ef41Sopenharmony_ci                     const Condition cond) {
34021cb0ef41Sopenharmony_ci  // vcmp(Dd, Dm) double precision floating point comparison.
34031cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-864.
34041cb0ef41Sopenharmony_ci  // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 0100(19-16) |
34051cb0ef41Sopenharmony_ci  // Vd(15-12) | 101(11-9) | sz=1(8) | E=0(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
34061cb0ef41Sopenharmony_ci  DCHECK(VfpRegisterIsAvailable(src1));
34071cb0ef41Sopenharmony_ci  DCHECK(VfpRegisterIsAvailable(src2));
34081cb0ef41Sopenharmony_ci  int vd, d;
34091cb0ef41Sopenharmony_ci  src1.split_code(&vd, &d);
34101cb0ef41Sopenharmony_ci  int vm, m;
34111cb0ef41Sopenharmony_ci  src2.split_code(&vm, &m);
34121cb0ef41Sopenharmony_ci  emit(cond | 0x1D * B23 | d * B22 | 0x3 * B20 | 0x4 * B16 | vd * B12 |
34131cb0ef41Sopenharmony_ci       0x5 * B9 | B8 | B6 | m * B5 | vm);
34141cb0ef41Sopenharmony_ci}
34151cb0ef41Sopenharmony_ci
34161cb0ef41Sopenharmony_civoid Assembler::vcmp(const SwVfpRegister src1, const SwVfpRegister src2,
34171cb0ef41Sopenharmony_ci                     const Condition cond) {
34181cb0ef41Sopenharmony_ci  // vcmp(Sd, Sm) single precision floating point comparison.
34191cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-864.
34201cb0ef41Sopenharmony_ci  // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 0100(19-16) |
34211cb0ef41Sopenharmony_ci  // Vd(15-12) | 101(11-9) | sz=0(8) | E=0(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
34221cb0ef41Sopenharmony_ci  int vd, d;
34231cb0ef41Sopenharmony_ci  src1.split_code(&vd, &d);
34241cb0ef41Sopenharmony_ci  int vm, m;
34251cb0ef41Sopenharmony_ci  src2.split_code(&vm, &m);
34261cb0ef41Sopenharmony_ci  emit(cond | 0x1D * B23 | d * B22 | 0x3 * B20 | 0x4 * B16 | vd * B12 |
34271cb0ef41Sopenharmony_ci       0x5 * B9 | B6 | m * B5 | vm);
34281cb0ef41Sopenharmony_ci}
34291cb0ef41Sopenharmony_ci
34301cb0ef41Sopenharmony_civoid Assembler::vcmp(const DwVfpRegister src1, const double src2,
34311cb0ef41Sopenharmony_ci                     const Condition cond) {
34321cb0ef41Sopenharmony_ci  // vcmp(Dd, #0.0) double precision floating point comparison.
34331cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-864.
34341cb0ef41Sopenharmony_ci  // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 0101(19-16) |
34351cb0ef41Sopenharmony_ci  // Vd(15-12) | 101(11-9) | sz=1(8) | E=0(7) | 1(6) | 0(5) | 0(4) | 0000(3-0)
34361cb0ef41Sopenharmony_ci  DCHECK(VfpRegisterIsAvailable(src1));
34371cb0ef41Sopenharmony_ci  DCHECK_EQ(src2, 0.0);
34381cb0ef41Sopenharmony_ci  int vd, d;
34391cb0ef41Sopenharmony_ci  src1.split_code(&vd, &d);
34401cb0ef41Sopenharmony_ci  emit(cond | 0x1D * B23 | d * B22 | 0x3 * B20 | 0x5 * B16 | vd * B12 |
34411cb0ef41Sopenharmony_ci       0x5 * B9 | B8 | B6);
34421cb0ef41Sopenharmony_ci}
34431cb0ef41Sopenharmony_ci
34441cb0ef41Sopenharmony_civoid Assembler::vcmp(const SwVfpRegister src1, const float src2,
34451cb0ef41Sopenharmony_ci                     const Condition cond) {
34461cb0ef41Sopenharmony_ci  // vcmp(Sd, #0.0) single precision floating point comparison.
34471cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-864.
34481cb0ef41Sopenharmony_ci  // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 0101(19-16) |
34491cb0ef41Sopenharmony_ci  // Vd(15-12) | 101(11-9) | sz=0(8) | E=0(7) | 1(6) | 0(5) | 0(4) | 0000(3-0)
34501cb0ef41Sopenharmony_ci  DCHECK_EQ(src2, 0.0);
34511cb0ef41Sopenharmony_ci  int vd, d;
34521cb0ef41Sopenharmony_ci  src1.split_code(&vd, &d);
34531cb0ef41Sopenharmony_ci  emit(cond | 0x1D * B23 | d * B22 | 0x3 * B20 | 0x5 * B16 | vd * B12 |
34541cb0ef41Sopenharmony_ci       0x5 * B9 | B6);
34551cb0ef41Sopenharmony_ci}
34561cb0ef41Sopenharmony_ci
34571cb0ef41Sopenharmony_civoid Assembler::vmaxnm(const DwVfpRegister dst, const DwVfpRegister src1,
34581cb0ef41Sopenharmony_ci                       const DwVfpRegister src2) {
34591cb0ef41Sopenharmony_ci  // kSpecialCondition(31-28) | 11101(27-23) | D(22) | 00(21-20) | Vn(19-16) |
34601cb0ef41Sopenharmony_ci  // Vd(15-12) | 101(11-9) | sz=1(8) | N(7) | 0(6) | M(5) | 0(4) | Vm(3-0)
34611cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(ARMv8));
34621cb0ef41Sopenharmony_ci  int vd, d;
34631cb0ef41Sopenharmony_ci  dst.split_code(&vd, &d);
34641cb0ef41Sopenharmony_ci  int vn, n;
34651cb0ef41Sopenharmony_ci  src1.split_code(&vn, &n);
34661cb0ef41Sopenharmony_ci  int vm, m;
34671cb0ef41Sopenharmony_ci  src2.split_code(&vm, &m);
34681cb0ef41Sopenharmony_ci
34691cb0ef41Sopenharmony_ci  emit(kSpecialCondition | 0x1D * B23 | d * B22 | vn * B16 | vd * B12 |
34701cb0ef41Sopenharmony_ci       0x5 * B9 | B8 | n * B7 | m * B5 | vm);
34711cb0ef41Sopenharmony_ci}
34721cb0ef41Sopenharmony_ci
34731cb0ef41Sopenharmony_civoid Assembler::vmaxnm(const SwVfpRegister dst, const SwVfpRegister src1,
34741cb0ef41Sopenharmony_ci                       const SwVfpRegister src2) {
34751cb0ef41Sopenharmony_ci  // kSpecialCondition(31-28) | 11101(27-23) | D(22) | 00(21-20) | Vn(19-16) |
34761cb0ef41Sopenharmony_ci  // Vd(15-12) | 101(11-9) | sz=0(8) | N(7) | 0(6) | M(5) | 0(4) | Vm(3-0)
34771cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(ARMv8));
34781cb0ef41Sopenharmony_ci  int vd, d;
34791cb0ef41Sopenharmony_ci  dst.split_code(&vd, &d);
34801cb0ef41Sopenharmony_ci  int vn, n;
34811cb0ef41Sopenharmony_ci  src1.split_code(&vn, &n);
34821cb0ef41Sopenharmony_ci  int vm, m;
34831cb0ef41Sopenharmony_ci  src2.split_code(&vm, &m);
34841cb0ef41Sopenharmony_ci
34851cb0ef41Sopenharmony_ci  emit(kSpecialCondition | 0x1D * B23 | d * B22 | vn * B16 | vd * B12 |
34861cb0ef41Sopenharmony_ci       0x5 * B9 | n * B7 | m * B5 | vm);
34871cb0ef41Sopenharmony_ci}
34881cb0ef41Sopenharmony_ci
34891cb0ef41Sopenharmony_civoid Assembler::vminnm(const DwVfpRegister dst, const DwVfpRegister src1,
34901cb0ef41Sopenharmony_ci                       const DwVfpRegister src2) {
34911cb0ef41Sopenharmony_ci  // kSpecialCondition(31-28) | 11101(27-23) | D(22) | 00(21-20) | Vn(19-16) |
34921cb0ef41Sopenharmony_ci  // Vd(15-12) | 101(11-9) | sz=1(8) | N(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
34931cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(ARMv8));
34941cb0ef41Sopenharmony_ci  int vd, d;
34951cb0ef41Sopenharmony_ci  dst.split_code(&vd, &d);
34961cb0ef41Sopenharmony_ci  int vn, n;
34971cb0ef41Sopenharmony_ci  src1.split_code(&vn, &n);
34981cb0ef41Sopenharmony_ci  int vm, m;
34991cb0ef41Sopenharmony_ci  src2.split_code(&vm, &m);
35001cb0ef41Sopenharmony_ci
35011cb0ef41Sopenharmony_ci  emit(kSpecialCondition | 0x1D * B23 | d * B22 | vn * B16 | vd * B12 |
35021cb0ef41Sopenharmony_ci       0x5 * B9 | B8 | n * B7 | B6 | m * B5 | vm);
35031cb0ef41Sopenharmony_ci}
35041cb0ef41Sopenharmony_ci
35051cb0ef41Sopenharmony_civoid Assembler::vminnm(const SwVfpRegister dst, const SwVfpRegister src1,
35061cb0ef41Sopenharmony_ci                       const SwVfpRegister src2) {
35071cb0ef41Sopenharmony_ci  // kSpecialCondition(31-28) | 11101(27-23) | D(22) | 00(21-20) | Vn(19-16) |
35081cb0ef41Sopenharmony_ci  // Vd(15-12) | 101(11-9) | sz=0(8) | N(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
35091cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(ARMv8));
35101cb0ef41Sopenharmony_ci  int vd, d;
35111cb0ef41Sopenharmony_ci  dst.split_code(&vd, &d);
35121cb0ef41Sopenharmony_ci  int vn, n;
35131cb0ef41Sopenharmony_ci  src1.split_code(&vn, &n);
35141cb0ef41Sopenharmony_ci  int vm, m;
35151cb0ef41Sopenharmony_ci  src2.split_code(&vm, &m);
35161cb0ef41Sopenharmony_ci
35171cb0ef41Sopenharmony_ci  emit(kSpecialCondition | 0x1D * B23 | d * B22 | vn * B16 | vd * B12 |
35181cb0ef41Sopenharmony_ci       0x5 * B9 | n * B7 | B6 | m * B5 | vm);
35191cb0ef41Sopenharmony_ci}
35201cb0ef41Sopenharmony_ci
35211cb0ef41Sopenharmony_civoid Assembler::vsel(Condition cond, const DwVfpRegister dst,
35221cb0ef41Sopenharmony_ci                     const DwVfpRegister src1, const DwVfpRegister src2) {
35231cb0ef41Sopenharmony_ci  // cond=kSpecialCondition(31-28) | 11100(27-23) | D(22) |
35241cb0ef41Sopenharmony_ci  // vsel_cond=XX(21-20) | Vn(19-16) | Vd(15-12) | 101(11-9) | sz=1(8) | N(7) |
35251cb0ef41Sopenharmony_ci  // 0(6) | M(5) | 0(4) | Vm(3-0)
35261cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(ARMv8));
35271cb0ef41Sopenharmony_ci  int vd, d;
35281cb0ef41Sopenharmony_ci  dst.split_code(&vd, &d);
35291cb0ef41Sopenharmony_ci  int vn, n;
35301cb0ef41Sopenharmony_ci  src1.split_code(&vn, &n);
35311cb0ef41Sopenharmony_ci  int vm, m;
35321cb0ef41Sopenharmony_ci  src2.split_code(&vm, &m);
35331cb0ef41Sopenharmony_ci  int sz = 1;
35341cb0ef41Sopenharmony_ci
35351cb0ef41Sopenharmony_ci  // VSEL has a special (restricted) condition encoding.
35361cb0ef41Sopenharmony_ci  //   eq(0b0000)... -> 0b00
35371cb0ef41Sopenharmony_ci  //   ge(0b1010)... -> 0b10
35381cb0ef41Sopenharmony_ci  //   gt(0b1100)... -> 0b11
35391cb0ef41Sopenharmony_ci  //   vs(0b0110)... -> 0b01
35401cb0ef41Sopenharmony_ci  // No other conditions are supported.
35411cb0ef41Sopenharmony_ci  int vsel_cond = (cond >> 30) & 0x3;
35421cb0ef41Sopenharmony_ci  if ((cond != eq) && (cond != ge) && (cond != gt) && (cond != vs)) {
35431cb0ef41Sopenharmony_ci    // We can implement some other conditions by swapping the inputs.
35441cb0ef41Sopenharmony_ci    DCHECK((cond == ne) | (cond == lt) | (cond == le) | (cond == vc));
35451cb0ef41Sopenharmony_ci    std::swap(vn, vm);
35461cb0ef41Sopenharmony_ci    std::swap(n, m);
35471cb0ef41Sopenharmony_ci  }
35481cb0ef41Sopenharmony_ci
35491cb0ef41Sopenharmony_ci  emit(kSpecialCondition | 0x1C * B23 | d * B22 | vsel_cond * B20 | vn * B16 |
35501cb0ef41Sopenharmony_ci       vd * B12 | 0x5 * B9 | sz * B8 | n * B7 | m * B5 | vm);
35511cb0ef41Sopenharmony_ci}
35521cb0ef41Sopenharmony_ci
35531cb0ef41Sopenharmony_civoid Assembler::vsel(Condition cond, const SwVfpRegister dst,
35541cb0ef41Sopenharmony_ci                     const SwVfpRegister src1, const SwVfpRegister src2) {
35551cb0ef41Sopenharmony_ci  // cond=kSpecialCondition(31-28) | 11100(27-23) | D(22) |
35561cb0ef41Sopenharmony_ci  // vsel_cond=XX(21-20) | Vn(19-16) | Vd(15-12) | 101(11-9) | sz=0(8) | N(7) |
35571cb0ef41Sopenharmony_ci  // 0(6) | M(5) | 0(4) | Vm(3-0)
35581cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(ARMv8));
35591cb0ef41Sopenharmony_ci  int vd, d;
35601cb0ef41Sopenharmony_ci  dst.split_code(&vd, &d);
35611cb0ef41Sopenharmony_ci  int vn, n;
35621cb0ef41Sopenharmony_ci  src1.split_code(&vn, &n);
35631cb0ef41Sopenharmony_ci  int vm, m;
35641cb0ef41Sopenharmony_ci  src2.split_code(&vm, &m);
35651cb0ef41Sopenharmony_ci  int sz = 0;
35661cb0ef41Sopenharmony_ci
35671cb0ef41Sopenharmony_ci  // VSEL has a special (restricted) condition encoding.
35681cb0ef41Sopenharmony_ci  //   eq(0b0000)... -> 0b00
35691cb0ef41Sopenharmony_ci  //   ge(0b1010)... -> 0b10
35701cb0ef41Sopenharmony_ci  //   gt(0b1100)... -> 0b11
35711cb0ef41Sopenharmony_ci  //   vs(0b0110)... -> 0b01
35721cb0ef41Sopenharmony_ci  // No other conditions are supported.
35731cb0ef41Sopenharmony_ci  int vsel_cond = (cond >> 30) & 0x3;
35741cb0ef41Sopenharmony_ci  if ((cond != eq) && (cond != ge) && (cond != gt) && (cond != vs)) {
35751cb0ef41Sopenharmony_ci    // We can implement some other conditions by swapping the inputs.
35761cb0ef41Sopenharmony_ci    DCHECK((cond == ne) | (cond == lt) | (cond == le) | (cond == vc));
35771cb0ef41Sopenharmony_ci    std::swap(vn, vm);
35781cb0ef41Sopenharmony_ci    std::swap(n, m);
35791cb0ef41Sopenharmony_ci  }
35801cb0ef41Sopenharmony_ci
35811cb0ef41Sopenharmony_ci  emit(kSpecialCondition | 0x1C * B23 | d * B22 | vsel_cond * B20 | vn * B16 |
35821cb0ef41Sopenharmony_ci       vd * B12 | 0x5 * B9 | sz * B8 | n * B7 | m * B5 | vm);
35831cb0ef41Sopenharmony_ci}
35841cb0ef41Sopenharmony_ci
35851cb0ef41Sopenharmony_civoid Assembler::vsqrt(const DwVfpRegister dst, const DwVfpRegister src,
35861cb0ef41Sopenharmony_ci                      const Condition cond) {
35871cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-1058.
35881cb0ef41Sopenharmony_ci  // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 0001(19-16) |
35891cb0ef41Sopenharmony_ci  // Vd(15-12) | 101(11-9) | sz=1(8) | 11(7-6) | M(5) | 0(4) | Vm(3-0)
35901cb0ef41Sopenharmony_ci  DCHECK(VfpRegisterIsAvailable(dst));
35911cb0ef41Sopenharmony_ci  DCHECK(VfpRegisterIsAvailable(src));
35921cb0ef41Sopenharmony_ci  int vd, d;
35931cb0ef41Sopenharmony_ci  dst.split_code(&vd, &d);
35941cb0ef41Sopenharmony_ci  int vm, m;
35951cb0ef41Sopenharmony_ci  src.split_code(&vm, &m);
35961cb0ef41Sopenharmony_ci  emit(cond | 0x1D * B23 | d * B22 | 0x3 * B20 | B16 | vd * B12 | 0x5 * B9 |
35971cb0ef41Sopenharmony_ci       B8 | 0x3 * B6 | m * B5 | vm);
35981cb0ef41Sopenharmony_ci}
35991cb0ef41Sopenharmony_ci
36001cb0ef41Sopenharmony_civoid Assembler::vsqrt(const SwVfpRegister dst, const SwVfpRegister src,
36011cb0ef41Sopenharmony_ci                      const Condition cond) {
36021cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-1058.
36031cb0ef41Sopenharmony_ci  // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 0001(19-16) |
36041cb0ef41Sopenharmony_ci  // Vd(15-12) | 101(11-9) | sz=0(8) | 11(7-6) | M(5) | 0(4) | Vm(3-0)
36051cb0ef41Sopenharmony_ci  int vd, d;
36061cb0ef41Sopenharmony_ci  dst.split_code(&vd, &d);
36071cb0ef41Sopenharmony_ci  int vm, m;
36081cb0ef41Sopenharmony_ci  src.split_code(&vm, &m);
36091cb0ef41Sopenharmony_ci  emit(cond | 0x1D * B23 | d * B22 | 0x3 * B20 | B16 | vd * B12 | 0x5 * B9 |
36101cb0ef41Sopenharmony_ci       0x3 * B6 | m * B5 | vm);
36111cb0ef41Sopenharmony_ci}
36121cb0ef41Sopenharmony_ci
36131cb0ef41Sopenharmony_civoid Assembler::vmsr(Register dst, Condition cond) {
36141cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406A, A8-652.
36151cb0ef41Sopenharmony_ci  // cond(31-28) | 1110 (27-24) | 1110(23-20)| 0001 (19-16) |
36161cb0ef41Sopenharmony_ci  // Rt(15-12) | 1010 (11-8) | 0(7) | 00 (6-5) | 1(4) | 0000(3-0)
36171cb0ef41Sopenharmony_ci  emit(cond | 0xE * B24 | 0xE * B20 | B16 | dst.code() * B12 | 0xA * B8 | B4);
36181cb0ef41Sopenharmony_ci}
36191cb0ef41Sopenharmony_ci
36201cb0ef41Sopenharmony_civoid Assembler::vmrs(Register dst, Condition cond) {
36211cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406A, A8-652.
36221cb0ef41Sopenharmony_ci  // cond(31-28) | 1110 (27-24) | 1111(23-20)| 0001 (19-16) |
36231cb0ef41Sopenharmony_ci  // Rt(15-12) | 1010 (11-8) | 0(7) | 00 (6-5) | 1(4) | 0000(3-0)
36241cb0ef41Sopenharmony_ci  emit(cond | 0xE * B24 | 0xF * B20 | B16 | dst.code() * B12 | 0xA * B8 | B4);
36251cb0ef41Sopenharmony_ci}
36261cb0ef41Sopenharmony_ci
36271cb0ef41Sopenharmony_civoid Assembler::vrinta(const SwVfpRegister dst, const SwVfpRegister src) {
36281cb0ef41Sopenharmony_ci  // cond=kSpecialCondition(31-28) | 11101(27-23)| D(22) | 11(21-20) |
36291cb0ef41Sopenharmony_ci  // 10(19-18) | RM=00(17-16) |  Vd(15-12) | 101(11-9) | sz=0(8) | 01(7-6) |
36301cb0ef41Sopenharmony_ci  // M(5) | 0(4) | Vm(3-0)
36311cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(ARMv8));
36321cb0ef41Sopenharmony_ci  int vd, d;
36331cb0ef41Sopenharmony_ci  dst.split_code(&vd, &d);
36341cb0ef41Sopenharmony_ci  int vm, m;
36351cb0ef41Sopenharmony_ci  src.split_code(&vm, &m);
36361cb0ef41Sopenharmony_ci  emit(kSpecialCondition | 0x1D * B23 | d * B22 | 0x3 * B20 | B19 | vd * B12 |
36371cb0ef41Sopenharmony_ci       0x5 * B9 | B6 | m * B5 | vm);
36381cb0ef41Sopenharmony_ci}
36391cb0ef41Sopenharmony_ci
36401cb0ef41Sopenharmony_civoid Assembler::vrinta(const DwVfpRegister dst, const DwVfpRegister src) {
36411cb0ef41Sopenharmony_ci  // cond=kSpecialCondition(31-28) | 11101(27-23)| D(22) | 11(21-20) |
36421cb0ef41Sopenharmony_ci  // 10(19-18) | RM=00(17-16) |  Vd(15-12) | 101(11-9) | sz=1(8) | 01(7-6) |
36431cb0ef41Sopenharmony_ci  // M(5) | 0(4) | Vm(3-0)
36441cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(ARMv8));
36451cb0ef41Sopenharmony_ci  int vd, d;
36461cb0ef41Sopenharmony_ci  dst.split_code(&vd, &d);
36471cb0ef41Sopenharmony_ci  int vm, m;
36481cb0ef41Sopenharmony_ci  src.split_code(&vm, &m);
36491cb0ef41Sopenharmony_ci  emit(kSpecialCondition | 0x1D * B23 | d * B22 | 0x3 * B20 | B19 | vd * B12 |
36501cb0ef41Sopenharmony_ci       0x5 * B9 | B8 | B6 | m * B5 | vm);
36511cb0ef41Sopenharmony_ci}
36521cb0ef41Sopenharmony_ci
36531cb0ef41Sopenharmony_civoid Assembler::vrintn(const SwVfpRegister dst, const SwVfpRegister src) {
36541cb0ef41Sopenharmony_ci  // cond=kSpecialCondition(31-28) | 11101(27-23)| D(22) | 11(21-20) |
36551cb0ef41Sopenharmony_ci  // 10(19-18) | RM=01(17-16) |  Vd(15-12) | 101(11-9) | sz=0(8) | 01(7-6) |
36561cb0ef41Sopenharmony_ci  // M(5) | 0(4) | Vm(3-0)
36571cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(ARMv8));
36581cb0ef41Sopenharmony_ci  int vd, d;
36591cb0ef41Sopenharmony_ci  dst.split_code(&vd, &d);
36601cb0ef41Sopenharmony_ci  int vm, m;
36611cb0ef41Sopenharmony_ci  src.split_code(&vm, &m);
36621cb0ef41Sopenharmony_ci  emit(kSpecialCondition | 0x1D * B23 | d * B22 | 0x3 * B20 | B19 | 0x1 * B16 |
36631cb0ef41Sopenharmony_ci       vd * B12 | 0x5 * B9 | B6 | m * B5 | vm);
36641cb0ef41Sopenharmony_ci}
36651cb0ef41Sopenharmony_ci
36661cb0ef41Sopenharmony_civoid Assembler::vrintn(const DwVfpRegister dst, const DwVfpRegister src) {
36671cb0ef41Sopenharmony_ci  // cond=kSpecialCondition(31-28) | 11101(27-23)| D(22) | 11(21-20) |
36681cb0ef41Sopenharmony_ci  // 10(19-18) | RM=01(17-16) |  Vd(15-12) | 101(11-9) | sz=1(8) | 01(7-6) |
36691cb0ef41Sopenharmony_ci  // M(5) | 0(4) | Vm(3-0)
36701cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(ARMv8));
36711cb0ef41Sopenharmony_ci  int vd, d;
36721cb0ef41Sopenharmony_ci  dst.split_code(&vd, &d);
36731cb0ef41Sopenharmony_ci  int vm, m;
36741cb0ef41Sopenharmony_ci  src.split_code(&vm, &m);
36751cb0ef41Sopenharmony_ci  emit(kSpecialCondition | 0x1D * B23 | d * B22 | 0x3 * B20 | B19 | 0x1 * B16 |
36761cb0ef41Sopenharmony_ci       vd * B12 | 0x5 * B9 | B8 | B6 | m * B5 | vm);
36771cb0ef41Sopenharmony_ci}
36781cb0ef41Sopenharmony_ci
36791cb0ef41Sopenharmony_civoid Assembler::vrintp(const SwVfpRegister dst, const SwVfpRegister src) {
36801cb0ef41Sopenharmony_ci  // cond=kSpecialCondition(31-28) | 11101(27-23)| D(22) | 11(21-20) |
36811cb0ef41Sopenharmony_ci  // 10(19-18) | RM=10(17-16) |  Vd(15-12) | 101(11-9) | sz=0(8) | 01(7-6) |
36821cb0ef41Sopenharmony_ci  // M(5) | 0(4) | Vm(3-0)
36831cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(ARMv8));
36841cb0ef41Sopenharmony_ci  int vd, d;
36851cb0ef41Sopenharmony_ci  dst.split_code(&vd, &d);
36861cb0ef41Sopenharmony_ci  int vm, m;
36871cb0ef41Sopenharmony_ci  src.split_code(&vm, &m);
36881cb0ef41Sopenharmony_ci  emit(kSpecialCondition | 0x1D * B23 | d * B22 | 0x3 * B20 | B19 | 0x2 * B16 |
36891cb0ef41Sopenharmony_ci       vd * B12 | 0x5 * B9 | B6 | m * B5 | vm);
36901cb0ef41Sopenharmony_ci}
36911cb0ef41Sopenharmony_ci
36921cb0ef41Sopenharmony_civoid Assembler::vrintp(const DwVfpRegister dst, const DwVfpRegister src) {
36931cb0ef41Sopenharmony_ci  // cond=kSpecialCondition(31-28) | 11101(27-23)| D(22) | 11(21-20) |
36941cb0ef41Sopenharmony_ci  // 10(19-18) | RM=10(17-16) |  Vd(15-12) | 101(11-9) | sz=1(8) | 01(7-6) |
36951cb0ef41Sopenharmony_ci  // M(5) | 0(4) | Vm(3-0)
36961cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(ARMv8));
36971cb0ef41Sopenharmony_ci  int vd, d;
36981cb0ef41Sopenharmony_ci  dst.split_code(&vd, &d);
36991cb0ef41Sopenharmony_ci  int vm, m;
37001cb0ef41Sopenharmony_ci  src.split_code(&vm, &m);
37011cb0ef41Sopenharmony_ci  emit(kSpecialCondition | 0x1D * B23 | d * B22 | 0x3 * B20 | B19 | 0x2 * B16 |
37021cb0ef41Sopenharmony_ci       vd * B12 | 0x5 * B9 | B8 | B6 | m * B5 | vm);
37031cb0ef41Sopenharmony_ci}
37041cb0ef41Sopenharmony_ci
37051cb0ef41Sopenharmony_civoid Assembler::vrintm(const SwVfpRegister dst, const SwVfpRegister src) {
37061cb0ef41Sopenharmony_ci  // cond=kSpecialCondition(31-28) | 11101(27-23)| D(22) | 11(21-20) |
37071cb0ef41Sopenharmony_ci  // 10(19-18) | RM=11(17-16) |  Vd(15-12) | 101(11-9) | sz=0(8) | 01(7-6) |
37081cb0ef41Sopenharmony_ci  // M(5) | 0(4) | Vm(3-0)
37091cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(ARMv8));
37101cb0ef41Sopenharmony_ci  int vd, d;
37111cb0ef41Sopenharmony_ci  dst.split_code(&vd, &d);
37121cb0ef41Sopenharmony_ci  int vm, m;
37131cb0ef41Sopenharmony_ci  src.split_code(&vm, &m);
37141cb0ef41Sopenharmony_ci  emit(kSpecialCondition | 0x1D * B23 | d * B22 | 0x3 * B20 | B19 | 0x3 * B16 |
37151cb0ef41Sopenharmony_ci       vd * B12 | 0x5 * B9 | B6 | m * B5 | vm);
37161cb0ef41Sopenharmony_ci}
37171cb0ef41Sopenharmony_ci
37181cb0ef41Sopenharmony_civoid Assembler::vrintm(const DwVfpRegister dst, const DwVfpRegister src) {
37191cb0ef41Sopenharmony_ci  // cond=kSpecialCondition(31-28) | 11101(27-23)| D(22) | 11(21-20) |
37201cb0ef41Sopenharmony_ci  // 10(19-18) | RM=11(17-16) |  Vd(15-12) | 101(11-9) | sz=1(8) | 01(7-6) |
37211cb0ef41Sopenharmony_ci  // M(5) | 0(4) | Vm(3-0)
37221cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(ARMv8));
37231cb0ef41Sopenharmony_ci  int vd, d;
37241cb0ef41Sopenharmony_ci  dst.split_code(&vd, &d);
37251cb0ef41Sopenharmony_ci  int vm, m;
37261cb0ef41Sopenharmony_ci  src.split_code(&vm, &m);
37271cb0ef41Sopenharmony_ci  emit(kSpecialCondition | 0x1D * B23 | d * B22 | 0x3 * B20 | B19 | 0x3 * B16 |
37281cb0ef41Sopenharmony_ci       vd * B12 | 0x5 * B9 | B8 | B6 | m * B5 | vm);
37291cb0ef41Sopenharmony_ci}
37301cb0ef41Sopenharmony_ci
37311cb0ef41Sopenharmony_civoid Assembler::vrintz(const SwVfpRegister dst, const SwVfpRegister src,
37321cb0ef41Sopenharmony_ci                       const Condition cond) {
37331cb0ef41Sopenharmony_ci  // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 011(19-17) | 0(16) |
37341cb0ef41Sopenharmony_ci  // Vd(15-12) | 101(11-9) | sz=0(8) | op=1(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
37351cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(ARMv8));
37361cb0ef41Sopenharmony_ci  int vd, d;
37371cb0ef41Sopenharmony_ci  dst.split_code(&vd, &d);
37381cb0ef41Sopenharmony_ci  int vm, m;
37391cb0ef41Sopenharmony_ci  src.split_code(&vm, &m);
37401cb0ef41Sopenharmony_ci  emit(cond | 0x1D * B23 | d * B22 | 0x3 * B20 | 0x3 * B17 | vd * B12 |
37411cb0ef41Sopenharmony_ci       0x5 * B9 | B7 | B6 | m * B5 | vm);
37421cb0ef41Sopenharmony_ci}
37431cb0ef41Sopenharmony_ci
37441cb0ef41Sopenharmony_civoid Assembler::vrintz(const DwVfpRegister dst, const DwVfpRegister src,
37451cb0ef41Sopenharmony_ci                       const Condition cond) {
37461cb0ef41Sopenharmony_ci  // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 011(19-17) | 0(16) |
37471cb0ef41Sopenharmony_ci  // Vd(15-12) | 101(11-9) | sz=1(8) | op=1(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
37481cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(ARMv8));
37491cb0ef41Sopenharmony_ci  int vd, d;
37501cb0ef41Sopenharmony_ci  dst.split_code(&vd, &d);
37511cb0ef41Sopenharmony_ci  int vm, m;
37521cb0ef41Sopenharmony_ci  src.split_code(&vm, &m);
37531cb0ef41Sopenharmony_ci  emit(cond | 0x1D * B23 | d * B22 | 0x3 * B20 | 0x3 * B17 | vd * B12 |
37541cb0ef41Sopenharmony_ci       0x5 * B9 | B8 | B7 | B6 | m * B5 | vm);
37551cb0ef41Sopenharmony_ci}
37561cb0ef41Sopenharmony_ci
37571cb0ef41Sopenharmony_ci// Support for NEON.
37581cb0ef41Sopenharmony_ci
37591cb0ef41Sopenharmony_civoid Assembler::vld1(NeonSize size, const NeonListOperand& dst,
37601cb0ef41Sopenharmony_ci                     const NeonMemOperand& src) {
37611cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8.8.320.
37621cb0ef41Sopenharmony_ci  // 1111(31-28) | 01000(27-23) | D(22) | 10(21-20) | Rn(19-16) |
37631cb0ef41Sopenharmony_ci  // Vd(15-12) | type(11-8) | size(7-6) | align(5-4) | Rm(3-0)
37641cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
37651cb0ef41Sopenharmony_ci  int vd, d;
37661cb0ef41Sopenharmony_ci  dst.base().split_code(&vd, &d);
37671cb0ef41Sopenharmony_ci  emit(0xFU * B28 | 4 * B24 | d * B22 | 2 * B20 | src.rn().code() * B16 |
37681cb0ef41Sopenharmony_ci       vd * B12 | dst.type() * B8 | size * B6 | src.align() * B4 |
37691cb0ef41Sopenharmony_ci       src.rm().code());
37701cb0ef41Sopenharmony_ci}
37711cb0ef41Sopenharmony_ci
37721cb0ef41Sopenharmony_ci// vld1s(ingle element to one lane).
37731cb0ef41Sopenharmony_civoid Assembler::vld1s(NeonSize size, const NeonListOperand& dst, uint8_t index,
37741cb0ef41Sopenharmony_ci                      const NeonMemOperand& src) {
37751cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8.8.322.
37761cb0ef41Sopenharmony_ci  // 1111(31-28) | 01001(27-23) | D(22) | 10(21-20) | Rn(19-16) |
37771cb0ef41Sopenharmony_ci  // Vd(15-12) | size(11-10) | index_align(7-4) | Rm(3-0)
37781cb0ef41Sopenharmony_ci  // See vld1 (single element to all lanes) if size == 0x3, implemented as
37791cb0ef41Sopenharmony_ci  // vld1r(eplicate).
37801cb0ef41Sopenharmony_ci  DCHECK_NE(size, 0x3);
37811cb0ef41Sopenharmony_ci  // Check for valid lane indices.
37821cb0ef41Sopenharmony_ci  DCHECK_GT(1 << (3 - size), index);
37831cb0ef41Sopenharmony_ci  // Specifying alignment not supported, use standard alignment.
37841cb0ef41Sopenharmony_ci  uint8_t index_align = index << (size + 1);
37851cb0ef41Sopenharmony_ci
37861cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
37871cb0ef41Sopenharmony_ci  int vd, d;
37881cb0ef41Sopenharmony_ci  dst.base().split_code(&vd, &d);
37891cb0ef41Sopenharmony_ci  emit(0xFU * B28 | 4 * B24 | 1 * B23 | d * B22 | 2 * B20 |
37901cb0ef41Sopenharmony_ci       src.rn().code() * B16 | vd * B12 | size * B10 | index_align * B4 |
37911cb0ef41Sopenharmony_ci       src.rm().code());
37921cb0ef41Sopenharmony_ci}
37931cb0ef41Sopenharmony_ci
37941cb0ef41Sopenharmony_ci// vld1r(eplicate)
37951cb0ef41Sopenharmony_civoid Assembler::vld1r(NeonSize size, const NeonListOperand& dst,
37961cb0ef41Sopenharmony_ci                      const NeonMemOperand& src) {
37971cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
37981cb0ef41Sopenharmony_ci  int vd, d;
37991cb0ef41Sopenharmony_ci  dst.base().split_code(&vd, &d);
38001cb0ef41Sopenharmony_ci  emit(0xFU * B28 | 4 * B24 | 1 * B23 | d * B22 | 2 * B20 |
38011cb0ef41Sopenharmony_ci       src.rn().code() * B16 | vd * B12 | 0xC * B8 | size * B6 |
38021cb0ef41Sopenharmony_ci       dst.length() * B5 | src.rm().code());
38031cb0ef41Sopenharmony_ci}
38041cb0ef41Sopenharmony_ci
38051cb0ef41Sopenharmony_civoid Assembler::vst1(NeonSize size, const NeonListOperand& src,
38061cb0ef41Sopenharmony_ci                     const NeonMemOperand& dst) {
38071cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8.8.404.
38081cb0ef41Sopenharmony_ci  // 1111(31-28) | 01000(27-23) | D(22) | 00(21-20) | Rn(19-16) |
38091cb0ef41Sopenharmony_ci  // Vd(15-12) | type(11-8) | size(7-6) | align(5-4) | Rm(3-0)
38101cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
38111cb0ef41Sopenharmony_ci  int vd, d;
38121cb0ef41Sopenharmony_ci  src.base().split_code(&vd, &d);
38131cb0ef41Sopenharmony_ci  emit(0xFU * B28 | 4 * B24 | d * B22 | dst.rn().code() * B16 | vd * B12 |
38141cb0ef41Sopenharmony_ci       src.type() * B8 | size * B6 | dst.align() * B4 | dst.rm().code());
38151cb0ef41Sopenharmony_ci}
38161cb0ef41Sopenharmony_ci
38171cb0ef41Sopenharmony_civoid Assembler::vst1s(NeonSize size, const NeonListOperand& src, uint8_t index,
38181cb0ef41Sopenharmony_ci                      const NeonMemOperand& dst) {
38191cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0487F.b F6.1.236.
38201cb0ef41Sopenharmony_ci  // 1111(31-28) | 01001(27-23) | D(22) | 00(21-20) | Rn(19-16) |
38211cb0ef41Sopenharmony_ci  // Vd(15-12) | size(11-10) | 00(9-8) | index_align(7-4) | Rm(3-0)
38221cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
38231cb0ef41Sopenharmony_ci  DCHECK_NE(size, 0x3);
38241cb0ef41Sopenharmony_ci  DCHECK_GT(1 << (3 - size), index);
38251cb0ef41Sopenharmony_ci  // Specifying alignment not supported, use standard alignment.
38261cb0ef41Sopenharmony_ci  uint8_t index_align = index << (size + 1);
38271cb0ef41Sopenharmony_ci  int vd, d;
38281cb0ef41Sopenharmony_ci  src.base().split_code(&vd, &d);
38291cb0ef41Sopenharmony_ci  emit(0xFU * B28 | 9 * B23 | d * B22 | dst.rn().code() * B16 | vd * B12 |
38301cb0ef41Sopenharmony_ci       size * B10 | index_align * B4 | dst.rm().code());
38311cb0ef41Sopenharmony_ci}
38321cb0ef41Sopenharmony_ci
38331cb0ef41Sopenharmony_civoid Assembler::vmovl(NeonDataType dt, QwNeonRegister dst, DwVfpRegister src) {
38341cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8.8.346.
38351cb0ef41Sopenharmony_ci  // 1111(31-28) | 001(27-25) | U(24) | 1(23) | D(22) | imm3(21-19) |
38361cb0ef41Sopenharmony_ci  // 000(18-16) | Vd(15-12) | 101000(11-6) | M(5) | 1(4) | Vm(3-0)
38371cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
38381cb0ef41Sopenharmony_ci  int vd, d;
38391cb0ef41Sopenharmony_ci  dst.split_code(&vd, &d);
38401cb0ef41Sopenharmony_ci  int vm, m;
38411cb0ef41Sopenharmony_ci  src.split_code(&vm, &m);
38421cb0ef41Sopenharmony_ci  int U = NeonU(dt);
38431cb0ef41Sopenharmony_ci  int imm3 = 1 << NeonSz(dt);
38441cb0ef41Sopenharmony_ci  emit(0xFU * B28 | B25 | U * B24 | B23 | d * B22 | imm3 * B19 | vd * B12 |
38451cb0ef41Sopenharmony_ci       0xA * B8 | m * B5 | B4 | vm);
38461cb0ef41Sopenharmony_ci}
38471cb0ef41Sopenharmony_ci
38481cb0ef41Sopenharmony_civoid Assembler::vqmovn(NeonDataType dst_dt, NeonDataType src_dt,
38491cb0ef41Sopenharmony_ci                       DwVfpRegister dst, QwNeonRegister src) {
38501cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8.8.1004.
38511cb0ef41Sopenharmony_ci  // vqmovn.<type><size> Dd, Qm. ARM vector narrowing move with saturation.
38521cb0ef41Sopenharmony_ci  // vqmovun.<type><size> Dd, Qm. Same as above, but produces unsigned results.
38531cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
38541cb0ef41Sopenharmony_ci  DCHECK_IMPLIES(NeonU(src_dt), NeonU(dst_dt));
38551cb0ef41Sopenharmony_ci  int vd, d;
38561cb0ef41Sopenharmony_ci  dst.split_code(&vd, &d);
38571cb0ef41Sopenharmony_ci  int vm, m;
38581cb0ef41Sopenharmony_ci  src.split_code(&vm, &m);
38591cb0ef41Sopenharmony_ci  int size = NeonSz(dst_dt);
38601cb0ef41Sopenharmony_ci  DCHECK_NE(3, size);
38611cb0ef41Sopenharmony_ci  int op = NeonU(src_dt) ? 0b11 : NeonU(dst_dt) ? 0b01 : 0b10;
38621cb0ef41Sopenharmony_ci  emit(0x1E7U * B23 | d * B22 | 0x3 * B20 | size * B18 | 0x2 * B16 | vd * B12 |
38631cb0ef41Sopenharmony_ci       0x2 * B8 | op * B6 | m * B5 | vm);
38641cb0ef41Sopenharmony_ci}
38651cb0ef41Sopenharmony_ci
38661cb0ef41Sopenharmony_cistatic int EncodeScalar(NeonDataType dt, int index) {
38671cb0ef41Sopenharmony_ci  int opc1_opc2 = 0;
38681cb0ef41Sopenharmony_ci  DCHECK_LE(0, index);
38691cb0ef41Sopenharmony_ci  switch (dt) {
38701cb0ef41Sopenharmony_ci    case NeonS8:
38711cb0ef41Sopenharmony_ci    case NeonU8:
38721cb0ef41Sopenharmony_ci      DCHECK_GT(8, index);
38731cb0ef41Sopenharmony_ci      opc1_opc2 = 0x8 | index;
38741cb0ef41Sopenharmony_ci      break;
38751cb0ef41Sopenharmony_ci    case NeonS16:
38761cb0ef41Sopenharmony_ci    case NeonU16:
38771cb0ef41Sopenharmony_ci      DCHECK_GT(4, index);
38781cb0ef41Sopenharmony_ci      opc1_opc2 = 0x1 | (index << 1);
38791cb0ef41Sopenharmony_ci      break;
38801cb0ef41Sopenharmony_ci    case NeonS32:
38811cb0ef41Sopenharmony_ci    case NeonU32:
38821cb0ef41Sopenharmony_ci      DCHECK_GT(2, index);
38831cb0ef41Sopenharmony_ci      opc1_opc2 = index << 2;
38841cb0ef41Sopenharmony_ci      break;
38851cb0ef41Sopenharmony_ci    default:
38861cb0ef41Sopenharmony_ci      UNREACHABLE();
38871cb0ef41Sopenharmony_ci  }
38881cb0ef41Sopenharmony_ci  return (opc1_opc2 >> 2) * B21 | (opc1_opc2 & 0x3) * B5;
38891cb0ef41Sopenharmony_ci}
38901cb0ef41Sopenharmony_ci
38911cb0ef41Sopenharmony_civoid Assembler::vmov(NeonDataType dt, DwVfpRegister dst, int index,
38921cb0ef41Sopenharmony_ci                     Register src) {
38931cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8.8.940.
38941cb0ef41Sopenharmony_ci  // vmov ARM core register to scalar.
38951cb0ef41Sopenharmony_ci  DCHECK(dt == NeonS32 || dt == NeonU32 || IsEnabled(NEON));
38961cb0ef41Sopenharmony_ci  int vd, d;
38971cb0ef41Sopenharmony_ci  dst.split_code(&vd, &d);
38981cb0ef41Sopenharmony_ci  int opc1_opc2 = EncodeScalar(dt, index);
38991cb0ef41Sopenharmony_ci  emit(0xEEu * B24 | vd * B16 | src.code() * B12 | 0xB * B8 | d * B7 | B4 |
39001cb0ef41Sopenharmony_ci       opc1_opc2);
39011cb0ef41Sopenharmony_ci}
39021cb0ef41Sopenharmony_ci
39031cb0ef41Sopenharmony_civoid Assembler::vmov(NeonDataType dt, Register dst, DwVfpRegister src,
39041cb0ef41Sopenharmony_ci                     int index) {
39051cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8.8.942.
39061cb0ef41Sopenharmony_ci  // vmov Arm scalar to core register.
39071cb0ef41Sopenharmony_ci  DCHECK(dt == NeonS32 || dt == NeonU32 || IsEnabled(NEON));
39081cb0ef41Sopenharmony_ci  int vn, n;
39091cb0ef41Sopenharmony_ci  src.split_code(&vn, &n);
39101cb0ef41Sopenharmony_ci  int opc1_opc2 = EncodeScalar(dt, index);
39111cb0ef41Sopenharmony_ci  // NeonS32 and NeonU32 both encoded as u = 0.
39121cb0ef41Sopenharmony_ci  int u = NeonDataTypeToSize(dt) == Neon32 ? 0 : NeonU(dt);
39131cb0ef41Sopenharmony_ci  emit(0xEEu * B24 | u * B23 | B20 | vn * B16 | dst.code() * B12 | 0xB * B8 |
39141cb0ef41Sopenharmony_ci       n * B7 | B4 | opc1_opc2);
39151cb0ef41Sopenharmony_ci}
39161cb0ef41Sopenharmony_ci
39171cb0ef41Sopenharmony_civoid Assembler::vmov(QwNeonRegister dst, QwNeonRegister src) {
39181cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-938.
39191cb0ef41Sopenharmony_ci  // vmov is encoded as vorr.
39201cb0ef41Sopenharmony_ci  vorr(dst, src, src);
39211cb0ef41Sopenharmony_ci}
39221cb0ef41Sopenharmony_ci
39231cb0ef41Sopenharmony_civoid Assembler::vdup(NeonSize size, QwNeonRegister dst, Register src) {
39241cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
39251cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-886.
39261cb0ef41Sopenharmony_ci  int B = 0, E = 0;
39271cb0ef41Sopenharmony_ci  switch (size) {
39281cb0ef41Sopenharmony_ci    case Neon8:
39291cb0ef41Sopenharmony_ci      B = 1;
39301cb0ef41Sopenharmony_ci      break;
39311cb0ef41Sopenharmony_ci    case Neon16:
39321cb0ef41Sopenharmony_ci      E = 1;
39331cb0ef41Sopenharmony_ci      break;
39341cb0ef41Sopenharmony_ci    case Neon32:
39351cb0ef41Sopenharmony_ci      break;
39361cb0ef41Sopenharmony_ci    default:
39371cb0ef41Sopenharmony_ci      UNREACHABLE();
39381cb0ef41Sopenharmony_ci  }
39391cb0ef41Sopenharmony_ci  int vd, d;
39401cb0ef41Sopenharmony_ci  dst.split_code(&vd, &d);
39411cb0ef41Sopenharmony_ci
39421cb0ef41Sopenharmony_ci  emit(al | 0x1D * B23 | B * B22 | B21 | vd * B16 | src.code() * B12 |
39431cb0ef41Sopenharmony_ci       0xB * B8 | d * B7 | E * B5 | B4);
39441cb0ef41Sopenharmony_ci}
39451cb0ef41Sopenharmony_ci
39461cb0ef41Sopenharmony_cienum NeonRegType { NEON_D, NEON_Q };
39471cb0ef41Sopenharmony_ci
39481cb0ef41Sopenharmony_civoid NeonSplitCode(NeonRegType type, int code, int* vm, int* m, int* encoding) {
39491cb0ef41Sopenharmony_ci  if (type == NEON_D) {
39501cb0ef41Sopenharmony_ci    DwVfpRegister::split_code(code, vm, m);
39511cb0ef41Sopenharmony_ci  } else {
39521cb0ef41Sopenharmony_ci    DCHECK_EQ(type, NEON_Q);
39531cb0ef41Sopenharmony_ci    QwNeonRegister::split_code(code, vm, m);
39541cb0ef41Sopenharmony_ci    *encoding |= B6;
39551cb0ef41Sopenharmony_ci  }
39561cb0ef41Sopenharmony_ci}
39571cb0ef41Sopenharmony_ci
39581cb0ef41Sopenharmony_cistatic Instr EncodeNeonDupOp(NeonSize size, NeonRegType reg_type, int dst_code,
39591cb0ef41Sopenharmony_ci                             DwVfpRegister src, int index) {
39601cb0ef41Sopenharmony_ci  DCHECK_NE(Neon64, size);
39611cb0ef41Sopenharmony_ci  int sz = static_cast<int>(size);
39621cb0ef41Sopenharmony_ci  DCHECK_LE(0, index);
39631cb0ef41Sopenharmony_ci  DCHECK_GT(kSimd128Size / (1 << sz), index);
39641cb0ef41Sopenharmony_ci  int imm4 = (1 << sz) | ((index << (sz + 1)) & 0xF);
39651cb0ef41Sopenharmony_ci  int qbit = 0;
39661cb0ef41Sopenharmony_ci  int vd, d;
39671cb0ef41Sopenharmony_ci  NeonSplitCode(reg_type, dst_code, &vd, &d, &qbit);
39681cb0ef41Sopenharmony_ci  int vm, m;
39691cb0ef41Sopenharmony_ci  src.split_code(&vm, &m);
39701cb0ef41Sopenharmony_ci
39711cb0ef41Sopenharmony_ci  return 0x1E7U * B23 | d * B22 | 0x3 * B20 | imm4 * B16 | vd * B12 |
39721cb0ef41Sopenharmony_ci         0x18 * B7 | qbit | m * B5 | vm;
39731cb0ef41Sopenharmony_ci}
39741cb0ef41Sopenharmony_ci
39751cb0ef41Sopenharmony_civoid Assembler::vdup(NeonSize size, DwVfpRegister dst, DwVfpRegister src,
39761cb0ef41Sopenharmony_ci                     int index) {
39771cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
39781cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-884.
39791cb0ef41Sopenharmony_ci  emit(EncodeNeonDupOp(size, NEON_D, dst.code(), src, index));
39801cb0ef41Sopenharmony_ci}
39811cb0ef41Sopenharmony_ci
39821cb0ef41Sopenharmony_civoid Assembler::vdup(NeonSize size, QwNeonRegister dst, DwVfpRegister src,
39831cb0ef41Sopenharmony_ci                     int index) {
39841cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-884.
39851cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
39861cb0ef41Sopenharmony_ci  emit(EncodeNeonDupOp(size, NEON_Q, dst.code(), src, index));
39871cb0ef41Sopenharmony_ci}
39881cb0ef41Sopenharmony_ci
39891cb0ef41Sopenharmony_ci// Encode NEON vcvt.src_type.dst_type instruction.
39901cb0ef41Sopenharmony_cistatic Instr EncodeNeonVCVT(VFPType dst_type, QwNeonRegister dst,
39911cb0ef41Sopenharmony_ci                            VFPType src_type, QwNeonRegister src) {
39921cb0ef41Sopenharmony_ci  DCHECK(src_type != dst_type);
39931cb0ef41Sopenharmony_ci  DCHECK(src_type == F32 || dst_type == F32);
39941cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8.8.868.
39951cb0ef41Sopenharmony_ci  int vd, d;
39961cb0ef41Sopenharmony_ci  dst.split_code(&vd, &d);
39971cb0ef41Sopenharmony_ci  int vm, m;
39981cb0ef41Sopenharmony_ci  src.split_code(&vm, &m);
39991cb0ef41Sopenharmony_ci
40001cb0ef41Sopenharmony_ci  int op = 0;
40011cb0ef41Sopenharmony_ci  if (src_type == F32) {
40021cb0ef41Sopenharmony_ci    DCHECK(dst_type == S32 || dst_type == U32);
40031cb0ef41Sopenharmony_ci    op = dst_type == U32 ? 3 : 2;
40041cb0ef41Sopenharmony_ci  } else {
40051cb0ef41Sopenharmony_ci    DCHECK(src_type == S32 || src_type == U32);
40061cb0ef41Sopenharmony_ci    op = src_type == U32 ? 1 : 0;
40071cb0ef41Sopenharmony_ci  }
40081cb0ef41Sopenharmony_ci
40091cb0ef41Sopenharmony_ci  return 0x1E7U * B23 | d * B22 | 0x3B * B16 | vd * B12 | 0x3 * B9 | op * B7 |
40101cb0ef41Sopenharmony_ci         B6 | m * B5 | vm;
40111cb0ef41Sopenharmony_ci}
40121cb0ef41Sopenharmony_ci
40131cb0ef41Sopenharmony_civoid Assembler::vcvt_f32_s32(QwNeonRegister dst, QwNeonRegister src) {
40141cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
40151cb0ef41Sopenharmony_ci  DCHECK(VfpRegisterIsAvailable(dst));
40161cb0ef41Sopenharmony_ci  DCHECK(VfpRegisterIsAvailable(src));
40171cb0ef41Sopenharmony_ci  emit(EncodeNeonVCVT(F32, dst, S32, src));
40181cb0ef41Sopenharmony_ci}
40191cb0ef41Sopenharmony_ci
40201cb0ef41Sopenharmony_civoid Assembler::vcvt_f32_u32(QwNeonRegister dst, QwNeonRegister src) {
40211cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
40221cb0ef41Sopenharmony_ci  DCHECK(VfpRegisterIsAvailable(dst));
40231cb0ef41Sopenharmony_ci  DCHECK(VfpRegisterIsAvailable(src));
40241cb0ef41Sopenharmony_ci  emit(EncodeNeonVCVT(F32, dst, U32, src));
40251cb0ef41Sopenharmony_ci}
40261cb0ef41Sopenharmony_ci
40271cb0ef41Sopenharmony_civoid Assembler::vcvt_s32_f32(QwNeonRegister dst, QwNeonRegister src) {
40281cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
40291cb0ef41Sopenharmony_ci  DCHECK(VfpRegisterIsAvailable(dst));
40301cb0ef41Sopenharmony_ci  DCHECK(VfpRegisterIsAvailable(src));
40311cb0ef41Sopenharmony_ci  emit(EncodeNeonVCVT(S32, dst, F32, src));
40321cb0ef41Sopenharmony_ci}
40331cb0ef41Sopenharmony_ci
40341cb0ef41Sopenharmony_civoid Assembler::vcvt_u32_f32(QwNeonRegister dst, QwNeonRegister src) {
40351cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
40361cb0ef41Sopenharmony_ci  DCHECK(VfpRegisterIsAvailable(dst));
40371cb0ef41Sopenharmony_ci  DCHECK(VfpRegisterIsAvailable(src));
40381cb0ef41Sopenharmony_ci  emit(EncodeNeonVCVT(U32, dst, F32, src));
40391cb0ef41Sopenharmony_ci}
40401cb0ef41Sopenharmony_ci
40411cb0ef41Sopenharmony_cienum UnaryOp {
40421cb0ef41Sopenharmony_ci  VMVN,
40431cb0ef41Sopenharmony_ci  VSWP,
40441cb0ef41Sopenharmony_ci  VABS,
40451cb0ef41Sopenharmony_ci  VABSF,
40461cb0ef41Sopenharmony_ci  VNEG,
40471cb0ef41Sopenharmony_ci  VNEGF,
40481cb0ef41Sopenharmony_ci  VRINTM,
40491cb0ef41Sopenharmony_ci  VRINTN,
40501cb0ef41Sopenharmony_ci  VRINTP,
40511cb0ef41Sopenharmony_ci  VRINTZ,
40521cb0ef41Sopenharmony_ci  VZIP,
40531cb0ef41Sopenharmony_ci  VUZP,
40541cb0ef41Sopenharmony_ci  VREV16,
40551cb0ef41Sopenharmony_ci  VREV32,
40561cb0ef41Sopenharmony_ci  VREV64,
40571cb0ef41Sopenharmony_ci  VTRN,
40581cb0ef41Sopenharmony_ci  VRECPE,
40591cb0ef41Sopenharmony_ci  VRSQRTE,
40601cb0ef41Sopenharmony_ci  VPADAL_S,
40611cb0ef41Sopenharmony_ci  VPADAL_U,
40621cb0ef41Sopenharmony_ci  VPADDL_S,
40631cb0ef41Sopenharmony_ci  VPADDL_U,
40641cb0ef41Sopenharmony_ci  VCEQ0,
40651cb0ef41Sopenharmony_ci  VCLT0,
40661cb0ef41Sopenharmony_ci  VCNT
40671cb0ef41Sopenharmony_ci};
40681cb0ef41Sopenharmony_ci
40691cb0ef41Sopenharmony_ci// Encoding helper for "Advanced SIMD two registers misc" decode group. See ARM
40701cb0ef41Sopenharmony_ci// DDI 0487F.b, F4-4228.
40711cb0ef41Sopenharmony_cistatic Instr EncodeNeonUnaryOp(UnaryOp op, NeonRegType reg_type, NeonSize size,
40721cb0ef41Sopenharmony_ci                               int dst_code, int src_code) {
40731cb0ef41Sopenharmony_ci  int op_encoding = 0;
40741cb0ef41Sopenharmony_ci  switch (op) {
40751cb0ef41Sopenharmony_ci    case VMVN:
40761cb0ef41Sopenharmony_ci      DCHECK_EQ(Neon8, size);  // size == 0 for vmvn
40771cb0ef41Sopenharmony_ci      op_encoding = B10 | 0x3 * B7;
40781cb0ef41Sopenharmony_ci      break;
40791cb0ef41Sopenharmony_ci    case VSWP:
40801cb0ef41Sopenharmony_ci      DCHECK_EQ(Neon8, size);  // size == 0 for vswp
40811cb0ef41Sopenharmony_ci      op_encoding = B17;
40821cb0ef41Sopenharmony_ci      break;
40831cb0ef41Sopenharmony_ci    case VABS:
40841cb0ef41Sopenharmony_ci      op_encoding = B16 | 0x6 * B7;
40851cb0ef41Sopenharmony_ci      break;
40861cb0ef41Sopenharmony_ci    case VABSF:
40871cb0ef41Sopenharmony_ci      DCHECK_EQ(Neon32, size);
40881cb0ef41Sopenharmony_ci      op_encoding = B16 | B10 | 0x6 * B7;
40891cb0ef41Sopenharmony_ci      break;
40901cb0ef41Sopenharmony_ci    case VNEG:
40911cb0ef41Sopenharmony_ci      op_encoding = B16 | 0x7 * B7;
40921cb0ef41Sopenharmony_ci      break;
40931cb0ef41Sopenharmony_ci    case VNEGF:
40941cb0ef41Sopenharmony_ci      DCHECK_EQ(Neon32, size);
40951cb0ef41Sopenharmony_ci      op_encoding = B16 | B10 | 0x7 * B7;
40961cb0ef41Sopenharmony_ci      break;
40971cb0ef41Sopenharmony_ci    case VRINTM:
40981cb0ef41Sopenharmony_ci      op_encoding = B17 | 0xD * B7;
40991cb0ef41Sopenharmony_ci      break;
41001cb0ef41Sopenharmony_ci    case VRINTN:
41011cb0ef41Sopenharmony_ci      op_encoding = B17 | 0x8 * B7;
41021cb0ef41Sopenharmony_ci      break;
41031cb0ef41Sopenharmony_ci    case VRINTP:
41041cb0ef41Sopenharmony_ci      op_encoding = B17 | 0xF * B7;
41051cb0ef41Sopenharmony_ci      break;
41061cb0ef41Sopenharmony_ci    case VRINTZ:
41071cb0ef41Sopenharmony_ci      op_encoding = B17 | 0xB * B7;
41081cb0ef41Sopenharmony_ci      break;
41091cb0ef41Sopenharmony_ci    case VZIP:
41101cb0ef41Sopenharmony_ci      op_encoding = 0x2 * B16 | 0x3 * B7;
41111cb0ef41Sopenharmony_ci      break;
41121cb0ef41Sopenharmony_ci    case VUZP:
41131cb0ef41Sopenharmony_ci      op_encoding = 0x2 * B16 | 0x2 * B7;
41141cb0ef41Sopenharmony_ci      break;
41151cb0ef41Sopenharmony_ci    case VREV16:
41161cb0ef41Sopenharmony_ci      op_encoding = 0x2 * B7;
41171cb0ef41Sopenharmony_ci      break;
41181cb0ef41Sopenharmony_ci    case VREV32:
41191cb0ef41Sopenharmony_ci      op_encoding = 0x1 * B7;
41201cb0ef41Sopenharmony_ci      break;
41211cb0ef41Sopenharmony_ci    case VREV64:
41221cb0ef41Sopenharmony_ci      // op_encoding is 0;
41231cb0ef41Sopenharmony_ci      break;
41241cb0ef41Sopenharmony_ci    case VTRN:
41251cb0ef41Sopenharmony_ci      op_encoding = 0x2 * B16 | B7;
41261cb0ef41Sopenharmony_ci      break;
41271cb0ef41Sopenharmony_ci    case VRECPE:
41281cb0ef41Sopenharmony_ci      // Only support floating point.
41291cb0ef41Sopenharmony_ci      op_encoding = 0x3 * B16 | 0xA * B7;
41301cb0ef41Sopenharmony_ci      break;
41311cb0ef41Sopenharmony_ci    case VRSQRTE:
41321cb0ef41Sopenharmony_ci      // Only support floating point.
41331cb0ef41Sopenharmony_ci      op_encoding = 0x3 * B16 | 0xB * B7;
41341cb0ef41Sopenharmony_ci      break;
41351cb0ef41Sopenharmony_ci    case VPADAL_S:
41361cb0ef41Sopenharmony_ci      op_encoding = 0xC * B7;
41371cb0ef41Sopenharmony_ci      break;
41381cb0ef41Sopenharmony_ci    case VPADAL_U:
41391cb0ef41Sopenharmony_ci      op_encoding = 0xD * B7;
41401cb0ef41Sopenharmony_ci      break;
41411cb0ef41Sopenharmony_ci    case VPADDL_S:
41421cb0ef41Sopenharmony_ci      op_encoding = 0x4 * B7;
41431cb0ef41Sopenharmony_ci      break;
41441cb0ef41Sopenharmony_ci    case VPADDL_U:
41451cb0ef41Sopenharmony_ci      op_encoding = 0x5 * B7;
41461cb0ef41Sopenharmony_ci      break;
41471cb0ef41Sopenharmony_ci    case VCEQ0:
41481cb0ef41Sopenharmony_ci      // Only support integers.
41491cb0ef41Sopenharmony_ci      op_encoding = 0x1 * B16 | 0x2 * B7;
41501cb0ef41Sopenharmony_ci      break;
41511cb0ef41Sopenharmony_ci    case VCLT0:
41521cb0ef41Sopenharmony_ci      // Only support signed integers.
41531cb0ef41Sopenharmony_ci      op_encoding = 0x1 * B16 | 0x4 * B7;
41541cb0ef41Sopenharmony_ci      break;
41551cb0ef41Sopenharmony_ci    case VCNT:
41561cb0ef41Sopenharmony_ci      op_encoding = 0xA * B7;
41571cb0ef41Sopenharmony_ci      break;
41581cb0ef41Sopenharmony_ci  }
41591cb0ef41Sopenharmony_ci  int vd, d;
41601cb0ef41Sopenharmony_ci  NeonSplitCode(reg_type, dst_code, &vd, &d, &op_encoding);
41611cb0ef41Sopenharmony_ci  int vm, m;
41621cb0ef41Sopenharmony_ci  NeonSplitCode(reg_type, src_code, &vm, &m, &op_encoding);
41631cb0ef41Sopenharmony_ci
41641cb0ef41Sopenharmony_ci  return 0x1E7U * B23 | d * B22 | 0x3 * B20 | size * B18 | vd * B12 | m * B5 |
41651cb0ef41Sopenharmony_ci         vm | op_encoding;
41661cb0ef41Sopenharmony_ci}
41671cb0ef41Sopenharmony_ci
41681cb0ef41Sopenharmony_civoid Assembler::vmvn(QwNeonRegister dst, QwNeonRegister src) {
41691cb0ef41Sopenharmony_ci  // Qd = vmvn(Qn, Qm) SIMD bitwise negate.
41701cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-966.
41711cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
41721cb0ef41Sopenharmony_ci  emit(EncodeNeonUnaryOp(VMVN, NEON_Q, Neon8, dst.code(), src.code()));
41731cb0ef41Sopenharmony_ci}
41741cb0ef41Sopenharmony_ci
41751cb0ef41Sopenharmony_civoid Assembler::vswp(DwVfpRegister dst, DwVfpRegister src) {
41761cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
41771cb0ef41Sopenharmony_ci  // Dd = vswp(Dn, Dm) SIMD d-register swap.
41781cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8.8.418.
41791cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
41801cb0ef41Sopenharmony_ci  emit(EncodeNeonUnaryOp(VSWP, NEON_D, Neon8, dst.code(), src.code()));
41811cb0ef41Sopenharmony_ci}
41821cb0ef41Sopenharmony_ci
41831cb0ef41Sopenharmony_civoid Assembler::vswp(QwNeonRegister dst, QwNeonRegister src) {
41841cb0ef41Sopenharmony_ci  // Qd = vswp(Qn, Qm) SIMD q-register swap.
41851cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8.8.418.
41861cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
41871cb0ef41Sopenharmony_ci  emit(EncodeNeonUnaryOp(VSWP, NEON_Q, Neon8, dst.code(), src.code()));
41881cb0ef41Sopenharmony_ci}
41891cb0ef41Sopenharmony_ci
41901cb0ef41Sopenharmony_civoid Assembler::vabs(QwNeonRegister dst, QwNeonRegister src) {
41911cb0ef41Sopenharmony_ci  // Qd = vabs.f<size>(Qn, Qm) SIMD floating point absolute value.
41921cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8.8.824.
41931cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
41941cb0ef41Sopenharmony_ci  emit(EncodeNeonUnaryOp(VABSF, NEON_Q, Neon32, dst.code(), src.code()));
41951cb0ef41Sopenharmony_ci}
41961cb0ef41Sopenharmony_ci
41971cb0ef41Sopenharmony_civoid Assembler::vabs(NeonSize size, QwNeonRegister dst, QwNeonRegister src) {
41981cb0ef41Sopenharmony_ci  // Qd = vabs.s<size>(Qn, Qm) SIMD integer absolute value.
41991cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8.8.824.
42001cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
42011cb0ef41Sopenharmony_ci  emit(EncodeNeonUnaryOp(VABS, NEON_Q, size, dst.code(), src.code()));
42021cb0ef41Sopenharmony_ci}
42031cb0ef41Sopenharmony_ci
42041cb0ef41Sopenharmony_civoid Assembler::vneg(QwNeonRegister dst, QwNeonRegister src) {
42051cb0ef41Sopenharmony_ci  // Qd = vabs.f<size>(Qn, Qm) SIMD floating point negate.
42061cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8.8.968.
42071cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
42081cb0ef41Sopenharmony_ci  emit(EncodeNeonUnaryOp(VNEGF, NEON_Q, Neon32, dst.code(), src.code()));
42091cb0ef41Sopenharmony_ci}
42101cb0ef41Sopenharmony_ci
42111cb0ef41Sopenharmony_civoid Assembler::vneg(NeonSize size, QwNeonRegister dst, QwNeonRegister src) {
42121cb0ef41Sopenharmony_ci  // Qd = vabs.s<size>(Qn, Qm) SIMD integer negate.
42131cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8.8.968.
42141cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
42151cb0ef41Sopenharmony_ci  emit(EncodeNeonUnaryOp(VNEG, NEON_Q, size, dst.code(), src.code()));
42161cb0ef41Sopenharmony_ci}
42171cb0ef41Sopenharmony_ci
42181cb0ef41Sopenharmony_cienum BinaryBitwiseOp { VAND, VBIC, VBIF, VBIT, VBSL, VEOR, VORR, VORN };
42191cb0ef41Sopenharmony_ci
42201cb0ef41Sopenharmony_cistatic Instr EncodeNeonBinaryBitwiseOp(BinaryBitwiseOp op, NeonRegType reg_type,
42211cb0ef41Sopenharmony_ci                                       int dst_code, int src_code1,
42221cb0ef41Sopenharmony_ci                                       int src_code2) {
42231cb0ef41Sopenharmony_ci  int op_encoding = 0;
42241cb0ef41Sopenharmony_ci  switch (op) {
42251cb0ef41Sopenharmony_ci    case VBIC:
42261cb0ef41Sopenharmony_ci      op_encoding = 0x1 * B20;
42271cb0ef41Sopenharmony_ci      break;
42281cb0ef41Sopenharmony_ci    case VBIF:
42291cb0ef41Sopenharmony_ci      op_encoding = B24 | 0x3 * B20;
42301cb0ef41Sopenharmony_ci      break;
42311cb0ef41Sopenharmony_ci    case VBIT:
42321cb0ef41Sopenharmony_ci      op_encoding = B24 | 0x2 * B20;
42331cb0ef41Sopenharmony_ci      break;
42341cb0ef41Sopenharmony_ci    case VBSL:
42351cb0ef41Sopenharmony_ci      op_encoding = B24 | 0x1 * B20;
42361cb0ef41Sopenharmony_ci      break;
42371cb0ef41Sopenharmony_ci    case VEOR:
42381cb0ef41Sopenharmony_ci      op_encoding = B24;
42391cb0ef41Sopenharmony_ci      break;
42401cb0ef41Sopenharmony_ci    case VORR:
42411cb0ef41Sopenharmony_ci      op_encoding = 0x2 * B20;
42421cb0ef41Sopenharmony_ci      break;
42431cb0ef41Sopenharmony_ci    case VORN:
42441cb0ef41Sopenharmony_ci      op_encoding = 0x3 * B20;
42451cb0ef41Sopenharmony_ci      break;
42461cb0ef41Sopenharmony_ci    case VAND:
42471cb0ef41Sopenharmony_ci      // op_encoding is 0.
42481cb0ef41Sopenharmony_ci      break;
42491cb0ef41Sopenharmony_ci    default:
42501cb0ef41Sopenharmony_ci      UNREACHABLE();
42511cb0ef41Sopenharmony_ci  }
42521cb0ef41Sopenharmony_ci  int vd, d;
42531cb0ef41Sopenharmony_ci  NeonSplitCode(reg_type, dst_code, &vd, &d, &op_encoding);
42541cb0ef41Sopenharmony_ci  int vn, n;
42551cb0ef41Sopenharmony_ci  NeonSplitCode(reg_type, src_code1, &vn, &n, &op_encoding);
42561cb0ef41Sopenharmony_ci  int vm, m;
42571cb0ef41Sopenharmony_ci  NeonSplitCode(reg_type, src_code2, &vm, &m, &op_encoding);
42581cb0ef41Sopenharmony_ci
42591cb0ef41Sopenharmony_ci  return 0x1E4U * B23 | op_encoding | d * B22 | vn * B16 | vd * B12 | B8 |
42601cb0ef41Sopenharmony_ci         n * B7 | m * B5 | B4 | vm;
42611cb0ef41Sopenharmony_ci}
42621cb0ef41Sopenharmony_ci
42631cb0ef41Sopenharmony_civoid Assembler::vand(QwNeonRegister dst, QwNeonRegister src1,
42641cb0ef41Sopenharmony_ci                     QwNeonRegister src2) {
42651cb0ef41Sopenharmony_ci  // Qd = vand(Qn, Qm) SIMD AND.
42661cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8.8.836.
42671cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
42681cb0ef41Sopenharmony_ci  emit(EncodeNeonBinaryBitwiseOp(VAND, NEON_Q, dst.code(), src1.code(),
42691cb0ef41Sopenharmony_ci                                 src2.code()));
42701cb0ef41Sopenharmony_ci}
42711cb0ef41Sopenharmony_ci
42721cb0ef41Sopenharmony_civoid Assembler::vbic(QwNeonRegister dst, QwNeonRegister src1,
42731cb0ef41Sopenharmony_ci                     QwNeonRegister src2) {
42741cb0ef41Sopenharmony_ci  // Qd = vbic(Qn, Qm) SIMD AND.
42751cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-840.
42761cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
42771cb0ef41Sopenharmony_ci  emit(EncodeNeonBinaryBitwiseOp(VBIC, NEON_Q, dst.code(), src1.code(),
42781cb0ef41Sopenharmony_ci                                 src2.code()));
42791cb0ef41Sopenharmony_ci}
42801cb0ef41Sopenharmony_ci
42811cb0ef41Sopenharmony_civoid Assembler::vbsl(QwNeonRegister dst, QwNeonRegister src1,
42821cb0ef41Sopenharmony_ci                     QwNeonRegister src2) {
42831cb0ef41Sopenharmony_ci  // Qd = vbsl(Qn, Qm) SIMD bitwise select.
42841cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-844.
42851cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
42861cb0ef41Sopenharmony_ci  emit(EncodeNeonBinaryBitwiseOp(VBSL, NEON_Q, dst.code(), src1.code(),
42871cb0ef41Sopenharmony_ci                                 src2.code()));
42881cb0ef41Sopenharmony_ci}
42891cb0ef41Sopenharmony_ci
42901cb0ef41Sopenharmony_civoid Assembler::veor(DwVfpRegister dst, DwVfpRegister src1,
42911cb0ef41Sopenharmony_ci                     DwVfpRegister src2) {
42921cb0ef41Sopenharmony_ci  // Dd = veor(Dn, Dm) SIMD exclusive OR.
42931cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8.8.888.
42941cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
42951cb0ef41Sopenharmony_ci  emit(EncodeNeonBinaryBitwiseOp(VEOR, NEON_D, dst.code(), src1.code(),
42961cb0ef41Sopenharmony_ci                                 src2.code()));
42971cb0ef41Sopenharmony_ci}
42981cb0ef41Sopenharmony_ci
42991cb0ef41Sopenharmony_civoid Assembler::veor(QwNeonRegister dst, QwNeonRegister src1,
43001cb0ef41Sopenharmony_ci                     QwNeonRegister src2) {
43011cb0ef41Sopenharmony_ci  // Qd = veor(Qn, Qm) SIMD exclusive OR.
43021cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8.8.888.
43031cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
43041cb0ef41Sopenharmony_ci  emit(EncodeNeonBinaryBitwiseOp(VEOR, NEON_Q, dst.code(), src1.code(),
43051cb0ef41Sopenharmony_ci                                 src2.code()));
43061cb0ef41Sopenharmony_ci}
43071cb0ef41Sopenharmony_ci
43081cb0ef41Sopenharmony_civoid Assembler::vorr(QwNeonRegister dst, QwNeonRegister src1,
43091cb0ef41Sopenharmony_ci                     QwNeonRegister src2) {
43101cb0ef41Sopenharmony_ci  // Qd = vorr(Qn, Qm) SIMD OR.
43111cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8.8.976.
43121cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
43131cb0ef41Sopenharmony_ci  emit(EncodeNeonBinaryBitwiseOp(VORR, NEON_Q, dst.code(), src1.code(),
43141cb0ef41Sopenharmony_ci                                 src2.code()));
43151cb0ef41Sopenharmony_ci}
43161cb0ef41Sopenharmony_ci
43171cb0ef41Sopenharmony_civoid Assembler::vorn(QwNeonRegister dst, QwNeonRegister src1,
43181cb0ef41Sopenharmony_ci                     QwNeonRegister src2) {
43191cb0ef41Sopenharmony_ci  // Qd = vorn(Qn, Qm) SIMD OR NOT.
43201cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.d, A8.8.359.
43211cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
43221cb0ef41Sopenharmony_ci  emit(EncodeNeonBinaryBitwiseOp(VORN, NEON_Q, dst.code(), src1.code(),
43231cb0ef41Sopenharmony_ci                                 src2.code()));
43241cb0ef41Sopenharmony_ci}
43251cb0ef41Sopenharmony_ci
43261cb0ef41Sopenharmony_cienum FPBinOp {
43271cb0ef41Sopenharmony_ci  VADDF,
43281cb0ef41Sopenharmony_ci  VSUBF,
43291cb0ef41Sopenharmony_ci  VMULF,
43301cb0ef41Sopenharmony_ci  VMINF,
43311cb0ef41Sopenharmony_ci  VMAXF,
43321cb0ef41Sopenharmony_ci  VRECPS,
43331cb0ef41Sopenharmony_ci  VRSQRTS,
43341cb0ef41Sopenharmony_ci  VCEQF,
43351cb0ef41Sopenharmony_ci  VCGEF,
43361cb0ef41Sopenharmony_ci  VCGTF
43371cb0ef41Sopenharmony_ci};
43381cb0ef41Sopenharmony_ci
43391cb0ef41Sopenharmony_cistatic Instr EncodeNeonBinOp(FPBinOp op, QwNeonRegister dst,
43401cb0ef41Sopenharmony_ci                             QwNeonRegister src1, QwNeonRegister src2) {
43411cb0ef41Sopenharmony_ci  int op_encoding = 0;
43421cb0ef41Sopenharmony_ci  switch (op) {
43431cb0ef41Sopenharmony_ci    case VADDF:
43441cb0ef41Sopenharmony_ci      op_encoding = 0xD * B8;
43451cb0ef41Sopenharmony_ci      break;
43461cb0ef41Sopenharmony_ci    case VSUBF:
43471cb0ef41Sopenharmony_ci      op_encoding = B21 | 0xD * B8;
43481cb0ef41Sopenharmony_ci      break;
43491cb0ef41Sopenharmony_ci    case VMULF:
43501cb0ef41Sopenharmony_ci      op_encoding = B24 | 0xD * B8 | B4;
43511cb0ef41Sopenharmony_ci      break;
43521cb0ef41Sopenharmony_ci    case VMINF:
43531cb0ef41Sopenharmony_ci      op_encoding = B21 | 0xF * B8;
43541cb0ef41Sopenharmony_ci      break;
43551cb0ef41Sopenharmony_ci    case VMAXF:
43561cb0ef41Sopenharmony_ci      op_encoding = 0xF * B8;
43571cb0ef41Sopenharmony_ci      break;
43581cb0ef41Sopenharmony_ci    case VRECPS:
43591cb0ef41Sopenharmony_ci      op_encoding = 0xF * B8 | B4;
43601cb0ef41Sopenharmony_ci      break;
43611cb0ef41Sopenharmony_ci    case VRSQRTS:
43621cb0ef41Sopenharmony_ci      op_encoding = B21 | 0xF * B8 | B4;
43631cb0ef41Sopenharmony_ci      break;
43641cb0ef41Sopenharmony_ci    case VCEQF:
43651cb0ef41Sopenharmony_ci      op_encoding = 0xE * B8;
43661cb0ef41Sopenharmony_ci      break;
43671cb0ef41Sopenharmony_ci    case VCGEF:
43681cb0ef41Sopenharmony_ci      op_encoding = B24 | 0xE * B8;
43691cb0ef41Sopenharmony_ci      break;
43701cb0ef41Sopenharmony_ci    case VCGTF:
43711cb0ef41Sopenharmony_ci      op_encoding = B24 | B21 | 0xE * B8;
43721cb0ef41Sopenharmony_ci      break;
43731cb0ef41Sopenharmony_ci    default:
43741cb0ef41Sopenharmony_ci      UNREACHABLE();
43751cb0ef41Sopenharmony_ci  }
43761cb0ef41Sopenharmony_ci  int vd, d;
43771cb0ef41Sopenharmony_ci  dst.split_code(&vd, &d);
43781cb0ef41Sopenharmony_ci  int vn, n;
43791cb0ef41Sopenharmony_ci  src1.split_code(&vn, &n);
43801cb0ef41Sopenharmony_ci  int vm, m;
43811cb0ef41Sopenharmony_ci  src2.split_code(&vm, &m);
43821cb0ef41Sopenharmony_ci  return 0x1E4U * B23 | d * B22 | vn * B16 | vd * B12 | n * B7 | B6 | m * B5 |
43831cb0ef41Sopenharmony_ci         vm | op_encoding;
43841cb0ef41Sopenharmony_ci}
43851cb0ef41Sopenharmony_ci
43861cb0ef41Sopenharmony_cienum IntegerBinOp {
43871cb0ef41Sopenharmony_ci  VADD,
43881cb0ef41Sopenharmony_ci  VQADD,
43891cb0ef41Sopenharmony_ci  VSUB,
43901cb0ef41Sopenharmony_ci  VQSUB,
43911cb0ef41Sopenharmony_ci  VMUL,
43921cb0ef41Sopenharmony_ci  VMIN,
43931cb0ef41Sopenharmony_ci  VMAX,
43941cb0ef41Sopenharmony_ci  VTST,
43951cb0ef41Sopenharmony_ci  VCEQ,
43961cb0ef41Sopenharmony_ci  VCGE,
43971cb0ef41Sopenharmony_ci  VCGT,
43981cb0ef41Sopenharmony_ci  VRHADD,
43991cb0ef41Sopenharmony_ci  VQRDMULH
44001cb0ef41Sopenharmony_ci};
44011cb0ef41Sopenharmony_ci
44021cb0ef41Sopenharmony_cistatic Instr EncodeNeonBinOp(IntegerBinOp op, NeonDataType dt,
44031cb0ef41Sopenharmony_ci                             QwNeonRegister dst, QwNeonRegister src1,
44041cb0ef41Sopenharmony_ci                             QwNeonRegister src2) {
44051cb0ef41Sopenharmony_ci  int op_encoding = 0;
44061cb0ef41Sopenharmony_ci  switch (op) {
44071cb0ef41Sopenharmony_ci    case VADD:
44081cb0ef41Sopenharmony_ci      op_encoding = 0x8 * B8;
44091cb0ef41Sopenharmony_ci      break;
44101cb0ef41Sopenharmony_ci    case VQADD:
44111cb0ef41Sopenharmony_ci      op_encoding = B4;
44121cb0ef41Sopenharmony_ci      break;
44131cb0ef41Sopenharmony_ci    case VSUB:
44141cb0ef41Sopenharmony_ci      op_encoding = B24 | 0x8 * B8;
44151cb0ef41Sopenharmony_ci      break;
44161cb0ef41Sopenharmony_ci    case VQSUB:
44171cb0ef41Sopenharmony_ci      op_encoding = 0x2 * B8 | B4;
44181cb0ef41Sopenharmony_ci      break;
44191cb0ef41Sopenharmony_ci    case VMUL:
44201cb0ef41Sopenharmony_ci      op_encoding = 0x9 * B8 | B4;
44211cb0ef41Sopenharmony_ci      break;
44221cb0ef41Sopenharmony_ci    case VMIN:
44231cb0ef41Sopenharmony_ci      op_encoding = 0x6 * B8 | B4;
44241cb0ef41Sopenharmony_ci      break;
44251cb0ef41Sopenharmony_ci    case VMAX:
44261cb0ef41Sopenharmony_ci      op_encoding = 0x6 * B8;
44271cb0ef41Sopenharmony_ci      break;
44281cb0ef41Sopenharmony_ci    case VTST:
44291cb0ef41Sopenharmony_ci      op_encoding = 0x8 * B8 | B4;
44301cb0ef41Sopenharmony_ci      break;
44311cb0ef41Sopenharmony_ci    case VCEQ:
44321cb0ef41Sopenharmony_ci      op_encoding = B24 | 0x8 * B8 | B4;
44331cb0ef41Sopenharmony_ci      break;
44341cb0ef41Sopenharmony_ci    case VCGE:
44351cb0ef41Sopenharmony_ci      op_encoding = 0x3 * B8 | B4;
44361cb0ef41Sopenharmony_ci      break;
44371cb0ef41Sopenharmony_ci    case VCGT:
44381cb0ef41Sopenharmony_ci      op_encoding = 0x3 * B8;
44391cb0ef41Sopenharmony_ci      break;
44401cb0ef41Sopenharmony_ci    case VRHADD:
44411cb0ef41Sopenharmony_ci      op_encoding = B8;
44421cb0ef41Sopenharmony_ci      break;
44431cb0ef41Sopenharmony_ci    case VQRDMULH:
44441cb0ef41Sopenharmony_ci      op_encoding = B24 | 0xB * B8;
44451cb0ef41Sopenharmony_ci      break;
44461cb0ef41Sopenharmony_ci    default:
44471cb0ef41Sopenharmony_ci      UNREACHABLE();
44481cb0ef41Sopenharmony_ci  }
44491cb0ef41Sopenharmony_ci  int vd, d;
44501cb0ef41Sopenharmony_ci  dst.split_code(&vd, &d);
44511cb0ef41Sopenharmony_ci  int vn, n;
44521cb0ef41Sopenharmony_ci  src1.split_code(&vn, &n);
44531cb0ef41Sopenharmony_ci  int vm, m;
44541cb0ef41Sopenharmony_ci  src2.split_code(&vm, &m);
44551cb0ef41Sopenharmony_ci  int size = NeonSz(dt);
44561cb0ef41Sopenharmony_ci  int u = NeonU(dt);
44571cb0ef41Sopenharmony_ci  return 0x1E4U * B23 | u * B24 | d * B22 | size * B20 | vn * B16 | vd * B12 |
44581cb0ef41Sopenharmony_ci         n * B7 | B6 | m * B5 | vm | op_encoding;
44591cb0ef41Sopenharmony_ci}
44601cb0ef41Sopenharmony_ci
44611cb0ef41Sopenharmony_cistatic Instr EncodeNeonBinOp(IntegerBinOp op, NeonSize size, QwNeonRegister dst,
44621cb0ef41Sopenharmony_ci                             QwNeonRegister src1, QwNeonRegister src2) {
44631cb0ef41Sopenharmony_ci  // Map NeonSize values to the signed values in NeonDataType, so the U bit
44641cb0ef41Sopenharmony_ci  // will be 0.
44651cb0ef41Sopenharmony_ci  return EncodeNeonBinOp(op, static_cast<NeonDataType>(size), dst, src1, src2);
44661cb0ef41Sopenharmony_ci}
44671cb0ef41Sopenharmony_ci
44681cb0ef41Sopenharmony_civoid Assembler::vadd(QwNeonRegister dst, QwNeonRegister src1,
44691cb0ef41Sopenharmony_ci                     QwNeonRegister src2) {
44701cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
44711cb0ef41Sopenharmony_ci  // Qd = vadd(Qn, Qm) SIMD floating point addition.
44721cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-830.
44731cb0ef41Sopenharmony_ci  emit(EncodeNeonBinOp(VADDF, dst, src1, src2));
44741cb0ef41Sopenharmony_ci}
44751cb0ef41Sopenharmony_ci
44761cb0ef41Sopenharmony_civoid Assembler::vadd(NeonSize size, QwNeonRegister dst, QwNeonRegister src1,
44771cb0ef41Sopenharmony_ci                     QwNeonRegister src2) {
44781cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
44791cb0ef41Sopenharmony_ci  // Qd = vadd(Qn, Qm) SIMD integer addition.
44801cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-828.
44811cb0ef41Sopenharmony_ci  emit(EncodeNeonBinOp(VADD, size, dst, src1, src2));
44821cb0ef41Sopenharmony_ci}
44831cb0ef41Sopenharmony_ci
44841cb0ef41Sopenharmony_civoid Assembler::vqadd(NeonDataType dt, QwNeonRegister dst, QwNeonRegister src1,
44851cb0ef41Sopenharmony_ci                      QwNeonRegister src2) {
44861cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
44871cb0ef41Sopenharmony_ci  // Qd = vqadd(Qn, Qm) SIMD integer saturating addition.
44881cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-996.
44891cb0ef41Sopenharmony_ci  emit(EncodeNeonBinOp(VQADD, dt, dst, src1, src2));
44901cb0ef41Sopenharmony_ci}
44911cb0ef41Sopenharmony_ci
44921cb0ef41Sopenharmony_civoid Assembler::vsub(QwNeonRegister dst, QwNeonRegister src1,
44931cb0ef41Sopenharmony_ci                     QwNeonRegister src2) {
44941cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
44951cb0ef41Sopenharmony_ci  // Qd = vsub(Qn, Qm) SIMD floating point subtraction.
44961cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-1086.
44971cb0ef41Sopenharmony_ci  emit(EncodeNeonBinOp(VSUBF, dst, src1, src2));
44981cb0ef41Sopenharmony_ci}
44991cb0ef41Sopenharmony_ci
45001cb0ef41Sopenharmony_civoid Assembler::vsub(NeonSize size, QwNeonRegister dst, QwNeonRegister src1,
45011cb0ef41Sopenharmony_ci                     QwNeonRegister src2) {
45021cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
45031cb0ef41Sopenharmony_ci  // Qd = vsub(Qn, Qm) SIMD integer subtraction.
45041cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-1084.
45051cb0ef41Sopenharmony_ci  emit(EncodeNeonBinOp(VSUB, size, dst, src1, src2));
45061cb0ef41Sopenharmony_ci}
45071cb0ef41Sopenharmony_ci
45081cb0ef41Sopenharmony_civoid Assembler::vqsub(NeonDataType dt, QwNeonRegister dst, QwNeonRegister src1,
45091cb0ef41Sopenharmony_ci                      QwNeonRegister src2) {
45101cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
45111cb0ef41Sopenharmony_ci  // Qd = vqsub(Qn, Qm) SIMD integer saturating subtraction.
45121cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-1020.
45131cb0ef41Sopenharmony_ci  emit(EncodeNeonBinOp(VQSUB, dt, dst, src1, src2));
45141cb0ef41Sopenharmony_ci}
45151cb0ef41Sopenharmony_ci
45161cb0ef41Sopenharmony_civoid Assembler::vmlal(NeonDataType dt, QwNeonRegister dst, DwVfpRegister src1,
45171cb0ef41Sopenharmony_ci                      DwVfpRegister src2) {
45181cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
45191cb0ef41Sopenharmony_ci  // Qd = vmlal(Dn, Dm) Vector Multiply Accumulate Long (integer)
45201cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-931.
45211cb0ef41Sopenharmony_ci  int vd, d;
45221cb0ef41Sopenharmony_ci  dst.split_code(&vd, &d);
45231cb0ef41Sopenharmony_ci  int vn, n;
45241cb0ef41Sopenharmony_ci  src1.split_code(&vn, &n);
45251cb0ef41Sopenharmony_ci  int vm, m;
45261cb0ef41Sopenharmony_ci  src2.split_code(&vm, &m);
45271cb0ef41Sopenharmony_ci  int size = NeonSz(dt);
45281cb0ef41Sopenharmony_ci  int u = NeonU(dt);
45291cb0ef41Sopenharmony_ci  if (!u) UNIMPLEMENTED();
45301cb0ef41Sopenharmony_ci  DCHECK_NE(size, 3);  // SEE "Related encodings"
45311cb0ef41Sopenharmony_ci  emit(0xFU * B28 | B25 | u * B24 | B23 | d * B22 | size * B20 | vn * B16 |
45321cb0ef41Sopenharmony_ci       vd * B12 | 0x8 * B8 | n * B7 | m * B5 | vm);
45331cb0ef41Sopenharmony_ci}
45341cb0ef41Sopenharmony_ci
45351cb0ef41Sopenharmony_civoid Assembler::vmul(QwNeonRegister dst, QwNeonRegister src1,
45361cb0ef41Sopenharmony_ci                     QwNeonRegister src2) {
45371cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
45381cb0ef41Sopenharmony_ci  // Qd = vadd(Qn, Qm) SIMD floating point multiply.
45391cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-958.
45401cb0ef41Sopenharmony_ci  emit(EncodeNeonBinOp(VMULF, dst, src1, src2));
45411cb0ef41Sopenharmony_ci}
45421cb0ef41Sopenharmony_ci
45431cb0ef41Sopenharmony_civoid Assembler::vmul(NeonSize size, QwNeonRegister dst, QwNeonRegister src1,
45441cb0ef41Sopenharmony_ci                     QwNeonRegister src2) {
45451cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
45461cb0ef41Sopenharmony_ci  // Qd = vadd(Qn, Qm) SIMD integer multiply.
45471cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-960.
45481cb0ef41Sopenharmony_ci  emit(EncodeNeonBinOp(VMUL, size, dst, src1, src2));
45491cb0ef41Sopenharmony_ci}
45501cb0ef41Sopenharmony_ci
45511cb0ef41Sopenharmony_civoid Assembler::vmull(NeonDataType dt, QwNeonRegister dst, DwVfpRegister src1,
45521cb0ef41Sopenharmony_ci                      DwVfpRegister src2) {
45531cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
45541cb0ef41Sopenharmony_ci  // Qd = vmull(Dn, Dm) Vector Multiply Long (integer).
45551cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-960.
45561cb0ef41Sopenharmony_ci  int vd, d;
45571cb0ef41Sopenharmony_ci  dst.split_code(&vd, &d);
45581cb0ef41Sopenharmony_ci  int vn, n;
45591cb0ef41Sopenharmony_ci  src1.split_code(&vn, &n);
45601cb0ef41Sopenharmony_ci  int vm, m;
45611cb0ef41Sopenharmony_ci  src2.split_code(&vm, &m);
45621cb0ef41Sopenharmony_ci  int size = NeonSz(dt);
45631cb0ef41Sopenharmony_ci  int u = NeonU(dt);
45641cb0ef41Sopenharmony_ci  emit(0xFU * B28 | B25 | u * B24 | B23 | d * B22 | size * B20 | vn * B16 |
45651cb0ef41Sopenharmony_ci       vd * B12 | 0xC * B8 | n * B7 | m * B5 | vm);
45661cb0ef41Sopenharmony_ci}
45671cb0ef41Sopenharmony_ci
45681cb0ef41Sopenharmony_civoid Assembler::vmin(QwNeonRegister dst, QwNeonRegister src1,
45691cb0ef41Sopenharmony_ci                     QwNeonRegister src2) {
45701cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
45711cb0ef41Sopenharmony_ci  // Qd = vmin(Qn, Qm) SIMD floating point MIN.
45721cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-928.
45731cb0ef41Sopenharmony_ci  emit(EncodeNeonBinOp(VMINF, dst, src1, src2));
45741cb0ef41Sopenharmony_ci}
45751cb0ef41Sopenharmony_ci
45761cb0ef41Sopenharmony_civoid Assembler::vmin(NeonDataType dt, QwNeonRegister dst, QwNeonRegister src1,
45771cb0ef41Sopenharmony_ci                     QwNeonRegister src2) {
45781cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
45791cb0ef41Sopenharmony_ci  // Qd = vmin(Qn, Qm) SIMD integer MIN.
45801cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-926.
45811cb0ef41Sopenharmony_ci  emit(EncodeNeonBinOp(VMIN, dt, dst, src1, src2));
45821cb0ef41Sopenharmony_ci}
45831cb0ef41Sopenharmony_ci
45841cb0ef41Sopenharmony_civoid Assembler::vmax(QwNeonRegister dst, QwNeonRegister src1,
45851cb0ef41Sopenharmony_ci                     QwNeonRegister src2) {
45861cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
45871cb0ef41Sopenharmony_ci  // Qd = vmax(Qn, Qm) SIMD floating point MAX.
45881cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-928.
45891cb0ef41Sopenharmony_ci  emit(EncodeNeonBinOp(VMAXF, dst, src1, src2));
45901cb0ef41Sopenharmony_ci}
45911cb0ef41Sopenharmony_ci
45921cb0ef41Sopenharmony_civoid Assembler::vmax(NeonDataType dt, QwNeonRegister dst, QwNeonRegister src1,
45931cb0ef41Sopenharmony_ci                     QwNeonRegister src2) {
45941cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
45951cb0ef41Sopenharmony_ci  // Qd = vmax(Qn, Qm) SIMD integer MAX.
45961cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-926.
45971cb0ef41Sopenharmony_ci  emit(EncodeNeonBinOp(VMAX, dt, dst, src1, src2));
45981cb0ef41Sopenharmony_ci}
45991cb0ef41Sopenharmony_ci
46001cb0ef41Sopenharmony_cienum NeonShiftOp { VSHL, VSHR, VSLI, VSRI, VSRA };
46011cb0ef41Sopenharmony_ci
46021cb0ef41Sopenharmony_cistatic Instr EncodeNeonShiftRegisterOp(NeonShiftOp op, NeonDataType dt,
46031cb0ef41Sopenharmony_ci                                       NeonRegType reg_type, int dst_code,
46041cb0ef41Sopenharmony_ci                                       int src_code, int shift_code) {
46051cb0ef41Sopenharmony_ci  DCHECK_EQ(op, VSHL);
46061cb0ef41Sopenharmony_ci  int op_encoding = 0;
46071cb0ef41Sopenharmony_ci  int vd, d;
46081cb0ef41Sopenharmony_ci  NeonSplitCode(reg_type, dst_code, &vd, &d, &op_encoding);
46091cb0ef41Sopenharmony_ci  int vm, m;
46101cb0ef41Sopenharmony_ci  NeonSplitCode(reg_type, src_code, &vm, &m, &op_encoding);
46111cb0ef41Sopenharmony_ci  int vn, n;
46121cb0ef41Sopenharmony_ci  NeonSplitCode(reg_type, shift_code, &vn, &n, &op_encoding);
46131cb0ef41Sopenharmony_ci  int size = NeonSz(dt);
46141cb0ef41Sopenharmony_ci  int u = NeonU(dt);
46151cb0ef41Sopenharmony_ci
46161cb0ef41Sopenharmony_ci  return 0x1E4U * B23 | u * B24 | d * B22 | size * B20 | vn * B16 | vd * B12 |
46171cb0ef41Sopenharmony_ci         0x4 * B8 | n * B7 | m * B5 | vm | op_encoding;
46181cb0ef41Sopenharmony_ci}
46191cb0ef41Sopenharmony_ci
46201cb0ef41Sopenharmony_cistatic Instr EncodeNeonShiftOp(NeonShiftOp op, NeonSize size, bool is_unsigned,
46211cb0ef41Sopenharmony_ci                               NeonRegType reg_type, int dst_code, int src_code,
46221cb0ef41Sopenharmony_ci                               int shift) {
46231cb0ef41Sopenharmony_ci  int size_in_bits = kBitsPerByte << static_cast<int>(size);
46241cb0ef41Sopenharmony_ci  int op_encoding = 0, imm6 = 0, L = 0;
46251cb0ef41Sopenharmony_ci  switch (op) {
46261cb0ef41Sopenharmony_ci    case VSHL: {
46271cb0ef41Sopenharmony_ci      DCHECK(shift >= 0 && size_in_bits > shift);
46281cb0ef41Sopenharmony_ci      imm6 = size_in_bits + shift;
46291cb0ef41Sopenharmony_ci      op_encoding = 0x5 * B8;
46301cb0ef41Sopenharmony_ci      break;
46311cb0ef41Sopenharmony_ci    }
46321cb0ef41Sopenharmony_ci    case VSHR: {
46331cb0ef41Sopenharmony_ci      DCHECK(shift > 0 && size_in_bits >= shift);
46341cb0ef41Sopenharmony_ci      imm6 = 2 * size_in_bits - shift;
46351cb0ef41Sopenharmony_ci      if (is_unsigned) op_encoding |= B24;
46361cb0ef41Sopenharmony_ci      break;
46371cb0ef41Sopenharmony_ci    }
46381cb0ef41Sopenharmony_ci    case VSLI: {
46391cb0ef41Sopenharmony_ci      DCHECK(shift >= 0 && size_in_bits > shift);
46401cb0ef41Sopenharmony_ci      imm6 = size_in_bits + shift;
46411cb0ef41Sopenharmony_ci      op_encoding = B24 | 0x5 * B8;
46421cb0ef41Sopenharmony_ci      break;
46431cb0ef41Sopenharmony_ci    }
46441cb0ef41Sopenharmony_ci    case VSRI: {
46451cb0ef41Sopenharmony_ci      DCHECK(shift > 0 && size_in_bits >= shift);
46461cb0ef41Sopenharmony_ci      imm6 = 2 * size_in_bits - shift;
46471cb0ef41Sopenharmony_ci      op_encoding = B24 | 0x4 * B8;
46481cb0ef41Sopenharmony_ci      break;
46491cb0ef41Sopenharmony_ci    }
46501cb0ef41Sopenharmony_ci    case VSRA: {
46511cb0ef41Sopenharmony_ci      DCHECK(shift > 0 && size_in_bits >= shift);
46521cb0ef41Sopenharmony_ci      imm6 = 2 * size_in_bits - shift;
46531cb0ef41Sopenharmony_ci      op_encoding = B8;
46541cb0ef41Sopenharmony_ci      if (is_unsigned) op_encoding |= B24;
46551cb0ef41Sopenharmony_ci      break;
46561cb0ef41Sopenharmony_ci    }
46571cb0ef41Sopenharmony_ci    default:
46581cb0ef41Sopenharmony_ci      UNREACHABLE();
46591cb0ef41Sopenharmony_ci  }
46601cb0ef41Sopenharmony_ci
46611cb0ef41Sopenharmony_ci  L = imm6 >> 6;
46621cb0ef41Sopenharmony_ci  imm6 &= 0x3F;
46631cb0ef41Sopenharmony_ci
46641cb0ef41Sopenharmony_ci  int vd, d;
46651cb0ef41Sopenharmony_ci  NeonSplitCode(reg_type, dst_code, &vd, &d, &op_encoding);
46661cb0ef41Sopenharmony_ci  int vm, m;
46671cb0ef41Sopenharmony_ci  NeonSplitCode(reg_type, src_code, &vm, &m, &op_encoding);
46681cb0ef41Sopenharmony_ci
46691cb0ef41Sopenharmony_ci  return 0x1E5U * B23 | d * B22 | imm6 * B16 | vd * B12 | L * B7 | m * B5 | B4 |
46701cb0ef41Sopenharmony_ci         vm | op_encoding;
46711cb0ef41Sopenharmony_ci}
46721cb0ef41Sopenharmony_ci
46731cb0ef41Sopenharmony_civoid Assembler::vshl(NeonDataType dt, QwNeonRegister dst, QwNeonRegister src,
46741cb0ef41Sopenharmony_ci                     int shift) {
46751cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
46761cb0ef41Sopenharmony_ci  // Qd = vshl(Qm, bits) SIMD shift left immediate.
46771cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-1046.
46781cb0ef41Sopenharmony_ci  emit(EncodeNeonShiftOp(VSHL, NeonDataTypeToSize(dt), false, NEON_Q,
46791cb0ef41Sopenharmony_ci                         dst.code(), src.code(), shift));
46801cb0ef41Sopenharmony_ci}
46811cb0ef41Sopenharmony_ci
46821cb0ef41Sopenharmony_civoid Assembler::vshl(NeonDataType dt, QwNeonRegister dst, QwNeonRegister src,
46831cb0ef41Sopenharmony_ci                     QwNeonRegister shift) {
46841cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
46851cb0ef41Sopenharmony_ci  // Qd = vshl(Qm, Qn) SIMD shift left Register.
46861cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0487A.a, F8-3340..
46871cb0ef41Sopenharmony_ci  emit(EncodeNeonShiftRegisterOp(VSHL, dt, NEON_Q, dst.code(), src.code(),
46881cb0ef41Sopenharmony_ci                                 shift.code()));
46891cb0ef41Sopenharmony_ci}
46901cb0ef41Sopenharmony_ci
46911cb0ef41Sopenharmony_civoid Assembler::vshr(NeonDataType dt, DwVfpRegister dst, DwVfpRegister src,
46921cb0ef41Sopenharmony_ci                     int shift) {
46931cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
46941cb0ef41Sopenharmony_ci  // Dd = vshr(Dm, bits) SIMD shift right immediate.
46951cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-1052.
46961cb0ef41Sopenharmony_ci  emit(EncodeNeonShiftOp(VSHR, NeonDataTypeToSize(dt), NeonU(dt), NEON_D,
46971cb0ef41Sopenharmony_ci                         dst.code(), src.code(), shift));
46981cb0ef41Sopenharmony_ci}
46991cb0ef41Sopenharmony_ci
47001cb0ef41Sopenharmony_civoid Assembler::vshr(NeonDataType dt, QwNeonRegister dst, QwNeonRegister src,
47011cb0ef41Sopenharmony_ci                     int shift) {
47021cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
47031cb0ef41Sopenharmony_ci  // Qd = vshr(Qm, bits) SIMD shift right immediate.
47041cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-1052.
47051cb0ef41Sopenharmony_ci  emit(EncodeNeonShiftOp(VSHR, NeonDataTypeToSize(dt), NeonU(dt), NEON_Q,
47061cb0ef41Sopenharmony_ci                         dst.code(), src.code(), shift));
47071cb0ef41Sopenharmony_ci}
47081cb0ef41Sopenharmony_ci
47091cb0ef41Sopenharmony_civoid Assembler::vsli(NeonSize size, DwVfpRegister dst, DwVfpRegister src,
47101cb0ef41Sopenharmony_ci                     int shift) {
47111cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
47121cb0ef41Sopenharmony_ci  // Dd = vsli(Dm, bits) SIMD shift left and insert.
47131cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-1056.
47141cb0ef41Sopenharmony_ci  emit(EncodeNeonShiftOp(VSLI, size, false, NEON_D, dst.code(), src.code(),
47151cb0ef41Sopenharmony_ci                         shift));
47161cb0ef41Sopenharmony_ci}
47171cb0ef41Sopenharmony_ci
47181cb0ef41Sopenharmony_civoid Assembler::vsri(NeonSize size, DwVfpRegister dst, DwVfpRegister src,
47191cb0ef41Sopenharmony_ci                     int shift) {
47201cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
47211cb0ef41Sopenharmony_ci  // Dd = vsri(Dm, bits) SIMD shift right and insert.
47221cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-1062.
47231cb0ef41Sopenharmony_ci  emit(EncodeNeonShiftOp(VSRI, size, false, NEON_D, dst.code(), src.code(),
47241cb0ef41Sopenharmony_ci                         shift));
47251cb0ef41Sopenharmony_ci}
47261cb0ef41Sopenharmony_ci
47271cb0ef41Sopenharmony_civoid Assembler::vsra(NeonDataType dt, DwVfpRegister dst, DwVfpRegister src,
47281cb0ef41Sopenharmony_ci                     int imm) {
47291cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
47301cb0ef41Sopenharmony_ci  // Dd = vsra(Dm, imm) SIMD shift right and accumulate.
47311cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0487F.b, F6-5569.
47321cb0ef41Sopenharmony_ci  emit(EncodeNeonShiftOp(VSRA, NeonDataTypeToSize(dt), NeonU(dt), NEON_D,
47331cb0ef41Sopenharmony_ci                         dst.code(), src.code(), imm));
47341cb0ef41Sopenharmony_ci}
47351cb0ef41Sopenharmony_ci
47361cb0ef41Sopenharmony_civoid Assembler::vrecpe(QwNeonRegister dst, QwNeonRegister src) {
47371cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
47381cb0ef41Sopenharmony_ci  // Qd = vrecpe(Qm) SIMD reciprocal estimate.
47391cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-1024.
47401cb0ef41Sopenharmony_ci  emit(EncodeNeonUnaryOp(VRECPE, NEON_Q, Neon32, dst.code(), src.code()));
47411cb0ef41Sopenharmony_ci}
47421cb0ef41Sopenharmony_ci
47431cb0ef41Sopenharmony_civoid Assembler::vrsqrte(QwNeonRegister dst, QwNeonRegister src) {
47441cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
47451cb0ef41Sopenharmony_ci  // Qd = vrsqrte(Qm) SIMD reciprocal square root estimate.
47461cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-1038.
47471cb0ef41Sopenharmony_ci  emit(EncodeNeonUnaryOp(VRSQRTE, NEON_Q, Neon32, dst.code(), src.code()));
47481cb0ef41Sopenharmony_ci}
47491cb0ef41Sopenharmony_ci
47501cb0ef41Sopenharmony_civoid Assembler::vrecps(QwNeonRegister dst, QwNeonRegister src1,
47511cb0ef41Sopenharmony_ci                       QwNeonRegister src2) {
47521cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
47531cb0ef41Sopenharmony_ci  // Qd = vrecps(Qn, Qm) SIMD reciprocal refinement step.
47541cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-1026.
47551cb0ef41Sopenharmony_ci  emit(EncodeNeonBinOp(VRECPS, dst, src1, src2));
47561cb0ef41Sopenharmony_ci}
47571cb0ef41Sopenharmony_ci
47581cb0ef41Sopenharmony_civoid Assembler::vrsqrts(QwNeonRegister dst, QwNeonRegister src1,
47591cb0ef41Sopenharmony_ci                        QwNeonRegister src2) {
47601cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
47611cb0ef41Sopenharmony_ci  // Qd = vrsqrts(Qn, Qm) SIMD reciprocal square root refinement step.
47621cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-1040.
47631cb0ef41Sopenharmony_ci  emit(EncodeNeonBinOp(VRSQRTS, dst, src1, src2));
47641cb0ef41Sopenharmony_ci}
47651cb0ef41Sopenharmony_ci
47661cb0ef41Sopenharmony_cienum NeonPairwiseOp { VPADD, VPMIN, VPMAX };
47671cb0ef41Sopenharmony_ci
47681cb0ef41Sopenharmony_cistatic Instr EncodeNeonPairwiseOp(NeonPairwiseOp op, NeonDataType dt,
47691cb0ef41Sopenharmony_ci                                  DwVfpRegister dst, DwVfpRegister src1,
47701cb0ef41Sopenharmony_ci                                  DwVfpRegister src2) {
47711cb0ef41Sopenharmony_ci  int op_encoding = 0;
47721cb0ef41Sopenharmony_ci  switch (op) {
47731cb0ef41Sopenharmony_ci    case VPADD:
47741cb0ef41Sopenharmony_ci      op_encoding = 0xB * B8 | B4;
47751cb0ef41Sopenharmony_ci      break;
47761cb0ef41Sopenharmony_ci    case VPMIN:
47771cb0ef41Sopenharmony_ci      op_encoding = 0xA * B8 | B4;
47781cb0ef41Sopenharmony_ci      break;
47791cb0ef41Sopenharmony_ci    case VPMAX:
47801cb0ef41Sopenharmony_ci      op_encoding = 0xA * B8;
47811cb0ef41Sopenharmony_ci      break;
47821cb0ef41Sopenharmony_ci    default:
47831cb0ef41Sopenharmony_ci      UNREACHABLE();
47841cb0ef41Sopenharmony_ci  }
47851cb0ef41Sopenharmony_ci  int vd, d;
47861cb0ef41Sopenharmony_ci  dst.split_code(&vd, &d);
47871cb0ef41Sopenharmony_ci  int vn, n;
47881cb0ef41Sopenharmony_ci  src1.split_code(&vn, &n);
47891cb0ef41Sopenharmony_ci  int vm, m;
47901cb0ef41Sopenharmony_ci  src2.split_code(&vm, &m);
47911cb0ef41Sopenharmony_ci  int size = NeonSz(dt);
47921cb0ef41Sopenharmony_ci  int u = NeonU(dt);
47931cb0ef41Sopenharmony_ci  return 0x1E4U * B23 | u * B24 | d * B22 | size * B20 | vn * B16 | vd * B12 |
47941cb0ef41Sopenharmony_ci         n * B7 | m * B5 | vm | op_encoding;
47951cb0ef41Sopenharmony_ci}
47961cb0ef41Sopenharmony_ci
47971cb0ef41Sopenharmony_civoid Assembler::vpadd(DwVfpRegister dst, DwVfpRegister src1,
47981cb0ef41Sopenharmony_ci                      DwVfpRegister src2) {
47991cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
48001cb0ef41Sopenharmony_ci  // Dd = vpadd(Dn, Dm) SIMD floating point pairwise ADD.
48011cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-982.
48021cb0ef41Sopenharmony_ci  int vd, d;
48031cb0ef41Sopenharmony_ci  dst.split_code(&vd, &d);
48041cb0ef41Sopenharmony_ci  int vn, n;
48051cb0ef41Sopenharmony_ci  src1.split_code(&vn, &n);
48061cb0ef41Sopenharmony_ci  int vm, m;
48071cb0ef41Sopenharmony_ci  src2.split_code(&vm, &m);
48081cb0ef41Sopenharmony_ci
48091cb0ef41Sopenharmony_ci  emit(0x1E6U * B23 | d * B22 | vn * B16 | vd * B12 | 0xD * B8 | n * B7 |
48101cb0ef41Sopenharmony_ci       m * B5 | vm);
48111cb0ef41Sopenharmony_ci}
48121cb0ef41Sopenharmony_ci
48131cb0ef41Sopenharmony_civoid Assembler::vpadd(NeonSize size, DwVfpRegister dst, DwVfpRegister src1,
48141cb0ef41Sopenharmony_ci                      DwVfpRegister src2) {
48151cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
48161cb0ef41Sopenharmony_ci  // Dd = vpadd(Dn, Dm) SIMD integer pairwise ADD.
48171cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-980.
48181cb0ef41Sopenharmony_ci  emit(EncodeNeonPairwiseOp(VPADD, NeonSizeToDataType(size), dst, src1, src2));
48191cb0ef41Sopenharmony_ci}
48201cb0ef41Sopenharmony_ci
48211cb0ef41Sopenharmony_civoid Assembler::vpmin(NeonDataType dt, DwVfpRegister dst, DwVfpRegister src1,
48221cb0ef41Sopenharmony_ci                      DwVfpRegister src2) {
48231cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
48241cb0ef41Sopenharmony_ci  // Dd = vpmin(Dn, Dm) SIMD integer pairwise MIN.
48251cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-986.
48261cb0ef41Sopenharmony_ci  emit(EncodeNeonPairwiseOp(VPMIN, dt, dst, src1, src2));
48271cb0ef41Sopenharmony_ci}
48281cb0ef41Sopenharmony_ci
48291cb0ef41Sopenharmony_civoid Assembler::vpmax(NeonDataType dt, DwVfpRegister dst, DwVfpRegister src1,
48301cb0ef41Sopenharmony_ci                      DwVfpRegister src2) {
48311cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
48321cb0ef41Sopenharmony_ci  // Dd = vpmax(Dn, Dm) SIMD integer pairwise MAX.
48331cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-986.
48341cb0ef41Sopenharmony_ci  emit(EncodeNeonPairwiseOp(VPMAX, dt, dst, src1, src2));
48351cb0ef41Sopenharmony_ci}
48361cb0ef41Sopenharmony_ci
48371cb0ef41Sopenharmony_civoid Assembler::vrintm(NeonDataType dt, const QwNeonRegister dst,
48381cb0ef41Sopenharmony_ci                       const QwNeonRegister src) {
48391cb0ef41Sopenharmony_ci  // SIMD vector round floating-point to integer towards -Infinity.
48401cb0ef41Sopenharmony_ci  // See ARM DDI 0487F.b, F6-5493.
48411cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(ARMv8));
48421cb0ef41Sopenharmony_ci  emit(EncodeNeonUnaryOp(VRINTM, NEON_Q, NeonSize(dt), dst.code(), src.code()));
48431cb0ef41Sopenharmony_ci}
48441cb0ef41Sopenharmony_ci
48451cb0ef41Sopenharmony_civoid Assembler::vrintn(NeonDataType dt, const QwNeonRegister dst,
48461cb0ef41Sopenharmony_ci                       const QwNeonRegister src) {
48471cb0ef41Sopenharmony_ci  // SIMD vector round floating-point to integer to Nearest.
48481cb0ef41Sopenharmony_ci  // See ARM DDI 0487F.b, F6-5497.
48491cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(ARMv8));
48501cb0ef41Sopenharmony_ci  emit(EncodeNeonUnaryOp(VRINTN, NEON_Q, NeonSize(dt), dst.code(), src.code()));
48511cb0ef41Sopenharmony_ci}
48521cb0ef41Sopenharmony_ci
48531cb0ef41Sopenharmony_civoid Assembler::vrintp(NeonDataType dt, const QwNeonRegister dst,
48541cb0ef41Sopenharmony_ci                       const QwNeonRegister src) {
48551cb0ef41Sopenharmony_ci  // SIMD vector round floating-point to integer towards +Infinity.
48561cb0ef41Sopenharmony_ci  // See ARM DDI 0487F.b, F6-5501.
48571cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(ARMv8));
48581cb0ef41Sopenharmony_ci  emit(EncodeNeonUnaryOp(VRINTP, NEON_Q, NeonSize(dt), dst.code(), src.code()));
48591cb0ef41Sopenharmony_ci}
48601cb0ef41Sopenharmony_ci
48611cb0ef41Sopenharmony_civoid Assembler::vrintz(NeonDataType dt, const QwNeonRegister dst,
48621cb0ef41Sopenharmony_ci                       const QwNeonRegister src) {
48631cb0ef41Sopenharmony_ci  // SIMD vector round floating-point to integer towards Zero.
48641cb0ef41Sopenharmony_ci  // See ARM DDI 0487F.b, F6-5511.
48651cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(ARMv8));
48661cb0ef41Sopenharmony_ci  emit(EncodeNeonUnaryOp(VRINTZ, NEON_Q, NeonSize(dt), dst.code(), src.code()));
48671cb0ef41Sopenharmony_ci}
48681cb0ef41Sopenharmony_ci
48691cb0ef41Sopenharmony_civoid Assembler::vtst(NeonSize size, QwNeonRegister dst, QwNeonRegister src1,
48701cb0ef41Sopenharmony_ci                     QwNeonRegister src2) {
48711cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
48721cb0ef41Sopenharmony_ci  // Qd = vtst(Qn, Qm) SIMD test integer operands.
48731cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-1098.
48741cb0ef41Sopenharmony_ci  emit(EncodeNeonBinOp(VTST, size, dst, src1, src2));
48751cb0ef41Sopenharmony_ci}
48761cb0ef41Sopenharmony_ci
48771cb0ef41Sopenharmony_civoid Assembler::vceq(QwNeonRegister dst, QwNeonRegister src1,
48781cb0ef41Sopenharmony_ci                     QwNeonRegister src2) {
48791cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
48801cb0ef41Sopenharmony_ci  // Qd = vceq(Qn, Qm) SIMD floating point compare equal.
48811cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-844.
48821cb0ef41Sopenharmony_ci  emit(EncodeNeonBinOp(VCEQF, dst, src1, src2));
48831cb0ef41Sopenharmony_ci}
48841cb0ef41Sopenharmony_ci
48851cb0ef41Sopenharmony_civoid Assembler::vceq(NeonSize size, QwNeonRegister dst, QwNeonRegister src1,
48861cb0ef41Sopenharmony_ci                     QwNeonRegister src2) {
48871cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
48881cb0ef41Sopenharmony_ci  // Qd = vceq(Qn, Qm) SIMD integer compare equal.
48891cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-844.
48901cb0ef41Sopenharmony_ci  emit(EncodeNeonBinOp(VCEQ, size, dst, src1, src2));
48911cb0ef41Sopenharmony_ci}
48921cb0ef41Sopenharmony_ci
48931cb0ef41Sopenharmony_civoid Assembler::vceq(NeonSize size, QwNeonRegister dst, QwNeonRegister src1,
48941cb0ef41Sopenharmony_ci                     int value) {
48951cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
48961cb0ef41Sopenharmony_ci  DCHECK_EQ(0, value);
48971cb0ef41Sopenharmony_ci  // Qd = vceq(Qn, Qm, #0) Vector Compare Equal to Zero.
48981cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.d, A8-847.
48991cb0ef41Sopenharmony_ci  emit(EncodeNeonUnaryOp(VCEQ0, NEON_Q, size, dst.code(), src1.code()));
49001cb0ef41Sopenharmony_ci}
49011cb0ef41Sopenharmony_ci
49021cb0ef41Sopenharmony_civoid Assembler::vcge(QwNeonRegister dst, QwNeonRegister src1,
49031cb0ef41Sopenharmony_ci                     QwNeonRegister src2) {
49041cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
49051cb0ef41Sopenharmony_ci  // Qd = vcge(Qn, Qm) SIMD floating point compare greater or equal.
49061cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-848.
49071cb0ef41Sopenharmony_ci  emit(EncodeNeonBinOp(VCGEF, dst, src1, src2));
49081cb0ef41Sopenharmony_ci}
49091cb0ef41Sopenharmony_ci
49101cb0ef41Sopenharmony_civoid Assembler::vcge(NeonDataType dt, QwNeonRegister dst, QwNeonRegister src1,
49111cb0ef41Sopenharmony_ci                     QwNeonRegister src2) {
49121cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
49131cb0ef41Sopenharmony_ci  // Qd = vcge(Qn, Qm) SIMD integer compare greater or equal.
49141cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-848.
49151cb0ef41Sopenharmony_ci  emit(EncodeNeonBinOp(VCGE, dt, dst, src1, src2));
49161cb0ef41Sopenharmony_ci}
49171cb0ef41Sopenharmony_ci
49181cb0ef41Sopenharmony_civoid Assembler::vcgt(QwNeonRegister dst, QwNeonRegister src1,
49191cb0ef41Sopenharmony_ci                     QwNeonRegister src2) {
49201cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
49211cb0ef41Sopenharmony_ci  // Qd = vcgt(Qn, Qm) SIMD floating point compare greater than.
49221cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-852.
49231cb0ef41Sopenharmony_ci  emit(EncodeNeonBinOp(VCGTF, dst, src1, src2));
49241cb0ef41Sopenharmony_ci}
49251cb0ef41Sopenharmony_ci
49261cb0ef41Sopenharmony_civoid Assembler::vcgt(NeonDataType dt, QwNeonRegister dst, QwNeonRegister src1,
49271cb0ef41Sopenharmony_ci                     QwNeonRegister src2) {
49281cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
49291cb0ef41Sopenharmony_ci  // Qd = vcgt(Qn, Qm) SIMD integer compare greater than.
49301cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-852.
49311cb0ef41Sopenharmony_ci  emit(EncodeNeonBinOp(VCGT, dt, dst, src1, src2));
49321cb0ef41Sopenharmony_ci}
49331cb0ef41Sopenharmony_ci
49341cb0ef41Sopenharmony_civoid Assembler::vclt(NeonSize size, QwNeonRegister dst, QwNeonRegister src,
49351cb0ef41Sopenharmony_ci                     int value) {
49361cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
49371cb0ef41Sopenharmony_ci  DCHECK_EQ(0, value);
49381cb0ef41Sopenharmony_ci  // vclt.<size>(Qn, Qm, #0) SIMD Vector Compare Less Than Zero.
49391cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0487F.b, F6-5072.
49401cb0ef41Sopenharmony_ci  emit(EncodeNeonUnaryOp(VCLT0, NEON_Q, size, dst.code(), src.code()));
49411cb0ef41Sopenharmony_ci}
49421cb0ef41Sopenharmony_ci
49431cb0ef41Sopenharmony_civoid Assembler::vrhadd(NeonDataType dt, QwNeonRegister dst, QwNeonRegister src1,
49441cb0ef41Sopenharmony_ci                       QwNeonRegister src2) {
49451cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
49461cb0ef41Sopenharmony_ci  // Qd = vrhadd(Qn, Qm) SIMD integer rounding halving add.
49471cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-1030.
49481cb0ef41Sopenharmony_ci  emit(EncodeNeonBinOp(VRHADD, dt, dst, src1, src2));
49491cb0ef41Sopenharmony_ci}
49501cb0ef41Sopenharmony_ci
49511cb0ef41Sopenharmony_civoid Assembler::vext(QwNeonRegister dst, QwNeonRegister src1,
49521cb0ef41Sopenharmony_ci                     QwNeonRegister src2, int bytes) {
49531cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
49541cb0ef41Sopenharmony_ci  // Qd = vext(Qn, Qm) SIMD byte extract.
49551cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-890.
49561cb0ef41Sopenharmony_ci  int vd, d;
49571cb0ef41Sopenharmony_ci  dst.split_code(&vd, &d);
49581cb0ef41Sopenharmony_ci  int vn, n;
49591cb0ef41Sopenharmony_ci  src1.split_code(&vn, &n);
49601cb0ef41Sopenharmony_ci  int vm, m;
49611cb0ef41Sopenharmony_ci  src2.split_code(&vm, &m);
49621cb0ef41Sopenharmony_ci  DCHECK_GT(16, bytes);
49631cb0ef41Sopenharmony_ci  emit(0x1E5U * B23 | d * B22 | 0x3 * B20 | vn * B16 | vd * B12 | bytes * B8 |
49641cb0ef41Sopenharmony_ci       n * B7 | B6 | m * B5 | vm);
49651cb0ef41Sopenharmony_ci}
49661cb0ef41Sopenharmony_ci
49671cb0ef41Sopenharmony_civoid Assembler::vzip(NeonSize size, DwVfpRegister src1, DwVfpRegister src2) {
49681cb0ef41Sopenharmony_ci  if (size == Neon32) {  // vzip.32 Dd, Dm is a pseudo-op for vtrn.32 Dd, Dm.
49691cb0ef41Sopenharmony_ci    vtrn(size, src1, src2);
49701cb0ef41Sopenharmony_ci  } else {
49711cb0ef41Sopenharmony_ci    DCHECK(IsEnabled(NEON));
49721cb0ef41Sopenharmony_ci    // vzip.<size>(Dn, Dm) SIMD zip (interleave).
49731cb0ef41Sopenharmony_ci    // Instruction details available in ARM DDI 0406C.b, A8-1102.
49741cb0ef41Sopenharmony_ci    emit(EncodeNeonUnaryOp(VZIP, NEON_D, size, src1.code(), src2.code()));
49751cb0ef41Sopenharmony_ci  }
49761cb0ef41Sopenharmony_ci}
49771cb0ef41Sopenharmony_ci
49781cb0ef41Sopenharmony_civoid Assembler::vzip(NeonSize size, QwNeonRegister src1, QwNeonRegister src2) {
49791cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
49801cb0ef41Sopenharmony_ci  // vzip.<size>(Qn, Qm) SIMD zip (interleave).
49811cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-1102.
49821cb0ef41Sopenharmony_ci  emit(EncodeNeonUnaryOp(VZIP, NEON_Q, size, src1.code(), src2.code()));
49831cb0ef41Sopenharmony_ci}
49841cb0ef41Sopenharmony_ci
49851cb0ef41Sopenharmony_civoid Assembler::vuzp(NeonSize size, DwVfpRegister src1, DwVfpRegister src2) {
49861cb0ef41Sopenharmony_ci  if (size == Neon32) {  // vuzp.32 Dd, Dm is a pseudo-op for vtrn.32 Dd, Dm.
49871cb0ef41Sopenharmony_ci    vtrn(size, src1, src2);
49881cb0ef41Sopenharmony_ci  } else {
49891cb0ef41Sopenharmony_ci    DCHECK(IsEnabled(NEON));
49901cb0ef41Sopenharmony_ci    // vuzp.<size>(Dn, Dm) SIMD un-zip (de-interleave).
49911cb0ef41Sopenharmony_ci    // Instruction details available in ARM DDI 0406C.b, A8-1100.
49921cb0ef41Sopenharmony_ci    emit(EncodeNeonUnaryOp(VUZP, NEON_D, size, src1.code(), src2.code()));
49931cb0ef41Sopenharmony_ci  }
49941cb0ef41Sopenharmony_ci}
49951cb0ef41Sopenharmony_ci
49961cb0ef41Sopenharmony_civoid Assembler::vuzp(NeonSize size, QwNeonRegister src1, QwNeonRegister src2) {
49971cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
49981cb0ef41Sopenharmony_ci  // vuzp.<size>(Qn, Qm) SIMD un-zip (de-interleave).
49991cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-1100.
50001cb0ef41Sopenharmony_ci  emit(EncodeNeonUnaryOp(VUZP, NEON_Q, size, src1.code(), src2.code()));
50011cb0ef41Sopenharmony_ci}
50021cb0ef41Sopenharmony_ci
50031cb0ef41Sopenharmony_civoid Assembler::vrev16(NeonSize size, QwNeonRegister dst, QwNeonRegister src) {
50041cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
50051cb0ef41Sopenharmony_ci  // Qd = vrev16.<size>(Qm) SIMD element reverse.
50061cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-1028.
50071cb0ef41Sopenharmony_ci  emit(EncodeNeonUnaryOp(VREV16, NEON_Q, size, dst.code(), src.code()));
50081cb0ef41Sopenharmony_ci}
50091cb0ef41Sopenharmony_ci
50101cb0ef41Sopenharmony_civoid Assembler::vrev32(NeonSize size, QwNeonRegister dst, QwNeonRegister src) {
50111cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
50121cb0ef41Sopenharmony_ci  // Qd = vrev32.<size>(Qm) SIMD element reverse.
50131cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-1028.
50141cb0ef41Sopenharmony_ci  emit(EncodeNeonUnaryOp(VREV32, NEON_Q, size, dst.code(), src.code()));
50151cb0ef41Sopenharmony_ci}
50161cb0ef41Sopenharmony_ci
50171cb0ef41Sopenharmony_civoid Assembler::vrev64(NeonSize size, QwNeonRegister dst, QwNeonRegister src) {
50181cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
50191cb0ef41Sopenharmony_ci  // Qd = vrev64.<size>(Qm) SIMD element reverse.
50201cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-1028.
50211cb0ef41Sopenharmony_ci  emit(EncodeNeonUnaryOp(VREV64, NEON_Q, size, dst.code(), src.code()));
50221cb0ef41Sopenharmony_ci}
50231cb0ef41Sopenharmony_ci
50241cb0ef41Sopenharmony_civoid Assembler::vtrn(NeonSize size, DwVfpRegister src1, DwVfpRegister src2) {
50251cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
50261cb0ef41Sopenharmony_ci  // vtrn.<size>(Dn, Dm) SIMD element transpose.
50271cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-1096.
50281cb0ef41Sopenharmony_ci  emit(EncodeNeonUnaryOp(VTRN, NEON_D, size, src1.code(), src2.code()));
50291cb0ef41Sopenharmony_ci}
50301cb0ef41Sopenharmony_ci
50311cb0ef41Sopenharmony_civoid Assembler::vtrn(NeonSize size, QwNeonRegister src1, QwNeonRegister src2) {
50321cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
50331cb0ef41Sopenharmony_ci  // vtrn.<size>(Qn, Qm) SIMD element transpose.
50341cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-1096.
50351cb0ef41Sopenharmony_ci  emit(EncodeNeonUnaryOp(VTRN, NEON_Q, size, src1.code(), src2.code()));
50361cb0ef41Sopenharmony_ci}
50371cb0ef41Sopenharmony_ci
50381cb0ef41Sopenharmony_civoid Assembler::vpadal(NeonDataType dt, QwNeonRegister dst,
50391cb0ef41Sopenharmony_ci                       QwNeonRegister src) {
50401cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
50411cb0ef41Sopenharmony_ci  // vpadal.<dt>(Qd, Qm) SIMD Vector Pairwise Add and Accumulate Long
50421cb0ef41Sopenharmony_ci  emit(EncodeNeonUnaryOp(NeonU(dt) ? VPADAL_U : VPADAL_S, NEON_Q,
50431cb0ef41Sopenharmony_ci                         NeonDataTypeToSize(dt), dst.code(), src.code()));
50441cb0ef41Sopenharmony_ci}
50451cb0ef41Sopenharmony_ci
50461cb0ef41Sopenharmony_civoid Assembler::vpaddl(NeonDataType dt, QwNeonRegister dst,
50471cb0ef41Sopenharmony_ci                       QwNeonRegister src) {
50481cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
50491cb0ef41Sopenharmony_ci  // vpaddl.<dt>(Qd, Qm) SIMD Vector Pairwise Add Long.
50501cb0ef41Sopenharmony_ci  emit(EncodeNeonUnaryOp(NeonU(dt) ? VPADDL_U : VPADDL_S, NEON_Q,
50511cb0ef41Sopenharmony_ci                         NeonDataTypeToSize(dt), dst.code(), src.code()));
50521cb0ef41Sopenharmony_ci}
50531cb0ef41Sopenharmony_ci
50541cb0ef41Sopenharmony_civoid Assembler::vqrdmulh(NeonDataType dt, QwNeonRegister dst,
50551cb0ef41Sopenharmony_ci                         QwNeonRegister src1, QwNeonRegister src2) {
50561cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
50571cb0ef41Sopenharmony_ci  DCHECK(dt == NeonS16 || dt == NeonS32);
50581cb0ef41Sopenharmony_ci  emit(EncodeNeonBinOp(VQRDMULH, dt, dst, src1, src2));
50591cb0ef41Sopenharmony_ci}
50601cb0ef41Sopenharmony_ci
50611cb0ef41Sopenharmony_civoid Assembler::vcnt(QwNeonRegister dst, QwNeonRegister src) {
50621cb0ef41Sopenharmony_ci  // Qd = vcnt(Qm) SIMD Vector Count Set Bits.
50631cb0ef41Sopenharmony_ci  // Instruction details available at ARM DDI 0487F.b, F6-5094.
50641cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
50651cb0ef41Sopenharmony_ci  emit(EncodeNeonUnaryOp(VCNT, NEON_Q, Neon8, dst.code(), src.code()));
50661cb0ef41Sopenharmony_ci}
50671cb0ef41Sopenharmony_ci
50681cb0ef41Sopenharmony_ci// Encode NEON vtbl / vtbx instruction.
50691cb0ef41Sopenharmony_cistatic Instr EncodeNeonVTB(DwVfpRegister dst, const NeonListOperand& list,
50701cb0ef41Sopenharmony_ci                           DwVfpRegister index, bool vtbx) {
50711cb0ef41Sopenharmony_ci  // Dd = vtbl(table, Dm) SIMD vector permute, zero at out of range indices.
50721cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-1094.
50731cb0ef41Sopenharmony_ci  // Dd = vtbx(table, Dm) SIMD vector permute, skip out of range indices.
50741cb0ef41Sopenharmony_ci  // Instruction details available in ARM DDI 0406C.b, A8-1094.
50751cb0ef41Sopenharmony_ci  int vd, d;
50761cb0ef41Sopenharmony_ci  dst.split_code(&vd, &d);
50771cb0ef41Sopenharmony_ci  int vn, n;
50781cb0ef41Sopenharmony_ci  list.base().split_code(&vn, &n);
50791cb0ef41Sopenharmony_ci  int vm, m;
50801cb0ef41Sopenharmony_ci  index.split_code(&vm, &m);
50811cb0ef41Sopenharmony_ci  int op = vtbx ? 1 : 0;  // vtbl = 0, vtbx = 1.
50821cb0ef41Sopenharmony_ci  return 0x1E7U * B23 | d * B22 | 0x3 * B20 | vn * B16 | vd * B12 | 0x2 * B10 |
50831cb0ef41Sopenharmony_ci         list.length() * B8 | n * B7 | op * B6 | m * B5 | vm;
50841cb0ef41Sopenharmony_ci}
50851cb0ef41Sopenharmony_ci
50861cb0ef41Sopenharmony_civoid Assembler::vtbl(DwVfpRegister dst, const NeonListOperand& list,
50871cb0ef41Sopenharmony_ci                     DwVfpRegister index) {
50881cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
50891cb0ef41Sopenharmony_ci  emit(EncodeNeonVTB(dst, list, index, false));
50901cb0ef41Sopenharmony_ci}
50911cb0ef41Sopenharmony_ci
50921cb0ef41Sopenharmony_civoid Assembler::vtbx(DwVfpRegister dst, const NeonListOperand& list,
50931cb0ef41Sopenharmony_ci                     DwVfpRegister index) {
50941cb0ef41Sopenharmony_ci  DCHECK(IsEnabled(NEON));
50951cb0ef41Sopenharmony_ci  emit(EncodeNeonVTB(dst, list, index, true));
50961cb0ef41Sopenharmony_ci}
50971cb0ef41Sopenharmony_ci
50981cb0ef41Sopenharmony_ci// Pseudo instructions.
50991cb0ef41Sopenharmony_civoid Assembler::nop(int type) {
51001cb0ef41Sopenharmony_ci  // ARMv6{K/T2} and v7 have an actual NOP instruction but it serializes
51011cb0ef41Sopenharmony_ci  // some of the CPU's pipeline and has to issue. Older ARM chips simply used
51021cb0ef41Sopenharmony_ci  // MOV Rx, Rx as NOP and it performs better even in newer CPUs.
51031cb0ef41Sopenharmony_ci  // We therefore use MOV Rx, Rx, even on newer CPUs, and use Rx to encode
51041cb0ef41Sopenharmony_ci  // a type.
51051cb0ef41Sopenharmony_ci  DCHECK(0 <= type && type <= 14);  // mov pc, pc isn't a nop.
51061cb0ef41Sopenharmony_ci  emit(al | 13 * B21 | type * B12 | type);
51071cb0ef41Sopenharmony_ci}
51081cb0ef41Sopenharmony_ci
51091cb0ef41Sopenharmony_civoid Assembler::pop() { add(sp, sp, Operand(kPointerSize)); }
51101cb0ef41Sopenharmony_ci
51111cb0ef41Sopenharmony_cibool Assembler::IsMovT(Instr instr) {
51121cb0ef41Sopenharmony_ci  instr &= ~(((kNumberOfConditions - 1) << 28) |  // Mask off conditions
51131cb0ef41Sopenharmony_ci             ((kNumRegisters - 1) * B12) |        // mask out register
51141cb0ef41Sopenharmony_ci             EncodeMovwImmediate(0xFFFF));        // mask out immediate value
51151cb0ef41Sopenharmony_ci  return instr == kMovtPattern;
51161cb0ef41Sopenharmony_ci}
51171cb0ef41Sopenharmony_ci
51181cb0ef41Sopenharmony_cibool Assembler::IsMovW(Instr instr) {
51191cb0ef41Sopenharmony_ci  instr &= ~(((kNumberOfConditions - 1) << 28) |  // Mask off conditions
51201cb0ef41Sopenharmony_ci             ((kNumRegisters - 1) * B12) |        // mask out destination
51211cb0ef41Sopenharmony_ci             EncodeMovwImmediate(0xFFFF));        // mask out immediate value
51221cb0ef41Sopenharmony_ci  return instr == kMovwPattern;
51231cb0ef41Sopenharmony_ci}
51241cb0ef41Sopenharmony_ci
51251cb0ef41Sopenharmony_ciInstr Assembler::GetMovTPattern() { return kMovtPattern; }
51261cb0ef41Sopenharmony_ci
51271cb0ef41Sopenharmony_ciInstr Assembler::GetMovWPattern() { return kMovwPattern; }
51281cb0ef41Sopenharmony_ci
51291cb0ef41Sopenharmony_ciInstr Assembler::EncodeMovwImmediate(uint32_t immediate) {
51301cb0ef41Sopenharmony_ci  DCHECK_LT(immediate, 0x10000);
51311cb0ef41Sopenharmony_ci  return ((immediate & 0xF000) << 4) | (immediate & 0xFFF);
51321cb0ef41Sopenharmony_ci}
51331cb0ef41Sopenharmony_ci
51341cb0ef41Sopenharmony_ciInstr Assembler::PatchMovwImmediate(Instr instruction, uint32_t immediate) {
51351cb0ef41Sopenharmony_ci  instruction &= ~EncodeMovwImmediate(0xFFFF);
51361cb0ef41Sopenharmony_ci  return instruction | EncodeMovwImmediate(immediate);
51371cb0ef41Sopenharmony_ci}
51381cb0ef41Sopenharmony_ci
51391cb0ef41Sopenharmony_ciint Assembler::DecodeShiftImm(Instr instr) {
51401cb0ef41Sopenharmony_ci  int rotate = Instruction::RotateValue(instr) * 2;
51411cb0ef41Sopenharmony_ci  int immed8 = Instruction::Immed8Value(instr);
51421cb0ef41Sopenharmony_ci  return base::bits::RotateRight32(immed8, rotate);
51431cb0ef41Sopenharmony_ci}
51441cb0ef41Sopenharmony_ci
51451cb0ef41Sopenharmony_ciInstr Assembler::PatchShiftImm(Instr instr, int immed) {
51461cb0ef41Sopenharmony_ci  uint32_t rotate_imm = 0;
51471cb0ef41Sopenharmony_ci  uint32_t immed_8 = 0;
51481cb0ef41Sopenharmony_ci  bool immed_fits = FitsShifter(immed, &rotate_imm, &immed_8, nullptr);
51491cb0ef41Sopenharmony_ci  DCHECK(immed_fits);
51501cb0ef41Sopenharmony_ci  USE(immed_fits);
51511cb0ef41Sopenharmony_ci  return (instr & ~kOff12Mask) | (rotate_imm << 8) | immed_8;
51521cb0ef41Sopenharmony_ci}
51531cb0ef41Sopenharmony_ci
51541cb0ef41Sopenharmony_cibool Assembler::IsNop(Instr instr, int type) {
51551cb0ef41Sopenharmony_ci  DCHECK(0 <= type && type <= 14);  // mov pc, pc isn't a nop.
51561cb0ef41Sopenharmony_ci  // Check for mov rx, rx where x = type.
51571cb0ef41Sopenharmony_ci  return instr == (al | 13 * B21 | type * B12 | type);
51581cb0ef41Sopenharmony_ci}
51591cb0ef41Sopenharmony_ci
51601cb0ef41Sopenharmony_cibool Assembler::IsMovImmed(Instr instr) {
51611cb0ef41Sopenharmony_ci  return (instr & kMovImmedMask) == kMovImmedPattern;
51621cb0ef41Sopenharmony_ci}
51631cb0ef41Sopenharmony_ci
51641cb0ef41Sopenharmony_cibool Assembler::IsOrrImmed(Instr instr) {
51651cb0ef41Sopenharmony_ci  return (instr & kOrrImmedMask) == kOrrImmedPattern;
51661cb0ef41Sopenharmony_ci}
51671cb0ef41Sopenharmony_ci
51681cb0ef41Sopenharmony_ci// static
51691cb0ef41Sopenharmony_cibool Assembler::ImmediateFitsAddrMode1Instruction(int32_t imm32) {
51701cb0ef41Sopenharmony_ci  uint32_t dummy1;
51711cb0ef41Sopenharmony_ci  uint32_t dummy2;
51721cb0ef41Sopenharmony_ci  return FitsShifter(imm32, &dummy1, &dummy2, nullptr);
51731cb0ef41Sopenharmony_ci}
51741cb0ef41Sopenharmony_ci
51751cb0ef41Sopenharmony_cibool Assembler::ImmediateFitsAddrMode2Instruction(int32_t imm32) {
51761cb0ef41Sopenharmony_ci  return is_uint12(abs(imm32));
51771cb0ef41Sopenharmony_ci}
51781cb0ef41Sopenharmony_ci
51791cb0ef41Sopenharmony_ci// Debugging.
51801cb0ef41Sopenharmony_civoid Assembler::RecordConstPool(int size) {
51811cb0ef41Sopenharmony_ci  // We only need this for debugger support, to correctly compute offsets in the
51821cb0ef41Sopenharmony_ci  // code.
51831cb0ef41Sopenharmony_ci  RecordRelocInfo(RelocInfo::CONST_POOL, static_cast<intptr_t>(size));
51841cb0ef41Sopenharmony_ci}
51851cb0ef41Sopenharmony_ci
51861cb0ef41Sopenharmony_civoid Assembler::GrowBuffer() {
51871cb0ef41Sopenharmony_ci  DCHECK_EQ(buffer_start_, buffer_->start());
51881cb0ef41Sopenharmony_ci
51891cb0ef41Sopenharmony_ci  // Compute new buffer size.
51901cb0ef41Sopenharmony_ci  int old_size = buffer_->size();
51911cb0ef41Sopenharmony_ci  int new_size = std::min(2 * old_size, old_size + 1 * MB);
51921cb0ef41Sopenharmony_ci
51931cb0ef41Sopenharmony_ci  // Some internal data structures overflow for very large buffers,
51941cb0ef41Sopenharmony_ci  // they must ensure that kMaximalBufferSize is not too large.
51951cb0ef41Sopenharmony_ci  if (new_size > kMaximalBufferSize) {
51961cb0ef41Sopenharmony_ci    V8::FatalProcessOutOfMemory(nullptr, "Assembler::GrowBuffer");
51971cb0ef41Sopenharmony_ci  }
51981cb0ef41Sopenharmony_ci
51991cb0ef41Sopenharmony_ci  // Set up new buffer.
52001cb0ef41Sopenharmony_ci  std::unique_ptr<AssemblerBuffer> new_buffer = buffer_->Grow(new_size);
52011cb0ef41Sopenharmony_ci  DCHECK_EQ(new_size, new_buffer->size());
52021cb0ef41Sopenharmony_ci  byte* new_start = new_buffer->start();
52031cb0ef41Sopenharmony_ci
52041cb0ef41Sopenharmony_ci  // Copy the data.
52051cb0ef41Sopenharmony_ci  int pc_delta = new_start - buffer_start_;
52061cb0ef41Sopenharmony_ci  int rc_delta = (new_start + new_size) - (buffer_start_ + old_size);
52071cb0ef41Sopenharmony_ci  size_t reloc_size = (buffer_start_ + old_size) - reloc_info_writer.pos();
52081cb0ef41Sopenharmony_ci  MemMove(new_start, buffer_start_, pc_offset());
52091cb0ef41Sopenharmony_ci  byte* new_reloc_start = reinterpret_cast<byte*>(
52101cb0ef41Sopenharmony_ci      reinterpret_cast<Address>(reloc_info_writer.pos()) + rc_delta);
52111cb0ef41Sopenharmony_ci  MemMove(new_reloc_start, reloc_info_writer.pos(), reloc_size);
52121cb0ef41Sopenharmony_ci
52131cb0ef41Sopenharmony_ci  // Switch buffers.
52141cb0ef41Sopenharmony_ci  buffer_ = std::move(new_buffer);
52151cb0ef41Sopenharmony_ci  buffer_start_ = new_start;
52161cb0ef41Sopenharmony_ci  pc_ = reinterpret_cast<byte*>(reinterpret_cast<Address>(pc_) + pc_delta);
52171cb0ef41Sopenharmony_ci  byte* new_last_pc = reinterpret_cast<byte*>(
52181cb0ef41Sopenharmony_ci      reinterpret_cast<Address>(reloc_info_writer.last_pc()) + pc_delta);
52191cb0ef41Sopenharmony_ci  reloc_info_writer.Reposition(new_reloc_start, new_last_pc);
52201cb0ef41Sopenharmony_ci
52211cb0ef41Sopenharmony_ci  // None of our relocation types are pc relative pointing outside the code
52221cb0ef41Sopenharmony_ci  // buffer nor pc absolute pointing inside the code buffer, so there is no need
52231cb0ef41Sopenharmony_ci  // to relocate any emitted relocation entries.
52241cb0ef41Sopenharmony_ci}
52251cb0ef41Sopenharmony_ci
52261cb0ef41Sopenharmony_civoid Assembler::db(uint8_t data) {
52271cb0ef41Sopenharmony_ci  // db is used to write raw data. The constant pool should be emitted or
52281cb0ef41Sopenharmony_ci  // blocked before using db.
52291cb0ef41Sopenharmony_ci  DCHECK(is_const_pool_blocked() || pending_32_bit_constants_.empty());
52301cb0ef41Sopenharmony_ci  CheckBuffer();
52311cb0ef41Sopenharmony_ci  *reinterpret_cast<uint8_t*>(pc_) = data;
52321cb0ef41Sopenharmony_ci  pc_ += sizeof(uint8_t);
52331cb0ef41Sopenharmony_ci}
52341cb0ef41Sopenharmony_ci
52351cb0ef41Sopenharmony_civoid Assembler::dd(uint32_t data, RelocInfo::Mode rmode) {
52361cb0ef41Sopenharmony_ci  // dd is used to write raw data. The constant pool should be emitted or
52371cb0ef41Sopenharmony_ci  // blocked before using dd.
52381cb0ef41Sopenharmony_ci  DCHECK(is_const_pool_blocked() || pending_32_bit_constants_.empty());
52391cb0ef41Sopenharmony_ci  CheckBuffer();
52401cb0ef41Sopenharmony_ci  if (!RelocInfo::IsNoInfo(rmode)) {
52411cb0ef41Sopenharmony_ci    DCHECK(RelocInfo::IsDataEmbeddedObject(rmode) ||
52421cb0ef41Sopenharmony_ci           RelocInfo::IsLiteralConstant(rmode));
52431cb0ef41Sopenharmony_ci    RecordRelocInfo(rmode);
52441cb0ef41Sopenharmony_ci  }
52451cb0ef41Sopenharmony_ci  base::WriteUnalignedValue(reinterpret_cast<Address>(pc_), data);
52461cb0ef41Sopenharmony_ci  pc_ += sizeof(uint32_t);
52471cb0ef41Sopenharmony_ci}
52481cb0ef41Sopenharmony_ci
52491cb0ef41Sopenharmony_civoid Assembler::dq(uint64_t value, RelocInfo::Mode rmode) {
52501cb0ef41Sopenharmony_ci  // dq is used to write raw data. The constant pool should be emitted or
52511cb0ef41Sopenharmony_ci  // blocked before using dq.
52521cb0ef41Sopenharmony_ci  DCHECK(is_const_pool_blocked() || pending_32_bit_constants_.empty());
52531cb0ef41Sopenharmony_ci  CheckBuffer();
52541cb0ef41Sopenharmony_ci  if (!RelocInfo::IsNoInfo(rmode)) {
52551cb0ef41Sopenharmony_ci    DCHECK(RelocInfo::IsDataEmbeddedObject(rmode) ||
52561cb0ef41Sopenharmony_ci           RelocInfo::IsLiteralConstant(rmode));
52571cb0ef41Sopenharmony_ci    RecordRelocInfo(rmode);
52581cb0ef41Sopenharmony_ci  }
52591cb0ef41Sopenharmony_ci  base::WriteUnalignedValue(reinterpret_cast<Address>(pc_), value);
52601cb0ef41Sopenharmony_ci  pc_ += sizeof(uint64_t);
52611cb0ef41Sopenharmony_ci}
52621cb0ef41Sopenharmony_ci
52631cb0ef41Sopenharmony_civoid Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
52641cb0ef41Sopenharmony_ci  if (!ShouldRecordRelocInfo(rmode)) return;
52651cb0ef41Sopenharmony_ci  DCHECK_GE(buffer_space(), kMaxRelocSize);  // too late to grow buffer here
52661cb0ef41Sopenharmony_ci  RelocInfo rinfo(reinterpret_cast<Address>(pc_), rmode, data, Code());
52671cb0ef41Sopenharmony_ci  reloc_info_writer.Write(&rinfo);
52681cb0ef41Sopenharmony_ci}
52691cb0ef41Sopenharmony_ci
52701cb0ef41Sopenharmony_civoid Assembler::ConstantPoolAddEntry(int position, RelocInfo::Mode rmode,
52711cb0ef41Sopenharmony_ci                                     intptr_t value) {
52721cb0ef41Sopenharmony_ci  DCHECK(rmode != RelocInfo::CONST_POOL);
52731cb0ef41Sopenharmony_ci  // We can share CODE_TARGETs and embedded objects, but we must make sure we
52741cb0ef41Sopenharmony_ci  // only emit one reloc info for them (thus delta patching will apply the delta
52751cb0ef41Sopenharmony_ci  // only once). At the moment, we do not deduplicate heap object request which
52761cb0ef41Sopenharmony_ci  // are indicated by value == 0.
52771cb0ef41Sopenharmony_ci  bool sharing_ok = RelocInfo::IsShareableRelocMode(rmode) ||
52781cb0ef41Sopenharmony_ci                    (rmode == RelocInfo::CODE_TARGET && value != 0) ||
52791cb0ef41Sopenharmony_ci                    (RelocInfo::IsEmbeddedObjectMode(rmode) && value != 0);
52801cb0ef41Sopenharmony_ci  DCHECK_LT(pending_32_bit_constants_.size(), kMaxNumPending32Constants);
52811cb0ef41Sopenharmony_ci  if (first_const_pool_32_use_ < 0) {
52821cb0ef41Sopenharmony_ci    DCHECK(pending_32_bit_constants_.empty());
52831cb0ef41Sopenharmony_ci    DCHECK_EQ(constant_pool_deadline_, kMaxInt);
52841cb0ef41Sopenharmony_ci    first_const_pool_32_use_ = position;
52851cb0ef41Sopenharmony_ci    constant_pool_deadline_ = position + kCheckPoolDeadline;
52861cb0ef41Sopenharmony_ci  } else {
52871cb0ef41Sopenharmony_ci    DCHECK(!pending_32_bit_constants_.empty());
52881cb0ef41Sopenharmony_ci  }
52891cb0ef41Sopenharmony_ci  ConstantPoolEntry entry(position, value, sharing_ok, rmode);
52901cb0ef41Sopenharmony_ci
52911cb0ef41Sopenharmony_ci  bool shared = false;
52921cb0ef41Sopenharmony_ci  if (sharing_ok) {
52931cb0ef41Sopenharmony_ci    // Merge the constant, if possible.
52941cb0ef41Sopenharmony_ci    for (size_t i = 0; i < pending_32_bit_constants_.size(); i++) {
52951cb0ef41Sopenharmony_ci      ConstantPoolEntry& current_entry = pending_32_bit_constants_[i];
52961cb0ef41Sopenharmony_ci      if (!current_entry.sharing_ok()) continue;
52971cb0ef41Sopenharmony_ci      if (entry.value() == current_entry.value() &&
52981cb0ef41Sopenharmony_ci          entry.rmode() == current_entry.rmode()) {
52991cb0ef41Sopenharmony_ci        entry.set_merged_index(i);
53001cb0ef41Sopenharmony_ci        shared = true;
53011cb0ef41Sopenharmony_ci        break;
53021cb0ef41Sopenharmony_ci      }
53031cb0ef41Sopenharmony_ci    }
53041cb0ef41Sopenharmony_ci  }
53051cb0ef41Sopenharmony_ci
53061cb0ef41Sopenharmony_ci  pending_32_bit_constants_.emplace_back(entry);
53071cb0ef41Sopenharmony_ci
53081cb0ef41Sopenharmony_ci  // Make sure the constant pool is not emitted in place of the next
53091cb0ef41Sopenharmony_ci  // instruction for which we just recorded relocation info.
53101cb0ef41Sopenharmony_ci  BlockConstPoolFor(1);
53111cb0ef41Sopenharmony_ci
53121cb0ef41Sopenharmony_ci  // Emit relocation info.
53131cb0ef41Sopenharmony_ci  if (MustOutputRelocInfo(rmode, this) && !shared) {
53141cb0ef41Sopenharmony_ci    RecordRelocInfo(rmode);
53151cb0ef41Sopenharmony_ci  }
53161cb0ef41Sopenharmony_ci}
53171cb0ef41Sopenharmony_ci
53181cb0ef41Sopenharmony_civoid Assembler::BlockConstPoolFor(int instructions) {
53191cb0ef41Sopenharmony_ci  int pc_limit = pc_offset() + instructions * kInstrSize;
53201cb0ef41Sopenharmony_ci  if (no_const_pool_before_ < pc_limit) {
53211cb0ef41Sopenharmony_ci    no_const_pool_before_ = pc_limit;
53221cb0ef41Sopenharmony_ci  }
53231cb0ef41Sopenharmony_ci
53241cb0ef41Sopenharmony_ci  // If we're due a const pool check before the block finishes, move it to just
53251cb0ef41Sopenharmony_ci  // after the block.
53261cb0ef41Sopenharmony_ci  if (constant_pool_deadline_ < no_const_pool_before_) {
53271cb0ef41Sopenharmony_ci    // Make sure that the new deadline isn't too late (including a jump and the
53281cb0ef41Sopenharmony_ci    // constant pool marker).
53291cb0ef41Sopenharmony_ci    DCHECK_LE(no_const_pool_before_,
53301cb0ef41Sopenharmony_ci              first_const_pool_32_use_ + kMaxDistToIntPool);
53311cb0ef41Sopenharmony_ci    constant_pool_deadline_ = no_const_pool_before_;
53321cb0ef41Sopenharmony_ci  }
53331cb0ef41Sopenharmony_ci}
53341cb0ef41Sopenharmony_ci
53351cb0ef41Sopenharmony_civoid Assembler::CheckConstPool(bool force_emit, bool require_jump) {
53361cb0ef41Sopenharmony_ci  // Some short sequence of instruction mustn't be broken up by constant pool
53371cb0ef41Sopenharmony_ci  // emission, such sequences are protected by calls to BlockConstPoolFor and
53381cb0ef41Sopenharmony_ci  // BlockConstPoolScope.
53391cb0ef41Sopenharmony_ci  if (is_const_pool_blocked()) {
53401cb0ef41Sopenharmony_ci    // Something is wrong if emission is forced and blocked at the same time.
53411cb0ef41Sopenharmony_ci    DCHECK(!force_emit);
53421cb0ef41Sopenharmony_ci    return;
53431cb0ef41Sopenharmony_ci  }
53441cb0ef41Sopenharmony_ci
53451cb0ef41Sopenharmony_ci  // There is nothing to do if there are no pending constant pool entries.
53461cb0ef41Sopenharmony_ci  if (pending_32_bit_constants_.empty()) {
53471cb0ef41Sopenharmony_ci    // We should only fall into this case if we're either trying to forcing
53481cb0ef41Sopenharmony_ci    // emission or opportunistically checking after a jump.
53491cb0ef41Sopenharmony_ci    DCHECK(force_emit || !require_jump);
53501cb0ef41Sopenharmony_ci    return;
53511cb0ef41Sopenharmony_ci  }
53521cb0ef41Sopenharmony_ci
53531cb0ef41Sopenharmony_ci  // We emit a constant pool when:
53541cb0ef41Sopenharmony_ci  //  * requested to do so by parameter force_emit (e.g. after each function).
53551cb0ef41Sopenharmony_ci  //  * the distance from the first instruction accessing the constant pool to
53561cb0ef41Sopenharmony_ci  //    the first constant pool entry will exceed its limit the next time the
53571cb0ef41Sopenharmony_ci  //    pool is checked.
53581cb0ef41Sopenharmony_ci  //  * the instruction doesn't require a jump after itself to jump over the
53591cb0ef41Sopenharmony_ci  //    constant pool, and we're getting close to running out of range.
53601cb0ef41Sopenharmony_ci  if (!force_emit) {
53611cb0ef41Sopenharmony_ci    DCHECK_NE(first_const_pool_32_use_, -1);
53621cb0ef41Sopenharmony_ci    int dist32 = pc_offset() - first_const_pool_32_use_;
53631cb0ef41Sopenharmony_ci    if (require_jump) {
53641cb0ef41Sopenharmony_ci      // We should only be on this path if we've exceeded our deadline.
53651cb0ef41Sopenharmony_ci      DCHECK_GE(dist32, kCheckPoolDeadline);
53661cb0ef41Sopenharmony_ci    } else if (dist32 < kCheckPoolDeadline / 2) {
53671cb0ef41Sopenharmony_ci      return;
53681cb0ef41Sopenharmony_ci    }
53691cb0ef41Sopenharmony_ci  }
53701cb0ef41Sopenharmony_ci
53711cb0ef41Sopenharmony_ci  int size_after_marker = pending_32_bit_constants_.size() * kPointerSize;
53721cb0ef41Sopenharmony_ci
53731cb0ef41Sopenharmony_ci  // Deduplicate constants.
53741cb0ef41Sopenharmony_ci  for (size_t i = 0; i < pending_32_bit_constants_.size(); i++) {
53751cb0ef41Sopenharmony_ci    ConstantPoolEntry& entry = pending_32_bit_constants_[i];
53761cb0ef41Sopenharmony_ci    if (entry.is_merged()) size_after_marker -= kPointerSize;
53771cb0ef41Sopenharmony_ci  }
53781cb0ef41Sopenharmony_ci
53791cb0ef41Sopenharmony_ci  // Check that the code buffer is large enough before emitting the constant
53801cb0ef41Sopenharmony_ci  // pool (include the jump over the pool and the constant pool marker and
53811cb0ef41Sopenharmony_ci  // the gap to the relocation information).
53821cb0ef41Sopenharmony_ci  int jump_instr = require_jump ? kInstrSize : 0;
53831cb0ef41Sopenharmony_ci  int size_up_to_marker = jump_instr + kInstrSize;
53841cb0ef41Sopenharmony_ci  int size = size_up_to_marker + size_after_marker;
53851cb0ef41Sopenharmony_ci  int needed_space = size + kGap;
53861cb0ef41Sopenharmony_ci  while (buffer_space() <= needed_space) GrowBuffer();
53871cb0ef41Sopenharmony_ci
53881cb0ef41Sopenharmony_ci  {
53891cb0ef41Sopenharmony_ci    ASM_CODE_COMMENT_STRING(this, "Constant Pool");
53901cb0ef41Sopenharmony_ci    // Block recursive calls to CheckConstPool.
53911cb0ef41Sopenharmony_ci    BlockConstPoolScope block_const_pool(this);
53921cb0ef41Sopenharmony_ci    RecordConstPool(size);
53931cb0ef41Sopenharmony_ci
53941cb0ef41Sopenharmony_ci    Label size_check;
53951cb0ef41Sopenharmony_ci    bind(&size_check);
53961cb0ef41Sopenharmony_ci
53971cb0ef41Sopenharmony_ci    // Emit jump over constant pool if necessary.
53981cb0ef41Sopenharmony_ci    Label after_pool;
53991cb0ef41Sopenharmony_ci    if (require_jump) {
54001cb0ef41Sopenharmony_ci      b(&after_pool);
54011cb0ef41Sopenharmony_ci    }
54021cb0ef41Sopenharmony_ci
54031cb0ef41Sopenharmony_ci    // Put down constant pool marker "Undefined instruction".
54041cb0ef41Sopenharmony_ci    // The data size helps disassembly know what to print.
54051cb0ef41Sopenharmony_ci    emit(kConstantPoolMarker |
54061cb0ef41Sopenharmony_ci         EncodeConstantPoolLength(size_after_marker / kPointerSize));
54071cb0ef41Sopenharmony_ci
54081cb0ef41Sopenharmony_ci    // The first entry in the constant pool should also be the first
54091cb0ef41Sopenharmony_ci    CHECK_EQ(first_const_pool_32_use_, pending_32_bit_constants_[0].position());
54101cb0ef41Sopenharmony_ci    CHECK(!pending_32_bit_constants_[0].is_merged());
54111cb0ef41Sopenharmony_ci
54121cb0ef41Sopenharmony_ci    // Make sure we're not emitting the constant too late.
54131cb0ef41Sopenharmony_ci    CHECK_LE(pc_offset(),
54141cb0ef41Sopenharmony_ci             first_const_pool_32_use_ + kMaxDistToPcRelativeConstant);
54151cb0ef41Sopenharmony_ci
54161cb0ef41Sopenharmony_ci    // Check that the code buffer is large enough before emitting the constant
54171cb0ef41Sopenharmony_ci    // pool (this includes the gap to the relocation information).
54181cb0ef41Sopenharmony_ci    int needed_space = pending_32_bit_constants_.size() * kPointerSize + kGap;
54191cb0ef41Sopenharmony_ci    while (buffer_space() <= needed_space) {
54201cb0ef41Sopenharmony_ci      GrowBuffer();
54211cb0ef41Sopenharmony_ci    }
54221cb0ef41Sopenharmony_ci
54231cb0ef41Sopenharmony_ci    // Emit 32-bit constant pool entries.
54241cb0ef41Sopenharmony_ci    for (size_t i = 0; i < pending_32_bit_constants_.size(); i++) {
54251cb0ef41Sopenharmony_ci      ConstantPoolEntry& entry = pending_32_bit_constants_[i];
54261cb0ef41Sopenharmony_ci      Instr instr = instr_at(entry.position());
54271cb0ef41Sopenharmony_ci
54281cb0ef41Sopenharmony_ci      // 64-bit loads shouldn't get here.
54291cb0ef41Sopenharmony_ci      DCHECK(!IsVldrDPcImmediateOffset(instr));
54301cb0ef41Sopenharmony_ci      DCHECK(!IsMovW(instr));
54311cb0ef41Sopenharmony_ci      DCHECK(IsLdrPcImmediateOffset(instr) &&
54321cb0ef41Sopenharmony_ci             GetLdrRegisterImmediateOffset(instr) == 0);
54331cb0ef41Sopenharmony_ci
54341cb0ef41Sopenharmony_ci      int delta = pc_offset() - entry.position() - Instruction::kPcLoadDelta;
54351cb0ef41Sopenharmony_ci      DCHECK(is_uint12(delta));
54361cb0ef41Sopenharmony_ci      // 0 is the smallest delta:
54371cb0ef41Sopenharmony_ci      //   ldr rd, [pc, #0]
54381cb0ef41Sopenharmony_ci      //   constant pool marker
54391cb0ef41Sopenharmony_ci      //   data
54401cb0ef41Sopenharmony_ci
54411cb0ef41Sopenharmony_ci      if (entry.is_merged()) {
54421cb0ef41Sopenharmony_ci        DCHECK(entry.sharing_ok());
54431cb0ef41Sopenharmony_ci        ConstantPoolEntry& merged =
54441cb0ef41Sopenharmony_ci            pending_32_bit_constants_[entry.merged_index()];
54451cb0ef41Sopenharmony_ci        DCHECK(entry.value() == merged.value());
54461cb0ef41Sopenharmony_ci        DCHECK_LT(merged.position(), entry.position());
54471cb0ef41Sopenharmony_ci        Instr merged_instr = instr_at(merged.position());
54481cb0ef41Sopenharmony_ci        DCHECK(IsLdrPcImmediateOffset(merged_instr));
54491cb0ef41Sopenharmony_ci        delta = GetLdrRegisterImmediateOffset(merged_instr);
54501cb0ef41Sopenharmony_ci        delta += merged.position() - entry.position();
54511cb0ef41Sopenharmony_ci      }
54521cb0ef41Sopenharmony_ci      instr_at_put(entry.position(),
54531cb0ef41Sopenharmony_ci                   SetLdrRegisterImmediateOffset(instr, delta));
54541cb0ef41Sopenharmony_ci      if (!entry.is_merged()) {
54551cb0ef41Sopenharmony_ci        emit(entry.value());
54561cb0ef41Sopenharmony_ci      }
54571cb0ef41Sopenharmony_ci    }
54581cb0ef41Sopenharmony_ci
54591cb0ef41Sopenharmony_ci    pending_32_bit_constants_.clear();
54601cb0ef41Sopenharmony_ci
54611cb0ef41Sopenharmony_ci    first_const_pool_32_use_ = -1;
54621cb0ef41Sopenharmony_ci
54631cb0ef41Sopenharmony_ci    DCHECK_EQ(size, SizeOfCodeGeneratedSince(&size_check));
54641cb0ef41Sopenharmony_ci
54651cb0ef41Sopenharmony_ci    if (after_pool.is_linked()) {
54661cb0ef41Sopenharmony_ci      bind(&after_pool);
54671cb0ef41Sopenharmony_ci    }
54681cb0ef41Sopenharmony_ci  }
54691cb0ef41Sopenharmony_ci
54701cb0ef41Sopenharmony_ci  // Since a constant pool was just emitted, we don't need another check until
54711cb0ef41Sopenharmony_ci  // the next constant pool entry is added.
54721cb0ef41Sopenharmony_ci  constant_pool_deadline_ = kMaxInt;
54731cb0ef41Sopenharmony_ci}
54741cb0ef41Sopenharmony_ci
54751cb0ef41Sopenharmony_ciPatchingAssembler::PatchingAssembler(const AssemblerOptions& options,
54761cb0ef41Sopenharmony_ci                                     byte* address, int instructions)
54771cb0ef41Sopenharmony_ci    : Assembler(options, ExternalAssemblerBuffer(
54781cb0ef41Sopenharmony_ci                             address, instructions * kInstrSize + kGap)) {
54791cb0ef41Sopenharmony_ci  DCHECK_EQ(reloc_info_writer.pos(), buffer_start_ + buffer_->size());
54801cb0ef41Sopenharmony_ci}
54811cb0ef41Sopenharmony_ci
54821cb0ef41Sopenharmony_ciPatchingAssembler::~PatchingAssembler() {
54831cb0ef41Sopenharmony_ci  // Check that we don't have any pending constant pools.
54841cb0ef41Sopenharmony_ci  DCHECK(pending_32_bit_constants_.empty());
54851cb0ef41Sopenharmony_ci
54861cb0ef41Sopenharmony_ci  // Check that the code was patched as expected.
54871cb0ef41Sopenharmony_ci  DCHECK_EQ(pc_, buffer_start_ + buffer_->size() - kGap);
54881cb0ef41Sopenharmony_ci  DCHECK_EQ(reloc_info_writer.pos(), buffer_start_ + buffer_->size());
54891cb0ef41Sopenharmony_ci}
54901cb0ef41Sopenharmony_ci
54911cb0ef41Sopenharmony_civoid PatchingAssembler::Emit(Address addr) { emit(static_cast<Instr>(addr)); }
54921cb0ef41Sopenharmony_ci
54931cb0ef41Sopenharmony_civoid PatchingAssembler::PadWithNops() {
54941cb0ef41Sopenharmony_ci  DCHECK_LE(pc_, buffer_start_ + buffer_->size() - kGap);
54951cb0ef41Sopenharmony_ci  while (pc_ < buffer_start_ + buffer_->size() - kGap) {
54961cb0ef41Sopenharmony_ci    nop();
54971cb0ef41Sopenharmony_ci  }
54981cb0ef41Sopenharmony_ci}
54991cb0ef41Sopenharmony_ci
55001cb0ef41Sopenharmony_ciUseScratchRegisterScope::UseScratchRegisterScope(Assembler* assembler)
55011cb0ef41Sopenharmony_ci    : assembler_(assembler),
55021cb0ef41Sopenharmony_ci      old_available_(*assembler->GetScratchRegisterList()),
55031cb0ef41Sopenharmony_ci      old_available_vfp_(*assembler->GetScratchVfpRegisterList()) {}
55041cb0ef41Sopenharmony_ci
55051cb0ef41Sopenharmony_ciUseScratchRegisterScope::~UseScratchRegisterScope() {
55061cb0ef41Sopenharmony_ci  *assembler_->GetScratchRegisterList() = old_available_;
55071cb0ef41Sopenharmony_ci  *assembler_->GetScratchVfpRegisterList() = old_available_vfp_;
55081cb0ef41Sopenharmony_ci}
55091cb0ef41Sopenharmony_ci
55101cb0ef41Sopenharmony_ciRegister UseScratchRegisterScope::Acquire() {
55111cb0ef41Sopenharmony_ci  RegList* available = assembler_->GetScratchRegisterList();
55121cb0ef41Sopenharmony_ci  DCHECK_NOT_NULL(available);
55131cb0ef41Sopenharmony_ci  return available->PopFirst();
55141cb0ef41Sopenharmony_ci}
55151cb0ef41Sopenharmony_ci
55161cb0ef41Sopenharmony_ciLoadStoreLaneParams::LoadStoreLaneParams(MachineRepresentation rep,
55171cb0ef41Sopenharmony_ci                                         uint8_t laneidx) {
55181cb0ef41Sopenharmony_ci  if (rep == MachineRepresentation::kWord8) {
55191cb0ef41Sopenharmony_ci    *this = LoadStoreLaneParams(laneidx, Neon8, 8);
55201cb0ef41Sopenharmony_ci  } else if (rep == MachineRepresentation::kWord16) {
55211cb0ef41Sopenharmony_ci    *this = LoadStoreLaneParams(laneidx, Neon16, 4);
55221cb0ef41Sopenharmony_ci  } else if (rep == MachineRepresentation::kWord32) {
55231cb0ef41Sopenharmony_ci    *this = LoadStoreLaneParams(laneidx, Neon32, 2);
55241cb0ef41Sopenharmony_ci  } else if (rep == MachineRepresentation::kWord64) {
55251cb0ef41Sopenharmony_ci    *this = LoadStoreLaneParams(laneidx, Neon64, 1);
55261cb0ef41Sopenharmony_ci  } else {
55271cb0ef41Sopenharmony_ci    UNREACHABLE();
55281cb0ef41Sopenharmony_ci  }
55291cb0ef41Sopenharmony_ci}
55301cb0ef41Sopenharmony_ci
55311cb0ef41Sopenharmony_ci}  // namespace internal
55321cb0ef41Sopenharmony_ci}  // namespace v8
55331cb0ef41Sopenharmony_ci
55341cb0ef41Sopenharmony_ci#endif  // V8_TARGET_ARCH_ARM
5535