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