1a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Copyright (c) 1994-2006 Sun Microsystems Inc.
2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// All Rights Reserved.
3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without
5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions
6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// are met:
7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// - Redistributions of source code must retain the above copyright notice,
9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// this list of conditions and the following disclaimer.
10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// - Redistribution in binary form must reproduce the above copyright
12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// notice, this list of conditions and the following disclaimer in the
13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// documentation and/or other materials provided with the
14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// distribution.
15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// - Neither the name of Sun Microsystems or the names of contributors may
17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// be used to endorse or promote products derived from this software without
18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// specific prior written permission.
19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THE POSSIBILITY OF SUCH DAMAGE.
32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
33d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// The original source code covered by the above license above has been
34d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// modified significantly by Google Inc.
35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved.
36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
37014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/arm/assembler-arm.h"
38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if V8_TARGET_ARCH_ARM
40f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/arm/assembler-arm-inl.h"
42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/base/bits.h"
43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/base/cpu.h"
44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/macro-assembler.h"
45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 {
47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal {
48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
49f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochstatic const unsigned kArmv6 = 0u;
50f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochstatic const unsigned kArmv7 = kArmv6 | (1u << ARMv7);
51f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochstatic const unsigned kArmv7WithSudiv = kArmv7 | (1u << ARMv7_SUDIV);
52f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochstatic const unsigned kArmv8 = kArmv7WithSudiv | (1u << ARMv8);
53f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
54f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochstatic unsigned CpuFeaturesFromCommandLine() {
55f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  unsigned result;
56f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  if (strcmp(FLAG_arm_arch, "armv8") == 0) {
57f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    result = kArmv8;
58f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  } else if (strcmp(FLAG_arm_arch, "armv7+sudiv") == 0) {
59f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    result = kArmv7WithSudiv;
60f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  } else if (strcmp(FLAG_arm_arch, "armv7") == 0) {
61f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    result = kArmv7;
62f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  } else if (strcmp(FLAG_arm_arch, "armv6") == 0) {
63f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    result = kArmv6;
64f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  } else {
65f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    fprintf(stderr, "Error: unrecognised value for --arm-arch ('%s').\n",
66f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            FLAG_arm_arch);
67f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    fprintf(stderr,
68f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            "Supported values are:  armv8\n"
69f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            "                       armv7+sudiv\n"
70f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            "                       armv7\n"
71f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            "                       armv6\n");
72f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    CHECK(false);
73f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  }
74f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
75f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // If any of the old (deprecated) flags are specified, print a warning, but
76f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // otherwise try to respect them for now.
77f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // TODO(jbramley): When all the old bots have been updated, remove this.
78f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  if (FLAG_enable_armv7.has_value || FLAG_enable_vfp3.has_value ||
79f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      FLAG_enable_32dregs.has_value || FLAG_enable_neon.has_value ||
80f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      FLAG_enable_sudiv.has_value || FLAG_enable_armv8.has_value) {
81f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    // As an approximation of the old behaviour, set the default values from the
82f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    // arm_arch setting, then apply the flags over the top.
83f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    bool enable_armv7 = (result & (1u << ARMv7)) != 0;
84f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    bool enable_vfp3 = (result & (1u << ARMv7)) != 0;
85f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    bool enable_32dregs = (result & (1u << ARMv7)) != 0;
86f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    bool enable_neon = (result & (1u << ARMv7)) != 0;
87f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    bool enable_sudiv = (result & (1u << ARMv7_SUDIV)) != 0;
88f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    bool enable_armv8 = (result & (1u << ARMv8)) != 0;
89f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    if (FLAG_enable_armv7.has_value) {
90f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      fprintf(stderr,
91f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch              "Warning: --enable_armv7 is deprecated. "
92f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch              "Use --arm_arch instead.\n");
93f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      enable_armv7 = FLAG_enable_armv7.value;
94f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    }
95f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    if (FLAG_enable_vfp3.has_value) {
96f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      fprintf(stderr,
97f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch              "Warning: --enable_vfp3 is deprecated. "
98f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch              "Use --arm_arch instead.\n");
99f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      enable_vfp3 = FLAG_enable_vfp3.value;
100f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    }
101f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    if (FLAG_enable_32dregs.has_value) {
102f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      fprintf(stderr,
103f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch              "Warning: --enable_32dregs is deprecated. "
104f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch              "Use --arm_arch instead.\n");
105f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      enable_32dregs = FLAG_enable_32dregs.value;
106f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    }
107f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    if (FLAG_enable_neon.has_value) {
108f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      fprintf(stderr,
109f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch              "Warning: --enable_neon is deprecated. "
110f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch              "Use --arm_arch instead.\n");
111f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      enable_neon = FLAG_enable_neon.value;
112f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    }
113f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    if (FLAG_enable_sudiv.has_value) {
114f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      fprintf(stderr,
115f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch              "Warning: --enable_sudiv is deprecated. "
116f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch              "Use --arm_arch instead.\n");
117f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      enable_sudiv = FLAG_enable_sudiv.value;
118f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    }
119f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    if (FLAG_enable_armv8.has_value) {
120f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      fprintf(stderr,
121f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch              "Warning: --enable_armv8 is deprecated. "
122f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch              "Use --arm_arch instead.\n");
123f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      enable_armv8 = FLAG_enable_armv8.value;
124f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    }
125f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    // Emulate the old implications.
126f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    if (enable_armv8) {
127f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      enable_vfp3 = true;
128f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      enable_neon = true;
129f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      enable_32dregs = true;
130f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      enable_sudiv = true;
131f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    }
132f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    // Select the best available configuration.
133f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    if (enable_armv7 && enable_vfp3 && enable_32dregs && enable_neon) {
134f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      if (enable_sudiv) {
135f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        if (enable_armv8) {
136f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch          result = kArmv8;
137f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        } else {
138f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch          result = kArmv7WithSudiv;
139f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        }
140f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      } else {
141f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        result = kArmv7;
142f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      }
143f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    } else {
144f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      result = kArmv6;
145f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    }
146014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
147f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  return result;
148f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch}
149f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
150f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch// Get the CPU features enabled by the build.
151f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch// For cross compilation the preprocessor symbols such as
152f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch// CAN_USE_ARMV7_INSTRUCTIONS and CAN_USE_VFP3_INSTRUCTIONS can be used to
153f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch// enable ARMv7 and VFPv3 instructions when building the snapshot. However,
154f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch// these flags should be consistent with a supported ARM configuration:
155f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch//  "armv6":       ARMv6 + VFPv2
156f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch//  "armv7":       ARMv7 + VFPv3-D32 + NEON
157f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch//  "armv7+sudiv": ARMv7 + VFPv4-D32 + NEON + SUDIV
158f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch//  "armv8":       ARMv8 (+ all of the above)
159f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochstatic constexpr unsigned CpuFeaturesFromCompiler() {
160f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch// TODO(jbramley): Once the build flags are simplified, these tests should
161f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch// also be simplified.
162f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
163f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch// Check *architectural* implications.
164f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#if defined(CAN_USE_ARMV8_INSTRUCTIONS) && !defined(CAN_USE_ARMV7_INSTRUCTIONS)
165f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#error "CAN_USE_ARMV8_INSTRUCTIONS should imply CAN_USE_ARMV7_INSTRUCTIONS"
166f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#endif
167f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#if defined(CAN_USE_ARMV8_INSTRUCTIONS) && !defined(CAN_USE_SUDIV)
168f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#error "CAN_USE_ARMV8_INSTRUCTIONS should imply CAN_USE_SUDIV"
169f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#endif
170f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#if defined(CAN_USE_ARMV7_INSTRUCTIONS) != defined(CAN_USE_VFP3_INSTRUCTIONS)
171f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch// V8 requires VFP, and all ARMv7 devices with VFP have VFPv3. Similarly,
172f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch// VFPv3 isn't available before ARMv7.
173f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#error "CAN_USE_ARMV7_INSTRUCTIONS should match CAN_USE_VFP3_INSTRUCTIONS"
174f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#endif
175f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#if defined(CAN_USE_NEON) && !defined(CAN_USE_ARMV7_INSTRUCTIONS)
176f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#error "CAN_USE_NEON should imply CAN_USE_ARMV7_INSTRUCTIONS"
177f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#endif
178257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
179f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch// Find compiler-implied features.
180f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#if defined(CAN_USE_ARMV8_INSTRUCTIONS) &&                           \
181f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    defined(CAN_USE_ARMV7_INSTRUCTIONS) && defined(CAN_USE_SUDIV) && \
182f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    defined(CAN_USE_NEON) && defined(CAN_USE_VFP3_INSTRUCTIONS)
183f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  return kArmv8;
184f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#elif defined(CAN_USE_ARMV7_INSTRUCTIONS) && defined(CAN_USE_SUDIV) && \
185f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    defined(CAN_USE_NEON) && defined(CAN_USE_VFP3_INSTRUCTIONS)
186f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  return kArmv7WithSudiv;
187f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#elif defined(CAN_USE_ARMV7_INSTRUCTIONS) && defined(CAN_USE_NEON) && \
188f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    defined(CAN_USE_VFP3_INSTRUCTIONS)
189f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  return kArmv7;
190f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#else
191f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  return kArmv6;
192f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#endif
193402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
194402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
195402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CpuFeatures::ProbeImpl(bool cross_compile) {
197109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  dcache_line_size_ = 64;
198257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
199f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  unsigned command_line = CpuFeaturesFromCommandLine();
200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Only use statically determined features for cross compile (snapshot).
201f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  if (cross_compile) {
202f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    supported_ |= command_line & CpuFeaturesFromCompiler();
203f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    return;
204f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  }
205257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
206402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu#ifndef __arm__
207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // For the simulator build, use whatever the flags specify.
208f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  supported_ |= command_line;
209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#else  // __arm__
211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Probe for additional features at runtime.
212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  base::CPU cpu;
213f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Runtime detection is slightly fuzzy, and some inferences are necessary.
214f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  unsigned runtime = kArmv6;
215f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // NEON and VFPv3 imply at least ARMv7-A.
216f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  if (cpu.has_neon() && cpu.has_vfp3_d32()) {
217f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    DCHECK(cpu.has_vfp3());
218f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    runtime |= kArmv7;
219f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    if (cpu.has_idiva()) {
220f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      runtime |= kArmv7WithSudiv;
221f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      if (cpu.architecture() >= 8) {
222f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        runtime |= kArmv8;
223f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      }
224f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    }
225d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
2263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
227f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Use the best of the features found by CPU detection and those inferred from
228f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // the build system. In both cases, restrict available features using the
229f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // command-line. Note that the command-line flags are very permissive (kArmv8)
230f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // by default.
231f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  supported_ |= command_line & CpuFeaturesFromCompiler();
232f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  supported_ |= command_line & runtime;
233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
234f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Additional tuning options.
235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // ARM Cortex-A9 and Cortex-A5 have 32 byte cachelines.
237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (cpu.implementer() == base::CPU::ARM &&
238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      (cpu.part() == base::CPU::ARM_CORTEX_A5 ||
239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       cpu.part() == base::CPU::ARM_CORTEX_A9)) {
240109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    dcache_line_size_ = 32;
2413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
244f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK_IMPLIES(IsSupported(ARMv7_SUDIV), IsSupported(ARMv7));
245f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK_IMPLIES(IsSupported(ARMv8), IsSupported(ARMv7_SUDIV));
246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CpuFeatures::PrintTarget() {
250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* arm_arch = NULL;
251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* arm_target_type = "";
252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* arm_no_probe = "";
253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* arm_fpu = "";
254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* arm_thumb = "";
255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* arm_float_abi = NULL;
256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if !defined __arm__
258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  arm_target_type = " simulator";
2596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#endif
260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if defined ARM_TEST_NO_FEATURE_PROBE
262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  arm_no_probe = " noprobe";
263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
265014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#if defined CAN_USE_ARMV8_INSTRUCTIONS
266014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  arm_arch = "arm v8";
267014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#elif defined CAN_USE_ARMV7_INSTRUCTIONS
268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  arm_arch = "arm v7";
269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#else
270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  arm_arch = "arm v6";
271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if defined CAN_USE_NEON
274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  arm_fpu = " neon";
275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#elif defined CAN_USE_VFP3_INSTRUCTIONS
276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#  if defined CAN_USE_VFP32DREGS
277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  arm_fpu = " vfp3";
278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#  else
279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  arm_fpu = " vfp3-d16";
280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#  endif
281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#else
282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  arm_fpu = " vfp2";
283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef __arm__
286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  arm_float_abi = base::OS::ArmUsingHardFloat() ? "hard" : "softfp";
287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#elif USE_EABI_HARDFLOAT
288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  arm_float_abi = "hard";
289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#else
290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  arm_float_abi = "softfp";
291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if defined __arm__ && (defined __thumb__) || (defined __thumb2__)
294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  arm_thumb = " thumb";
295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  printf("target%s%s %s%s%s %s\n",
298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         arm_target_type, arm_no_probe, arm_arch, arm_fpu, arm_thumb,
299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         arm_float_abi);
300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CpuFeatures::PrintFeatures() {
304f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  printf("ARMv8=%d ARMv7=%d VFPv3=%d VFP32DREGS=%d NEON=%d SUDIV=%d",
305f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch         CpuFeatures::IsSupported(ARMv8), CpuFeatures::IsSupported(ARMv7),
306f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch         CpuFeatures::IsSupported(VFPv3), CpuFeatures::IsSupported(VFP32DREGS),
307f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch         CpuFeatures::IsSupported(NEON), CpuFeatures::IsSupported(SUDIV));
308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef __arm__
309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool eabi_hardfloat = base::OS::ArmUsingHardFloat();
310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#elif USE_EABI_HARDFLOAT
311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool eabi_hardfloat = true;
312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#else
313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool eabi_hardfloat = false;
314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
315f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  printf(" USE_EABI_HARDFLOAT=%d\n", eabi_hardfloat);
316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// -----------------------------------------------------------------------------
320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Implementation of RelocInfo
321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
322014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// static
323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst int RelocInfo::kApplyMask = 0;
324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
326f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkebool RelocInfo::IsCodedSpecially() {
327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The deserializer needs to know whether a pointer is specially coded.  Being
328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // specially coded on ARM means that it is a movw/movt instruction, or is an
329014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // embedded constant pool entry.  These only occur if
330014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // FLAG_enable_embedded_constant_pool is true.
331014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return FLAG_enable_embedded_constant_pool;
332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool RelocInfo::IsInConstantPool() {
336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return Assembler::is_constant_pool_load(pc_);
337f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
338f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
339bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochAddress RelocInfo::wasm_memory_reference() {
340bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK(IsWasmMemoryReference(rmode_));
341bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  return Assembler::target_address_at(pc_, host_);
342bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
343bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
344bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochuint32_t RelocInfo::wasm_memory_size_reference() {
345bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK(IsWasmMemorySizeReference(rmode_));
346bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  return reinterpret_cast<uint32_t>(Assembler::target_address_at(pc_, host_));
347bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
348bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
34913e2dadd00298019ed862f2b2fc5068bba730bcfBen MurdochAddress RelocInfo::wasm_global_reference() {
35013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  DCHECK(IsWasmGlobalReference(rmode_));
35113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  return Assembler::target_address_at(pc_, host_);
35213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
35313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
35462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochuint32_t RelocInfo::wasm_function_table_size_reference() {
35562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(IsWasmFunctionTableSizeReference(rmode_));
35662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return reinterpret_cast<uint32_t>(Assembler::target_address_at(pc_, host_));
35762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
35862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
35913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid RelocInfo::unchecked_update_wasm_memory_reference(
36013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    Address address, ICacheFlushMode flush_mode) {
36113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Assembler::set_target_address_at(isolate_, pc_, host_, address, flush_mode);
36213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
36313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
36462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid RelocInfo::unchecked_update_wasm_size(uint32_t size,
36562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                           ICacheFlushMode flush_mode) {
36613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Assembler::set_target_address_at(isolate_, pc_, host_,
36713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                                   reinterpret_cast<Address>(size), flush_mode);
368bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
369f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// -----------------------------------------------------------------------------
371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Implementation of Operand and MemOperand
372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// See assembler-arm-inl.h for inlined constructors
373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockOperand::Operand(Handle<Object> handle) {
375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AllowDeferredHandleDereference using_raw_address;
376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  rm_ = no_reg;
377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Verify all Objects referred by code are NOT in new space.
378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Object* obj = *handle;
379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (obj->IsHeapObject()) {
380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    imm32_ = reinterpret_cast<intptr_t>(handle.location());
381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    rmode_ = RelocInfo::EMBEDDED_OBJECT;
382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // no relocation needed
384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    imm32_ = reinterpret_cast<intptr_t>(obj);
385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    rmode_ = RelocInfo::NONE32;
386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockOperand::Operand(Register rm, ShiftOp shift_op, int shift_imm) {
391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(is_uint5(shift_imm));
392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  rm_ = rm;
394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  rs_ = no_reg;
395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  shift_op_ = shift_op;
396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  shift_imm_ = shift_imm & 31;
397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if ((shift_op == ROR) && (shift_imm == 0)) {
399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // ROR #0 is functionally equivalent to LSL #0 and this allow us to encode
400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // RRX as ROR #0 (See below).
401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    shift_op = LSL;
402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (shift_op == RRX) {
403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // encoded as ROR with shift_imm == 0
404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(shift_imm == 0);
405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    shift_op_ = ROR;
406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    shift_imm_ = 0;
407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockOperand::Operand(Register rm, ShiftOp shift_op, Register rs) {
412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(shift_op != RRX);
413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  rm_ = rm;
414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  rs_ = no_reg;
415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  shift_op_ = shift_op;
416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  rs_ = rs;
417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockMemOperand::MemOperand(Register rn, int32_t offset, AddrMode am) {
421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  rn_ = rn;
422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  rm_ = no_reg;
423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  offset_ = offset;
424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  am_ = am;
425014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
426014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Accesses below the stack pointer are not safe, and are prohibited by the
427014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // ABI. We can check obvious violations here.
428014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (rn.is(sp)) {
429014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (am == Offset) DCHECK_LE(0, offset);
430014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (am == NegOffset) DCHECK_GE(0, offset);
431014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockMemOperand::MemOperand(Register rn, Register rm, AddrMode am) {
436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  rn_ = rn;
437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  rm_ = rm;
438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  shift_op_ = LSL;
439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  shift_imm_ = 0;
440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  am_ = am;
441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockMemOperand::MemOperand(Register rn, Register rm,
445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       ShiftOp shift_op, int shift_imm, AddrMode am) {
446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(is_uint5(shift_imm));
447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  rn_ = rn;
448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  rm_ = rm;
449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  shift_op_ = shift_op;
450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  shift_imm_ = shift_imm & 31;
451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  am_ = am;
452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochNeonMemOperand::NeonMemOperand(Register rn, AddrMode am, int align) {
456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((am == Offset) || (am == PostIndex));
457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  rn_ = rn;
458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  rm_ = (am == Offset) ? pc : sp;
459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SetAlignment(align);
460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochNeonMemOperand::NeonMemOperand(Register rn, Register rm, int align) {
464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  rn_ = rn;
465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  rm_ = rm;
466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SetAlignment(align);
467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NeonMemOperand::SetAlignment(int align) {
471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  switch (align) {
472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case 0:
473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      align_ = 0;
474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case 64:
476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      align_ = 1;
477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case 128:
479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      align_ = 2;
480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case 256:
482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      align_ = 3;
483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    default:
485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      UNREACHABLE();
486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      align_ = 0;
487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// -----------------------------------------------------------------------------
4921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// Specific instructions, constants, and masks.
493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// str(r, MemOperand(sp, 4, NegPreIndex), al) instruction (aka push(r))
495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// register r is not encoded.
4961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockconst Instr kPushRegPattern =
497014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    al | B26 | 4 | NegPreIndex | Register::kCode_sp * B16;
498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ldr(r, MemOperand(sp, 4, PostIndex), al) instruction (aka pop(r))
499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// register r is not encoded.
5001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockconst Instr kPopRegPattern =
501014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    al | B26 | L | 4 | PostIndex | Register::kCode_sp * B16;
5026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// ldr rd, [pc, #offset]
503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst Instr kLdrPCImmedMask = 15 * B24 | 7 * B20 | 15 * B16;
504014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Instr kLdrPCImmedPattern = 5 * B24 | L | Register::kCode_pc * B16;
505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// ldr rd, [pp, #offset]
506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst Instr kLdrPpImmedMask = 15 * B24 | 7 * B20 | 15 * B16;
507014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Instr kLdrPpImmedPattern = 5 * B24 | L | Register::kCode_r8 * B16;
508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// ldr rd, [pp, rn]
509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst Instr kLdrPpRegMask = 15 * B24 | 7 * B20 | 15 * B16;
510014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Instr kLdrPpRegPattern = 7 * B24 | L | Register::kCode_r8 * B16;
511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// vldr dd, [pc, #offset]
512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst Instr kVldrDPCMask = 15 * B24 | 3 * B20 | 15 * B16 | 15 * B8;
513014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Instr kVldrDPCPattern = 13 * B24 | L | Register::kCode_pc * B16 | 11 * B8;
514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// vldr dd, [pp, #offset]
515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst Instr kVldrDPpMask = 15 * B24 | 3 * B20 | 15 * B16 | 15 * B8;
516014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Instr kVldrDPpPattern = 13 * B24 | L | Register::kCode_r8 * B16 | 11 * B8;
5176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// blxcc rm
5186ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst Instr kBlxRegMask =
5196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    15 * B24 | 15 * B20 | 15 * B16 | 15 * B12 | 15 * B8 | 15 * B4;
5206ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst Instr kBlxRegPattern =
5211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    B24 | B21 | 15 * B16 | 15 * B12 | 15 * B8 | BLX;
5223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst Instr kBlxIp = al | kBlxRegPattern | ip.code();
5239dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenconst Instr kMovMvnMask = 0x6d * B21 | 0xf * B16;
5249dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenconst Instr kMovMvnPattern = 0xd * B21;
5259dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenconst Instr kMovMvnFlip = B22;
5269dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenconst Instr kMovLeaveCCMask = 0xdff * B16;
5279dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenconst Instr kMovLeaveCCPattern = 0x1a0 * B16;
5289dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenconst Instr kMovwPattern = 0x30 * B20;
529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst Instr kMovtPattern = 0x34 * B20;
5309dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenconst Instr kMovwLeaveCCFlip = 0x5 * B21;
531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst Instr kMovImmedMask = 0x7f * B21;
532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst Instr kMovImmedPattern = 0x1d * B21;
533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst Instr kOrrImmedMask = 0x7f * B21;
534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst Instr kOrrImmedPattern = 0x1c * B21;
5359dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenconst Instr kCmpCmnMask = 0xdd * B20 | 0xf * B12;
5369dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenconst Instr kCmpCmnPattern = 0x15 * B20;
5379dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenconst Instr kCmpCmnFlip = B21;
5389dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenconst Instr kAddSubFlip = 0x6 * B21;
5399dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenconst Instr kAndBicFlip = 0xe * B21;
5409dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
541f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke// A mask for the Rd register for push, pop, ldr, str instructions.
5421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockconst Instr kLdrRegFpOffsetPattern =
543014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    al | B26 | L | Offset | Register::kCode_fp * B16;
5441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockconst Instr kStrRegFpOffsetPattern =
545014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    al | B26 | Offset | Register::kCode_fp * B16;
5461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockconst Instr kLdrRegFpNegOffsetPattern =
547014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    al | B26 | L | NegOffset | Register::kCode_fp * B16;
5481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockconst Instr kStrRegFpNegOffsetPattern =
549014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    al | B26 | NegOffset | Register::kCode_fp * B16;
5501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockconst Instr kLdrStrInstrTypeMask = 0xffff0000;
551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochAssembler::Assembler(Isolate* isolate, void* buffer, int buffer_size)
553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    : AssemblerBase(isolate, buffer, buffer_size),
554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      recorded_ast_id_(TypeFeedbackId::None()),
55513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      pending_32_bit_constants_(),
55613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      pending_64_bit_constants_(),
557f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      constant_pool_builder_(kLdrMaxReachBits, kVldrMaxReachBits) {
55813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  pending_32_bit_constants_.reserve(kMinNumPendingConstants);
55913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  pending_64_bit_constants_.reserve(kMinNumPendingConstants);
560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  reloc_info_writer.Reposition(buffer_ + buffer_size_, pc_);
561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  next_buffer_check_ = 0;
5626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  const_pool_blocked_nesting_ = 0;
563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  no_const_pool_before_ = 0;
564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  first_const_pool_32_use_ = -1;
565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  first_const_pool_64_use_ = -1;
566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  last_bound_pos_ = 0;
5673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ClearRecordedAstId();
568f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  if (CpuFeatures::IsSupported(VFP32DREGS)) {
569f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    // Register objects tend to be abstracted and survive between scopes, so
570f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    // it's awkward to use CpuFeatures::VFP32DREGS with CpuFeatureScope. To make
571f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    // its use consistent with other features, we always enable it if we can.
572f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    EnableCpuFeature(VFP32DREGS);
573f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  }
574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockAssembler::~Assembler() {
578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(const_pool_blocked_nesting_ == 0);
579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::GetCode(CodeDesc* desc) {
583014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Emit constant pool if necessary.
584014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int constant_pool_offset = 0;
585014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (FLAG_enable_embedded_constant_pool) {
586014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    constant_pool_offset = EmitEmbeddedConstantPool();
587014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CheckConstPool(true, false);
58913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    DCHECK(pending_32_bit_constants_.empty());
59013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    DCHECK(pending_64_bit_constants_.empty());
591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set up code descriptor.
593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  desc->buffer = buffer_;
594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  desc->buffer_size = buffer_size_;
595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  desc->instr_size = pc_offset();
596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
597014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  desc->constant_pool_size =
598014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      (constant_pool_offset ? desc->instr_size - constant_pool_offset : 0);
599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  desc->origin = this;
60013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  desc->unwinding_info_size = 0;
60113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  desc->unwinding_info = nullptr;
602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::Align(int m) {
606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(m >= 4 && base::bits::IsPowerOfTwo32(m));
607014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK((pc_offset() & (kInstrSize - 1)) == 0);
608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while ((pc_offset() & (m - 1)) != 0) {
609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    nop();
610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6149dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenvoid Assembler::CodeTargetAlign() {
6159dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // Preferred alignment of jump targets on some ARM chips.
6169dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  Align(8);
6179dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
6189dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
6199dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
6201e0659c275bb392c045087af4f6b0d7565cb3d77Steve BlockCondition Assembler::GetCondition(Instr instr) {
6211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return Instruction::ConditionField(instr);
6221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
6231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
6241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
6256ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockbool Assembler::IsBranch(Instr instr) {
6266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return (instr & (B27 | B25)) == (B27 | B25);
6276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
6286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
6296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
6306ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockint Assembler::GetBranchOffset(Instr instr) {
631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsBranch(instr));
6326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Take the jump offset in the lower 24 bits, sign extend it and multiply it
6336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // with 4 to get the offset in bytes.
6341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return ((instr & kImm24Mask) << 8) >> 6;
6356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
6366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
6376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
6386ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockbool Assembler::IsLdrRegisterImmediate(Instr instr) {
6396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return (instr & (B27 | B26 | B25 | B22 | B20)) == (B26 | B20);
6406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
6416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
6426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool Assembler::IsVldrDRegisterImmediate(Instr instr) {
644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return (instr & (15 * B24 | 3 * B20 | 15 * B8)) == (13 * B24 | B20 | 11 * B8);
645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6486ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockint Assembler::GetLdrRegisterImmediateOffset(Instr instr) {
649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsLdrRegisterImmediate(instr));
6506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  bool positive = (instr & B23) == B23;
6511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  int offset = instr & kOff12Mask;  // Zero extended offset.
6526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return positive ? offset : -offset;
6536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
6546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
6556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint Assembler::GetVldrDRegisterImmediateOffset(Instr instr) {
657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsVldrDRegisterImmediate(instr));
658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool positive = (instr & B23) == B23;
659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int offset = instr & kOff8Mask;  // Zero extended offset.
660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  offset <<= 2;
661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return positive ? offset : -offset;
662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6656ded16be15dd865a9b21ea304d5273c8be299c87Steve BlockInstr Assembler::SetLdrRegisterImmediateOffset(Instr instr, int offset) {
666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsLdrRegisterImmediate(instr));
6676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  bool positive = offset >= 0;
6686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (!positive) offset = -offset;
669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(is_uint12(offset));
6706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Set bit indicating whether the offset should be added.
6716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  instr = (instr & ~B23) | (positive ? B23 : 0);
6726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Set the actual offset.
6731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return (instr & ~kOff12Mask) | offset;
6746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
6756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
6766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochInstr Assembler::SetVldrDRegisterImmediateOffset(Instr instr, int offset) {
678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsVldrDRegisterImmediate(instr));
679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((offset & ~3) == offset);  // Must be 64-bit aligned.
680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool positive = offset >= 0;
681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!positive) offset = -offset;
682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(is_uint10(offset));
683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Set bit indicating whether the offset should be added.
684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  instr = (instr & ~B23) | (positive ? B23 : 0);
685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Set the actual offset. Its bottom 2 bits are zero.
686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return (instr & ~kOff8Mask) | (offset >> 2);
687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
69050ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsenbool Assembler::IsStrRegisterImmediate(Instr instr) {
69150ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  return (instr & (B27 | B26 | B25 | B22 | B20)) == B26;
69250ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen}
69350ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen
69450ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen
69550ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian MonsenInstr Assembler::SetStrRegisterImmediateOffset(Instr instr, int offset) {
696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsStrRegisterImmediate(instr));
69750ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  bool positive = offset >= 0;
69850ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  if (!positive) offset = -offset;
699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(is_uint12(offset));
70050ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  // Set bit indicating whether the offset should be added.
70150ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  instr = (instr & ~B23) | (positive ? B23 : 0);
70250ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  // Set the actual offset.
7031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return (instr & ~kOff12Mask) | offset;
70450ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen}
70550ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen
70650ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen
70750ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsenbool Assembler::IsAddRegisterImmediate(Instr instr) {
70850ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  return (instr & (B27 | B26 | B25 | B24 | B23 | B22 | B21)) == (B25 | B23);
70950ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen}
71050ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen
71150ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen
71250ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian MonsenInstr Assembler::SetAddRegisterImmediateOffset(Instr instr, int offset) {
713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsAddRegisterImmediate(instr));
714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(offset >= 0);
715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(is_uint12(offset));
71650ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  // Set the offset.
7171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return (instr & ~kOff12Mask) | offset;
71850ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen}
71950ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen
72050ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen
721f7060e27768c550ace7ec48ad8c093466db52dfaLeon ClarkeRegister Assembler::GetRd(Instr instr) {
722f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Register reg;
723014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  reg.reg_code = Instruction::RdValue(instr);
7241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return reg;
7251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
7261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
7271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
7281e0659c275bb392c045087af4f6b0d7565cb3d77Steve BlockRegister Assembler::GetRn(Instr instr) {
7291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Register reg;
730014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  reg.reg_code = Instruction::RnValue(instr);
7311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return reg;
7321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
7331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
7341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
7351e0659c275bb392c045087af4f6b0d7565cb3d77Steve BlockRegister Assembler::GetRm(Instr instr) {
7361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Register reg;
737014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  reg.reg_code = Instruction::RmValue(instr);
738f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  return reg;
739f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
740f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
741f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochInstr Assembler::GetConsantPoolLoadPattern() {
743014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (FLAG_enable_embedded_constant_pool) {
744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return kLdrPpImmedPattern;
745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return kLdrPCImmedPattern;
747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochInstr Assembler::GetConsantPoolLoadMask() {
752014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (FLAG_enable_embedded_constant_pool) {
753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return kLdrPpImmedMask;
754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return kLdrPCImmedMask;
756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
760f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkebool Assembler::IsPush(Instr instr) {
761f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  return ((instr & ~kRdMask) == kPushRegPattern);
762f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
763f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
764f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
765f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkebool Assembler::IsPop(Instr instr) {
766f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  return ((instr & ~kRdMask) == kPopRegPattern);
767f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
768f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
769f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
770f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkebool Assembler::IsStrRegFpOffset(Instr instr) {
771f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  return ((instr & kLdrStrInstrTypeMask) == kStrRegFpOffsetPattern);
772f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
773f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
774f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
775f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkebool Assembler::IsLdrRegFpOffset(Instr instr) {
776f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  return ((instr & kLdrStrInstrTypeMask) == kLdrRegFpOffsetPattern);
777f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
778f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
779f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
780f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkebool Assembler::IsStrRegFpNegOffset(Instr instr) {
781f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  return ((instr & kLdrStrInstrTypeMask) == kStrRegFpNegOffsetPattern);
782f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
783f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
784f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
785f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkebool Assembler::IsLdrRegFpNegOffset(Instr instr) {
786f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  return ((instr & kLdrStrInstrTypeMask) == kLdrRegFpNegOffsetPattern);
787f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
788f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
789f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
7908a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wangbool Assembler::IsLdrPcImmediateOffset(Instr instr) {
7918a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Check the instruction is indeed a
7928a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // ldr<cond> <Rd>, [pc +/- offset_12].
793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return (instr & kLdrPCImmedMask) == kLdrPCImmedPattern;
794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool Assembler::IsLdrPpImmediateOffset(Instr instr) {
798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check the instruction is indeed a
799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // ldr<cond> <Rd>, [pp +/- offset_12].
800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return (instr & kLdrPpImmedMask) == kLdrPpImmedPattern;
801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool Assembler::IsLdrPpRegOffset(Instr instr) {
805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check the instruction is indeed a
806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // ldr<cond> <Rd>, [pp, +/- <Rm>].
807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return (instr & kLdrPpRegMask) == kLdrPpRegPattern;
808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochInstr Assembler::GetLdrPpRegOffsetPattern() { return kLdrPpRegPattern; }
812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool Assembler::IsVldrDPcImmediateOffset(Instr instr) {
815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check the instruction is indeed a
816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // vldr<cond> <Dd>, [pc +/- offset_10].
817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return (instr & kVldrDPCMask) == kVldrDPCPattern;
818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool Assembler::IsVldrDPpImmediateOffset(Instr instr) {
822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check the instruction is indeed a
823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // vldr<cond> <Dd>, [pp +/- offset_10].
824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return (instr & kVldrDPpMask) == kVldrDPpPattern;
825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool Assembler::IsBlxReg(Instr instr) {
829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check the instruction is indeed a
830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // blxcc <Rm>
831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return (instr & kBlxRegMask) == kBlxRegPattern;
832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool Assembler::IsBlxIp(Instr instr) {
836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check the instruction is indeed a
837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // blx ip
838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return instr == kBlxIp;
8391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
8401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
8411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
8421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockbool Assembler::IsTstImmediate(Instr instr) {
8431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return (instr & (B27 | B26 | I | kOpCodeMask | S | kRdMask)) ==
8441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      (I | TST | S);
8451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
8461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
8471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
8481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockbool Assembler::IsCmpRegister(Instr instr) {
8491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return (instr & (B27 | B26 | I | kOpCodeMask | S | kRdMask | B4)) ==
8501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      (CMP | S);
8511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
8521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
8531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
8541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockbool Assembler::IsCmpImmediate(Instr instr) {
8551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return (instr & (B27 | B26 | I | kOpCodeMask | S | kRdMask)) ==
8561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      (I | CMP | S);
8578a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang}
8588a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
8598a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
8601e0659c275bb392c045087af4f6b0d7565cb3d77Steve BlockRegister Assembler::GetCmpImmediateRegister(Instr instr) {
861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsCmpImmediate(instr));
8621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return GetRn(instr);
8631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
8641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
8651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
8661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockint Assembler::GetCmpImmediateRawImmediate(Instr instr) {
867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsCmpImmediate(instr));
8681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return instr & kOff12Mask;
8691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
8701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Labels refer to positions in the (to be) generated code.
873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// There are bound, linked, and unused labels.
874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Bound labels refer to known positions in the already
876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// generated code. pos() is the position the label refers to.
877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Linked labels refer to unknown positions in the code
879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// to be generated; pos() is the position of the last
880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// instruction using the label.
881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//
882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// The linked labels form a link chain by making the branch offset
883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// in the instruction steam to point to the previous branch
884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// instruction using the same label.
885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//
886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// The link chain is terminated by a branch offset pointing to the
887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// same position.
888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint Assembler::target_at(int pos) {
891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Instr instr = instr_at(pos);
892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (is_uint24(instr)) {
893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Emitted link to a label, not part of a branch.
894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return instr;
895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
896014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_EQ(5 * B25, instr & 7 * B25);  // b, bl, or blx imm24
8971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  int imm26 = ((instr & kImm24Mask) << 8) >> 6;
8981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if ((Instruction::ConditionField(instr) == kSpecialCondition) &&
8991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      ((instr & B24) != 0)) {
900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // blx uses bit 24 to encode bit 2 of imm26
901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    imm26 += 2;
9026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return pos + kPcLoadDelta + imm26;
904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::target_at_put(int pos, int target_pos) {
908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Instr instr = instr_at(pos);
909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (is_uint24(instr)) {
910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(target_pos == pos || target_pos >= 0);
911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Emitted link to a label, not part of a branch.
912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Load the position of the label relative to the generated code object
913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // pointer in a register.
914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
91513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    // The existing code must be a single 24-bit label chain link, followed by
91613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    // nops encoding the destination register. See mov_label_offset.
91713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
91813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    // Extract the destination register from the first nop instructions.
91913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    Register dst =
92013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        Register::from_code(Instruction::RmValue(instr_at(pos + kInstrSize)));
92113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    // In addition to the 24-bit label chain link, we expect to find one nop for
92213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    // ARMv7 and above, or two nops for ARMv6. See mov_label_offset.
92313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    DCHECK(IsNop(instr_at(pos + kInstrSize), dst.code()));
92413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (!CpuFeatures::IsSupported(ARMv7)) {
92513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      DCHECK(IsNop(instr_at(pos + 2 * kInstrSize), dst.code()));
92613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    }
92713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Here are the instructions we need to emit:
929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    //   For ARMv7: target24 => target16_1:target16_0
930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    //      movw dst, #target16_0
931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    //      movt dst, #target16_1
932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    //   For ARMv6: target24 => target8_2:target8_1:target8_0
933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    //      mov dst, #target8_0
934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    //      orr dst, dst, #target8_1 << 8
935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    //      orr dst, dst, #target8_2 << 16
936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint32_t target24 = target_pos + (Code::kHeaderSize - kHeapObjectTag);
938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(is_uint24(target24));
939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (is_uint8(target24)) {
940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // If the target fits in a byte then only patch with a mov
941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // instruction.
942014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      CodePatcher patcher(isolate(), reinterpret_cast<byte*>(buffer_ + pos), 1,
943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          CodePatcher::DONT_FLUSH);
944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      patcher.masm()->mov(dst, Operand(target24));
945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      uint16_t target16_0 = target24 & kImm16Mask;
947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      uint16_t target16_1 = target24 >> 16;
948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (CpuFeatures::IsSupported(ARMv7)) {
949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // Patch with movw/movt.
950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (target16_1 == 0) {
951014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          CodePatcher patcher(isolate(), reinterpret_cast<byte*>(buffer_ + pos),
952014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                              1, CodePatcher::DONT_FLUSH);
953f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch          CpuFeatureScope scope(patcher.masm(), ARMv7);
954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          patcher.masm()->movw(dst, target16_0);
955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        } else {
956014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          CodePatcher patcher(isolate(), reinterpret_cast<byte*>(buffer_ + pos),
957014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                              2, CodePatcher::DONT_FLUSH);
958f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch          CpuFeatureScope scope(patcher.masm(), ARMv7);
959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          patcher.masm()->movw(dst, target16_0);
960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          patcher.masm()->movt(dst, target16_1);
961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // Patch with a sequence of mov/orr/orr instructions.
964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        uint8_t target8_0 = target16_0 & kImm8Mask;
965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        uint8_t target8_1 = target16_0 >> 8;
966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        uint8_t target8_2 = target16_1 & kImm8Mask;
967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (target8_2 == 0) {
968014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          CodePatcher patcher(isolate(), reinterpret_cast<byte*>(buffer_ + pos),
969014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                              2, CodePatcher::DONT_FLUSH);
970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          patcher.masm()->mov(dst, Operand(target8_0));
971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          patcher.masm()->orr(dst, dst, Operand(target8_1 << 8));
972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        } else {
973014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          CodePatcher patcher(isolate(), reinterpret_cast<byte*>(buffer_ + pos),
974014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                              3, CodePatcher::DONT_FLUSH);
975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          patcher.masm()->mov(dst, Operand(target8_0));
976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          patcher.masm()->orr(dst, dst, Operand(target8_1 << 8));
977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          patcher.masm()->orr(dst, dst, Operand(target8_2 << 16));
978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int imm26 = target_pos - (pos + kPcLoadDelta);
984014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_EQ(5 * B25, instr & 7 * B25);  // b, bl, or blx imm24
9851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (Instruction::ConditionField(instr) == kSpecialCondition) {
986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // blx uses bit 24 to encode bit 2 of imm26
987014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK_EQ(0, imm26 & 1);
988014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    instr = (instr & ~(B24 | kImm24Mask)) | ((imm26 & 2) >> 1) * B24;
989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
990014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK_EQ(0, imm26 & 3);
9911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    instr &= ~kImm24Mask;
992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int imm24 = imm26 >> 2;
994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(is_int24(imm24));
9951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  instr_at_put(pos, instr | (imm24 & kImm24Mask));
996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::print(Label* L) {
1000a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (L->is_unused()) {
1001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    PrintF("unused label\n");
1002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (L->is_bound()) {
1003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    PrintF("bound label to %d\n", L->pos());
1004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (L->is_linked()) {
1005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Label l = *L;
1006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    PrintF("unbound label");
1007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    while (l.is_linked()) {
1008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      PrintF("@ %d ", l.pos());
1009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Instr instr = instr_at(l.pos());
10101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      if ((instr & ~kImm24Mask) == 0) {
1011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        PrintF("value\n");
1012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else {
1013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        DCHECK((instr & 7*B25) == 5*B25);  // b, bl, or blx
10141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        Condition cond = Instruction::ConditionField(instr);
1015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        const char* b;
1016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        const char* c;
10171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        if (cond == kSpecialCondition) {
1018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          b = "blx";
1019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          c = "";
1020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
1021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          if ((instr & B24) != 0)
1022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            b = "bl";
1023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          else
1024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            b = "b";
1025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          switch (cond) {
1027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case eq: c = "eq"; break;
1028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case ne: c = "ne"; break;
1029a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case hs: c = "hs"; break;
1030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case lo: c = "lo"; break;
1031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case mi: c = "mi"; break;
1032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case pl: c = "pl"; break;
1033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case vs: c = "vs"; break;
1034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case vc: c = "vc"; break;
1035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case hi: c = "hi"; break;
1036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case ls: c = "ls"; break;
1037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case ge: c = "ge"; break;
1038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case lt: c = "lt"; break;
1039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case gt: c = "gt"; break;
1040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case le: c = "le"; break;
1041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case al: c = ""; break;
1042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            default:
1043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              c = "";
1044a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              UNREACHABLE();
1045a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          }
1046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
1047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        PrintF("%s%s\n", b, c);
1048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
1049a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      next(&l);
1050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
1052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    PrintF("label in inconsistent state (pos = %d)\n", L->pos_);
1053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::bind_to(Label* L, int pos) {
1058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(0 <= pos && pos <= pc_offset());  // must have a valid binding position
1059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (L->is_linked()) {
1060a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int fixup_pos = L->pos();
1061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    next(L);  // call next before overwriting link with target at fixup_pos
1062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    target_at_put(fixup_pos, pos);
1063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  L->bind_to(pos);
1065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1066a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Keep track of the last bound label so we don't eliminate any instructions
1067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // before a bound label.
1068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (pos > last_bound_pos_)
1069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    last_bound_pos_ = pos;
1070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1072a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1073a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::bind(Label* L) {
1074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!L->is_bound());  // label can only be bound once
1075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind_to(L, pc_offset());
1076a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1078a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1079a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::next(Label* L) {
1080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(L->is_linked());
1081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int link = target_at(L->pos());
1082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (link == L->pos()) {
1083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Branch target points to the same instuction. This is the end of the link
1084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // chain.
1085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    L->Unuse();
108669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  } else {
1087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(link >= 0);
108869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    L->link_to(link);
1089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10933100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Low-level code emission routines depending on the addressing mode.
10949dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen// If this returns true then you have to use the rotate_imm and immed_8
10959dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen// that it returns, because it may have already changed the instruction
10969dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen// to match them!
1097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic bool fits_shifter(uint32_t imm32,
1098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         uint32_t* rotate_imm,
1099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         uint32_t* immed_8,
1100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         Instr* instr) {
11013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // imm32 must be unsigned.
1102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int rot = 0; rot < 16; rot++) {
1103014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    uint32_t imm8 = base::bits::RotateLeft32(imm32, 2 * rot);
1104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if ((imm8 <= 0xff)) {
1105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      *rotate_imm = rot;
1106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      *immed_8 = imm8;
1107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return true;
1108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
11109dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // If the opcode is one with a complementary version and the complementary
11119dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // immediate fits, change the opcode.
11129dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  if (instr != NULL) {
11139dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    if ((*instr & kMovMvnMask) == kMovMvnPattern) {
11149dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      if (fits_shifter(~imm32, rotate_imm, immed_8, NULL)) {
11159dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        *instr ^= kMovMvnFlip;
11169dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        return true;
11179dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      } else if ((*instr & kMovLeaveCCMask) == kMovLeaveCCPattern) {
11188b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        if (CpuFeatures::IsSupported(ARMv7)) {
11199dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen          if (imm32 < 0x10000) {
11209dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen            *instr ^= kMovwLeaveCCFlip;
1121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            *instr |= Assembler::EncodeMovwImmediate(imm32);
11229dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen            *rotate_imm = *immed_8 = 0;  // Not used for movw.
11239dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen            return true;
11249dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen          }
11259dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        }
11269dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      }
11279dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    } else if ((*instr & kCmpCmnMask) == kCmpCmnPattern) {
1128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (fits_shifter(-static_cast<int>(imm32), rotate_imm, immed_8, NULL)) {
11299dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        *instr ^= kCmpCmnFlip;
11309dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        return true;
11319dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      }
11329dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    } else {
11339dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      Instr alu_insn = (*instr & kALUMask);
11341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      if (alu_insn == ADD ||
11351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block          alu_insn == SUB) {
1136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (fits_shifter(-static_cast<int>(imm32), rotate_imm, immed_8, NULL)) {
11379dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen          *instr ^= kAddSubFlip;
11389dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen          return true;
11399dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        }
11401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      } else if (alu_insn == AND ||
11411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                 alu_insn == BIC) {
11429dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        if (fits_shifter(~imm32, rotate_imm, immed_8, NULL)) {
11439dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen          *instr ^= kAndBicFlip;
11449dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen          return true;
11459dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        }
11469dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      }
1147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return false;
1150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// We have to use the temporary register for things that can be relocated even
1154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// if they can be encoded in the ARM's 12 bits of immediate-offset instruction
1155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// space.  There is no guarantee that the relocated location can be similarly
1156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// encoded.
1157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool Operand::must_output_reloc_info(const Assembler* assembler) const {
11583e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  if (rmode_ == RelocInfo::EXTERNAL_REFERENCE) {
1159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (assembler != NULL && assembler->predictable_code_size()) return true;
1160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return assembler->serializer_enabled();
1161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (RelocInfo::IsNone(rmode_)) {
1162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return false;
1163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return true;
1165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic bool use_mov_immediate_load(const Operand& x,
1169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   const Assembler* assembler) {
1170f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(assembler != nullptr);
1171f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  if (FLAG_enable_embedded_constant_pool &&
1172014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      !assembler->is_constant_pool_available()) {
1173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return true;
1174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (x.must_output_reloc_info(assembler)) {
1175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Prefer constant pool if data is likely to be patched.
1176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return false;
1177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Otherwise, use immediate load if movw / movt is available.
1179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return CpuFeatures::IsSupported(ARMv7);
1180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint Operand::instructions_required(const Assembler* assembler,
1185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   Instr instr) const {
1186f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(assembler != nullptr);
1187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (rm_.is_valid()) return 1;
11889dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  uint32_t dummy1, dummy2;
1189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (must_output_reloc_info(assembler) ||
119044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      !fits_shifter(imm32_, &dummy1, &dummy2, &instr)) {
119144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // The immediate operand cannot be encoded as a shifter operand, or use of
1192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // constant pool is required.  First account for the instructions required
1193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // for the constant pool or immediate load
1194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int instructions;
1195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (use_mov_immediate_load(*this, assembler)) {
1196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // A movw / movt or mov / orr immediate load.
1197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      instructions = CpuFeatures::IsSupported(ARMv7) ? 2 : 4;
1198f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    } else if (assembler->ConstantPoolAccessIsInOverflow()) {
1199014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // An overflowed constant pool load.
1200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      instructions = CpuFeatures::IsSupported(ARMv7) ? 3 : 5;
120144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    } else {
1202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // A small constant pool load.
1203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      instructions = 1;
1204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if ((instr & ~kCondMask) != 13 * B21) {  // mov, S not set
1207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // For a mov or mvn instruction which doesn't set the condition
1208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // code, the constant pool or immediate load is enough, otherwise we need
1209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // to account for the actual instruction being requested.
1210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      instructions += 1;
121144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
1212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return instructions;
121344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {
121444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // No use of constant pool and the immediate operand can be encoded as a
121544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // shifter operand.
1216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return 1;
1217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::move_32_bit_immediate(Register rd,
1222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                      const Operand& x,
1223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                      Condition cond) {
1224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  uint32_t imm32 = static_cast<uint32_t>(x.imm32_);
1225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (x.must_output_reloc_info(this)) {
1226014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    RecordRelocInfo(x.rmode_);
1227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (use_mov_immediate_load(x, this)) {
1230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register target = rd.code() == pc.code() ? ip : rd;
1231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (CpuFeatures::IsSupported(ARMv7)) {
1232f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      CpuFeatureScope scope(this, ARMv7);
1233014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (!FLAG_enable_embedded_constant_pool &&
1234014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          x.must_output_reloc_info(this)) {
1235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // Make sure the movw/movt doesn't get separated.
1236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        BlockConstPoolFor(2);
1237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
1238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      movw(target, imm32 & 0xffff, cond);
1239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      movt(target, imm32 >> 16, cond);
1240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
1241014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK(FLAG_enable_embedded_constant_pool);
1242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mov(target, Operand(imm32 & kImm8Mask), LeaveCC, cond);
1243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      orr(target, target, Operand(imm32 & (kImm8Mask << 8)), LeaveCC, cond);
1244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      orr(target, target, Operand(imm32 & (kImm8Mask << 16)), LeaveCC, cond);
1245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      orr(target, target, Operand(imm32 & (kImm8Mask << 24)), LeaveCC, cond);
1246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (target.code() != rd.code()) {
1248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mov(rd, target, LeaveCC, cond);
1249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1251014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(!FLAG_enable_embedded_constant_pool || is_constant_pool_available());
1252014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    ConstantPoolEntry::Access access =
1253014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        ConstantPoolAddEntry(pc_offset(), x.rmode_, x.imm32_);
1254014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (access == ConstantPoolEntry::OVERFLOWED) {
1255014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK(FLAG_enable_embedded_constant_pool);
1256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Register target = rd.code() == pc.code() ? ip : rd;
1257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Emit instructions to load constant pool offset.
1258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (CpuFeatures::IsSupported(ARMv7)) {
1259f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        CpuFeatureScope scope(this, ARMv7);
1260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        movw(target, 0, cond);
1261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        movt(target, 0, cond);
1262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
1263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        mov(target, Operand(0), LeaveCC, cond);
1264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        orr(target, target, Operand(0), LeaveCC, cond);
1265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        orr(target, target, Operand(0), LeaveCC, cond);
1266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        orr(target, target, Operand(0), LeaveCC, cond);
1267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
1268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Load from constant pool at offset.
1269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ldr(rd, MemOperand(pp, target), cond);
1270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
1271014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK(access == ConstantPoolEntry::REGULAR);
1272014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      ldr(rd, MemOperand(FLAG_enable_embedded_constant_pool ? pp : pc, 0),
1273014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          cond);
1274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
127544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
12769dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
12779dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
12789dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
1279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::addrmod1(Instr instr,
1280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         Register rn,
1281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         Register rd,
1282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         const Operand& x) {
1283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckBuffer();
1284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((instr & ~(kCondMask | kOpCodeMask | S)) == 0);
1285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!x.rm_.is_valid()) {
12863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // Immediate.
1287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    uint32_t rotate_imm;
1288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    uint32_t immed_8;
1289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (x.must_output_reloc_info(this) ||
1290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        !fits_shifter(x.imm32_, &rotate_imm, &immed_8, &instr)) {
1291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // The immediate operand cannot be encoded as a shifter operand, so load
1292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // it first to register ip and change the original instruction to use ip.
1293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // However, if the original instruction is a 'mov rd, x' (not setting the
12943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      // condition code), then replace it with a 'ldr rd, [pc]'.
1295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      CHECK(!rn.is(ip));  // rn should never be ip, or will be trashed
12961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      Condition cond = Instruction::ConditionField(instr);
12971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      if ((instr & ~kCondMask) == 13*B21) {  // mov, S not set
1298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        move_32_bit_immediate(rd, x, cond);
1299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else {
1300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        mov(ip, x, LeaveCC, cond);
1301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        addrmod1(instr, rn, rd, Operand(ip));
1302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
1303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return;
1304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    instr |= I | rotate_imm*B8 | immed_8;
1306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (!x.rs_.is_valid()) {
13073100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // Immediate shift.
1308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    instr |= x.shift_imm_*B7 | x.shift_op_ | x.rm_.code();
1309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
13103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // Register shift.
1311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!rn.is(pc) && !rd.is(pc) && !x.rm_.is(pc) && !x.rs_.is(pc));
1312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    instr |= x.rs_.code()*B8 | x.shift_op_ | B4 | x.rm_.code();
1313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(instr | rn.code()*B16 | rd.code()*B12);
131550ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  if (rn.is(pc) || x.rm_.is(pc)) {
13163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // Block constant pool emission for one instruction after reading pc.
13173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    BlockConstPoolFor(1);
131850ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  }
1319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::addrmod2(Instr instr, Register rd, const MemOperand& x) {
1323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((instr & ~(kCondMask | B | L)) == B26);
1324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int am = x.am_;
1325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!x.rm_.is_valid()) {
13263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // Immediate offset.
1327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int offset_12 = x.offset_;
1328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (offset_12 < 0) {
1329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      offset_12 = -offset_12;
1330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      am ^= U;
1331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (!is_uint12(offset_12)) {
13333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      // Immediate offset cannot be encoded, load it first to register ip
13343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      // rn (and rd in a load) should never be ip, or will be trashed.
1335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(!x.rn_.is(ip) && ((instr & L) == L || !rd.is(ip)));
13361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      mov(ip, Operand(x.offset_), LeaveCC, Instruction::ConditionField(instr));
1337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      addrmod2(instr, rd, MemOperand(x.rn_, ip, x.am_));
1338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return;
1339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(offset_12 >= 0);  // no masking needed
1341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    instr |= offset_12;
1342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
13433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // Register offset (shift_imm_ and shift_op_ are 0) or scaled
1344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // register offset the constructors make sure than both shift_imm_
13453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // and shift_op_ are initialized.
1346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!x.rm_.is(pc));
1347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    instr |= B25 | x.shift_imm_*B7 | x.shift_op_ | x.rm_.code();
1348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((am & (P|W)) == P || !x.rn_.is(pc));  // no pc base with writeback
1350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(instr | am | x.rn_.code()*B16 | rd.code()*B12);
1351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::addrmod3(Instr instr, Register rd, const MemOperand& x) {
1355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((instr & ~(kCondMask | L | S6 | H)) == (B4 | B7));
1356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(x.rn_.is_valid());
1357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int am = x.am_;
1358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!x.rm_.is_valid()) {
13593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // Immediate offset.
1360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int offset_8 = x.offset_;
1361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (offset_8 < 0) {
1362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      offset_8 = -offset_8;
1363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      am ^= U;
1364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (!is_uint8(offset_8)) {
13663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      // Immediate offset cannot be encoded, load it first to register ip
13673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      // rn (and rd in a load) should never be ip, or will be trashed.
1368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(!x.rn_.is(ip) && ((instr & L) == L || !rd.is(ip)));
13691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      mov(ip, Operand(x.offset_), LeaveCC, Instruction::ConditionField(instr));
1370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      addrmod3(instr, rd, MemOperand(x.rn_, ip, x.am_));
1371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return;
1372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(offset_8 >= 0);  // no masking needed
1374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    instr |= B | (offset_8 >> 4)*B8 | (offset_8 & 0xf);
1375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (x.shift_imm_ != 0) {
13763100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // Scaled register offset not supported, load index first
13773100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // rn (and rd in a load) should never be ip, or will be trashed.
1378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!x.rn_.is(ip) && ((instr & L) == L || !rd.is(ip)));
1379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    mov(ip, Operand(x.rm_, x.shift_op_, x.shift_imm_), LeaveCC,
13801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        Instruction::ConditionField(instr));
1381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    addrmod3(instr, rd, MemOperand(x.rn_, ip, x.am_));
1382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
1383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
13843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // Register offset.
1385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK((am & (P|W)) == P || !x.rm_.is(pc));  // no pc index with writeback
1386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    instr |= x.rm_.code();
1387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((am & (P|W)) == P || !x.rn_.is(pc));  // no pc base with writeback
1389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(instr | am | x.rn_.code()*B16 | rd.code()*B12);
1390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::addrmod4(Instr instr, Register rn, RegList rl) {
1394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((instr & ~(kCondMask | P | U | W | L)) == B27);
1395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(rl != 0);
1396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!rn.is(pc));
1397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(instr | rn.code()*B16 | rl);
1398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::addrmod5(Instr instr, CRegister crd, const MemOperand& x) {
14023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Unindexed addressing is not encoded by this function.
1403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ((B27 | B26),
14041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block            (instr & ~(kCondMask | kCoprocessorMask | P | U | N | W | L)));
1405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(x.rn_.is_valid() && !x.rm_.is_valid());
1406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int am = x.am_;
1407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int offset_8 = x.offset_;
1408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((offset_8 & 3) == 0);  // offset must be an aligned word offset
1409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  offset_8 >>= 2;
1410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (offset_8 < 0) {
1411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    offset_8 = -offset_8;
1412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    am ^= U;
1413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(is_uint8(offset_8));  // unsigned word offset must fit in a byte
1415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((am & (P|W)) == P || !x.rn_.is(pc));  // no pc base with writeback
1416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Post-indexed addressing requires W == 1; different than in addrmod2/3.
1418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if ((am & P) == 0)
1419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    am |= W;
1420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(offset_8 >= 0);  // no masking needed
1422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(instr | am | x.rn_.code()*B16 | crd.code()*B12 | offset_8);
1423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1426014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochint Assembler::branch_offset(Label* L) {
1427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int target_pos;
1428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (L->is_bound()) {
1429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    target_pos = L->pos();
1430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
1431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (L->is_linked()) {
1432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Point to previous instruction that uses the link.
1433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      target_pos = L->pos();
1434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
1435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // First entry of the link chain points to itself.
1436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      target_pos = pc_offset();
1437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    L->link_to(pc_offset());
1439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Block the emission of the constant pool, since the branch instruction must
14423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // be emitted at the pc offset recorded by the label.
1443014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (!is_const_pool_blocked()) BlockConstPoolFor(1);
1444014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return target_pos - (pc_offset() + kPcLoadDelta);
1446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Branch instructions.
1450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::b(int branch_offset, Condition cond) {
1451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((branch_offset & 3) == 0);
1452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int imm24 = branch_offset >> 2;
1453958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  CHECK(is_int24(imm24));
14541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  emit(cond | B27 | B25 | (imm24 & kImm24Mask));
1455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (cond == al) {
14573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // Dead code is a good location to emit the constant pool.
1458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CheckConstPool(false, false);
14596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
1460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::bl(int branch_offset, Condition cond) {
1464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((branch_offset & 3) == 0);
1465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int imm24 = branch_offset >> 2;
1466958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  CHECK(is_int24(imm24));
14671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  emit(cond | B27 | B25 | B24 | (imm24 & kImm24Mask));
1468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1470f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochvoid Assembler::blx(int branch_offset) {
1471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((branch_offset & 1) == 0);
1472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int h = ((branch_offset & 2) >> 1)*B24;
1473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int imm24 = branch_offset >> 2;
1474958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  CHECK(is_int24(imm24));
14751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  emit(kSpecialCondition | B27 | B25 | h | (imm24 & kImm24Mask));
1476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1478f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochvoid Assembler::blx(Register target, Condition cond) {
1479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!target.is(pc));
14801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  emit(cond | B24 | B21 | 15*B16 | 15*B12 | 15*B8 | BLX | target.code());
1481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1483f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochvoid Assembler::bx(Register target, Condition cond) {
1484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!target.is(pc));  // use of pc is actually allowed, but discouraged
14851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  emit(cond | B24 | B21 | 15*B16 | 15*B12 | 15*B8 | BX | target.code());
1486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1489014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::b(Label* L, Condition cond) {
1490014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CheckBuffer();
1491014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  b(branch_offset(L), cond);
1492014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1493014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1494014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1495014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::bl(Label* L, Condition cond) {
1496014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CheckBuffer();
1497014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bl(branch_offset(L), cond);
1498014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1499014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1500014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1501014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::blx(Label* L) {
1502014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CheckBuffer();
1503014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  blx(branch_offset(L));
1504014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1505014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1506014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
15073100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Data-processing instructions.
15083100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::and_(Register dst, Register src1, const Operand& src2,
1510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     SBit s, Condition cond) {
15111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  addrmod1(cond | AND | s, src1, dst, src2);
1512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::eor(Register dst, Register src1, const Operand& src2,
1516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    SBit s, Condition cond) {
15171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  addrmod1(cond | EOR | s, src1, dst, src2);
1518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::sub(Register dst, Register src1, const Operand& src2,
1522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    SBit s, Condition cond) {
15231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  addrmod1(cond | SUB | s, src1, dst, src2);
1524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::rsb(Register dst, Register src1, const Operand& src2,
1528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    SBit s, Condition cond) {
15291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  addrmod1(cond | RSB | s, src1, dst, src2);
1530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::add(Register dst, Register src1, const Operand& src2,
1534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    SBit s, Condition cond) {
15351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  addrmod1(cond | ADD | s, src1, dst, src2);
1536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::adc(Register dst, Register src1, const Operand& src2,
1540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    SBit s, Condition cond) {
15411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  addrmod1(cond | ADC | s, src1, dst, src2);
1542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::sbc(Register dst, Register src1, const Operand& src2,
1546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    SBit s, Condition cond) {
15471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  addrmod1(cond | SBC | s, src1, dst, src2);
1548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::rsc(Register dst, Register src1, const Operand& src2,
1552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    SBit s, Condition cond) {
15531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  addrmod1(cond | RSC | s, src1, dst, src2);
1554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::tst(Register src1, const Operand& src2, Condition cond) {
15581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  addrmod1(cond | TST | S, src1, r0, src2);
1559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::teq(Register src1, const Operand& src2, Condition cond) {
15631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  addrmod1(cond | TEQ | S, src1, r0, src2);
1564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::cmp(Register src1, const Operand& src2, Condition cond) {
15681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  addrmod1(cond | CMP | S, src1, r0, src2);
15691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
15701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
15711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
15721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Assembler::cmp_raw_immediate(
15731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    Register src, int raw_immediate, Condition cond) {
1574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(is_uint12(raw_immediate));
15751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  emit(cond | I | CMP | S | src.code() << 16 | raw_immediate);
1576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::cmn(Register src1, const Operand& src2, Condition cond) {
15801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  addrmod1(cond | CMN | S, src1, r0, src2);
1581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::orr(Register dst, Register src1, const Operand& src2,
1585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    SBit s, Condition cond) {
15861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  addrmod1(cond | ORR | s, src1, dst, src2);
1587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::mov(Register dst, const Operand& src, SBit s, Condition cond) {
15916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Don't allow nop instructions in the form mov rn, rn to be generated using
15928a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // the mov instruction. They must be generated using nop(int/NopMarkerTypes)
15938a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // or MarkCode(int/NopMarkerTypes) pseudo instructions.
1594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!(src.is_reg() && src.rm().is(dst) && s == LeaveCC && cond == al));
15951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  addrmod1(cond | MOV | s, r0, dst, src);
1596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::mov_label_offset(Register dst, Label* label) {
1600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (label->is_bound()) {
1601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(dst, Operand(label->pos() + (Code::kHeaderSize - kHeapObjectTag)));
1602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Emit the link to the label in the code stream followed by extra nop
1604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // instructions.
1605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // If the label is not linked, then start a new link chain by linking it to
1606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // itself, emitting pc_offset().
1607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int link = label->is_linked() ? label->pos() : pc_offset();
1608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    label->link_to(pc_offset());
1609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // When the label is bound, these instructions will be patched with a
1611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // sequence of movw/movt or mov/orr/orr instructions. They will load the
1612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // destination register with the position of the label from the beginning
1613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // of the code.
1614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    //
1615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // The link will be extracted from the first instruction and the destination
1616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // register from the second.
1617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    //   For ARMv7:
1618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    //      link
1619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    //      mov dst, dst
1620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    //   For ARMv6:
1621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    //      link
1622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    //      mov dst, dst
1623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    //      mov dst, dst
1624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    //
1625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // When the label gets bound: target_at extracts the link and target_at_put
1626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // patches the instructions.
1627958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    CHECK(is_uint24(link));
1628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    BlockConstPoolScope block_const_pool(this);
1629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    emit(link);
1630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    nop(dst.code());
1631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!CpuFeatures::IsSupported(ARMv7)) {
1632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      nop(dst.code());
1633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
16389dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenvoid Assembler::movw(Register reg, uint32_t immediate, Condition cond) {
1639f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(IsEnabled(ARMv7));
1640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  emit(cond | 0x30*B20 | reg.code()*B12 | EncodeMovwImmediate(immediate));
16419dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
16429dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
16439dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
16449dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenvoid Assembler::movt(Register reg, uint32_t immediate, Condition cond) {
1645f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(IsEnabled(ARMv7));
16469dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  emit(cond | 0x34*B20 | reg.code()*B12 | EncodeMovwImmediate(immediate));
16479dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
16489dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
16499dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
1650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::bic(Register dst, Register src1, const Operand& src2,
1651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    SBit s, Condition cond) {
16521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  addrmod1(cond | BIC | s, src1, dst, src2);
1653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::mvn(Register dst, const Operand& src, SBit s, Condition cond) {
16571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  addrmod1(cond | MVN | s, r0, dst, src);
1658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
16613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Multiply instructions.
1662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::mla(Register dst, Register src1, Register src2, Register srcA,
1663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    SBit s, Condition cond) {
1664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dst.is(pc) && !src1.is(pc) && !src2.is(pc) && !srcA.is(pc));
1665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(cond | A | s | dst.code()*B16 | srcA.code()*B12 |
1666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       src2.code()*B8 | B7 | B4 | src1.code());
1667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::mls(Register dst, Register src1, Register src2, Register srcA,
1671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                    Condition cond) {
1672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dst.is(pc) && !src1.is(pc) && !src2.is(pc) && !srcA.is(pc));
167313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  DCHECK(IsEnabled(ARMv7));
1674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  emit(cond | B22 | B21 | dst.code()*B16 | srcA.code()*B12 |
1675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       src2.code()*B8 | B7 | B4 | src1.code());
1676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::sdiv(Register dst, Register src1, Register src2,
1680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     Condition cond) {
1681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dst.is(pc) && !src1.is(pc) && !src2.is(pc));
1682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsEnabled(SUDIV));
1683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  emit(cond | B26 | B25| B24 | B20 | dst.code()*B16 | 0xf * B12 |
1684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       src2.code()*B8 | B4 | src1.code());
1685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::udiv(Register dst, Register src1, Register src2,
1689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     Condition cond) {
1690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dst.is(pc) && !src1.is(pc) && !src2.is(pc));
1691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsEnabled(SUDIV));
1692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  emit(cond | B26 | B25 | B24 | B21 | B20 | dst.code() * B16 | 0xf * B12 |
1693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       src2.code() * B8 | B4 | src1.code());
1694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1697958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid Assembler::mul(Register dst, Register src1, Register src2, SBit s,
1698958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                    Condition cond) {
1699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dst.is(pc) && !src1.is(pc) && !src2.is(pc));
1700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // dst goes in bits 16-19 for this instruction!
1701958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  emit(cond | s | dst.code() * B16 | src2.code() * B8 | B7 | B4 | src1.code());
1702958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
1703958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1704958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1705958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid Assembler::smmla(Register dst, Register src1, Register src2, Register srcA,
1706958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                      Condition cond) {
1707958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(!dst.is(pc) && !src1.is(pc) && !src2.is(pc) && !srcA.is(pc));
1708958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  emit(cond | B26 | B25 | B24 | B22 | B20 | dst.code() * B16 |
1709958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier       srcA.code() * B12 | src2.code() * B8 | B4 | src1.code());
1710958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
1711958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1712958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1713958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid Assembler::smmul(Register dst, Register src1, Register src2,
1714958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                      Condition cond) {
1715958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(!dst.is(pc) && !src1.is(pc) && !src2.is(pc));
1716958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  emit(cond | B26 | B25 | B24 | B22 | B20 | dst.code() * B16 | 0xf * B12 |
1717958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier       src2.code() * B8 | B4 | src1.code());
1718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::smlal(Register dstL,
1722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Register dstH,
1723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Register src1,
1724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Register src2,
1725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      SBit s,
1726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Condition cond) {
1727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc));
1728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dstL.is(dstH));
1729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(cond | B23 | B22 | A | s | dstH.code()*B16 | dstL.code()*B12 |
1730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       src2.code()*B8 | B7 | B4 | src1.code());
1731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::smull(Register dstL,
1735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Register dstH,
1736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Register src1,
1737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Register src2,
1738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      SBit s,
1739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Condition cond) {
1740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc));
1741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dstL.is(dstH));
1742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(cond | B23 | B22 | s | dstH.code()*B16 | dstL.code()*B12 |
1743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       src2.code()*B8 | B7 | B4 | src1.code());
1744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::umlal(Register dstL,
1748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Register dstH,
1749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Register src1,
1750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Register src2,
1751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      SBit s,
1752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Condition cond) {
1753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc));
1754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dstL.is(dstH));
1755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(cond | B23 | A | s | dstH.code()*B16 | dstL.code()*B12 |
1756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       src2.code()*B8 | B7 | B4 | src1.code());
1757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::umull(Register dstL,
1761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Register dstH,
1762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Register src1,
1763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Register src2,
1764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      SBit s,
1765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Condition cond) {
1766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc));
1767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dstL.is(dstH));
1768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(cond | B23 | s | dstH.code()*B16 | dstL.code()*B12 |
1769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       src2.code()*B8 | B7 | B4 | src1.code());
1770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
17733100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Miscellaneous arithmetic instructions.
1774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::clz(Register dst, Register src, Condition cond) {
1775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dst.is(pc) && !src.is(pc));
1776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(cond | B24 | B22 | B21 | 15*B16 | dst.code()*B12 |
17771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block       15*B8 | CLZ | src.code());
1778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
178150ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen// Saturating instructions.
178250ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen
178350ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen// Unsigned saturate.
178450ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsenvoid Assembler::usat(Register dst,
178550ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen                     int satpos,
178650ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen                     const Operand& src,
178750ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen                     Condition cond) {
1788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dst.is(pc) && !src.rm_.is(pc));
1789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((satpos >= 0) && (satpos <= 31));
1790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((src.shift_op_ == ASR) || (src.shift_op_ == LSL));
1791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(src.rs_.is(no_reg));
179250ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen
179350ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  int sh = 0;
179450ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  if (src.shift_op_ == ASR) {
179550ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen      sh = 1;
179650ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  }
179750ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen
179850ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  emit(cond | 0x6*B24 | 0xe*B20 | satpos*B16 | dst.code()*B12 |
179950ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen       src.shift_imm_*B7 | sh*B6 | 0x1*B4 | src.rm_.code());
180050ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen}
180150ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen
180250ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen
18037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// Bitfield manipulation instructions.
18047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
18057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// Unsigned bit field extract.
18067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// Extracts #width adjacent bits from position #lsb in a register, and
18077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// writes them to the low bits of a destination register.
18087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch//   ubfx dst, src, #lsb, #width
18097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid Assembler::ubfx(Register dst,
18107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                     Register src,
18117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                     int lsb,
18127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                     int width,
18137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                     Condition cond) {
1814f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(IsEnabled(ARMv7));
1815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dst.is(pc) && !src.is(pc));
1816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((lsb >= 0) && (lsb <= 31));
1817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((width >= 1) && (width <= (32 - lsb)));
18187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  emit(cond | 0xf*B23 | B22 | B21 | (width - 1)*B16 | dst.code()*B12 |
18197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch       lsb*B7 | B6 | B4 | src.code());
18207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
18217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
18227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
18237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// Signed bit field extract.
18247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// Extracts #width adjacent bits from position #lsb in a register, and
18257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// writes them to the low bits of a destination register. The extracted
18267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// value is sign extended to fill the destination register.
18277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch//   sbfx dst, src, #lsb, #width
18287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid Assembler::sbfx(Register dst,
18297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                     Register src,
18307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                     int lsb,
18317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                     int width,
18327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                     Condition cond) {
1833f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(IsEnabled(ARMv7));
1834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dst.is(pc) && !src.is(pc));
1835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((lsb >= 0) && (lsb <= 31));
1836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((width >= 1) && (width <= (32 - lsb)));
18377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  emit(cond | 0xf*B23 | B21 | (width - 1)*B16 | dst.code()*B12 |
18387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch       lsb*B7 | B6 | B4 | src.code());
18397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
18407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
18417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
18427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// Bit field clear.
18437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// Sets #width adjacent bits at position #lsb in the destination register
18447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// to zero, preserving the value of the other bits.
18457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch//   bfc dst, #lsb, #width
18467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid Assembler::bfc(Register dst, int lsb, int width, Condition cond) {
1847f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(IsEnabled(ARMv7));
1848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dst.is(pc));
1849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((lsb >= 0) && (lsb <= 31));
1850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((width >= 1) && (width <= (32 - lsb)));
18517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  int msb = lsb + width - 1;
18527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  emit(cond | 0x1f*B22 | msb*B16 | dst.code()*B12 | lsb*B7 | B4 | 0xf);
18537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
18547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
18557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
18567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// Bit field insert.
18577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// Inserts #width adjacent bits from the low bits of the source register
18587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// into position #lsb of the destination register.
18597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch//   bfi dst, src, #lsb, #width
18607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid Assembler::bfi(Register dst,
18617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                    Register src,
18627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                    int lsb,
18637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                    int width,
18647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                    Condition cond) {
1865f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(IsEnabled(ARMv7));
1866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dst.is(pc) && !src.is(pc));
1867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((lsb >= 0) && (lsb <= 31));
1868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((width >= 1) && (width <= (32 - lsb)));
18697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  int msb = lsb + width - 1;
18707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  emit(cond | 0x1f*B22 | msb*B16 | dst.code()*B12 | lsb*B7 | B4 |
18717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch       src.code());
18727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
18737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
18747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::pkhbt(Register dst,
1876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      Register src1,
1877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      const Operand& src2,
1878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      Condition cond ) {
1879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8.8.125.
1880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // cond(31-28) | 01101000(27-20) | Rn(19-16) |
1881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Rd(15-12) | imm5(11-7) | 0(6) | 01(5-4) | Rm(3-0)
1882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dst.is(pc));
1883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!src1.is(pc));
1884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!src2.rm().is(pc));
1885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!src2.rm().is(no_reg));
1886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(src2.rs().is(no_reg));
1887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((src2.shift_imm_ >= 0) && (src2.shift_imm_ <= 31));
1888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(src2.shift_op() == LSL);
1889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  emit(cond | 0x68*B20 | src1.code()*B16 | dst.code()*B12 |
1890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       src2.shift_imm_*B7 | B4 | src2.rm().code());
1891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::pkhtb(Register dst,
1895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      Register src1,
1896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      const Operand& src2,
1897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      Condition cond) {
1898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8.8.125.
1899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // cond(31-28) | 01101000(27-20) | Rn(19-16) |
1900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Rd(15-12) | imm5(11-7) | 1(6) | 01(5-4) | Rm(3-0)
1901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dst.is(pc));
1902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!src1.is(pc));
1903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!src2.rm().is(pc));
1904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!src2.rm().is(no_reg));
1905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(src2.rs().is(no_reg));
1906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((src2.shift_imm_ >= 1) && (src2.shift_imm_ <= 32));
1907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(src2.shift_op() == ASR);
1908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int asr = (src2.shift_imm_ == 32) ? 0 : src2.shift_imm_;
1909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  emit(cond | 0x68*B20 | src1.code()*B16 | dst.code()*B12 |
1910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       asr*B7 | B6 | B4 | src2.rm().code());
1911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1914958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid Assembler::sxtb(Register dst, Register src, int rotate, Condition cond) {
1915958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Instruction details available in ARM DDI 0406C.b, A8.8.233.
1916958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // cond(31-28) | 01101010(27-20) | 1111(19-16) |
1917958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Rd(15-12) | rotate(11-10) | 00(9-8)| 0111(7-4) | Rm(3-0)
1918958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(!dst.is(pc));
1919958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(!src.is(pc));
1920958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(rotate == 0 || rotate == 8 || rotate == 16 || rotate == 24);
1921958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  emit(cond | 0x6A * B20 | 0xF * B16 | dst.code() * B12 |
1922958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier       ((rotate >> 1) & 0xC) * B8 | 7 * B4 | src.code());
1923958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
1924958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1925958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1926958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid Assembler::sxtab(Register dst, Register src1, Register src2, int rotate,
1927958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                      Condition cond) {
1928958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Instruction details available in ARM DDI 0406C.b, A8.8.233.
1929958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // cond(31-28) | 01101010(27-20) | Rn(19-16) |
1930958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Rd(15-12) | rotate(11-10) | 00(9-8)| 0111(7-4) | Rm(3-0)
1931958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(!dst.is(pc));
1932958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(!src1.is(pc));
1933958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(!src2.is(pc));
1934958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(rotate == 0 || rotate == 8 || rotate == 16 || rotate == 24);
1935958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  emit(cond | 0x6A * B20 | src1.code() * B16 | dst.code() * B12 |
1936958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier       ((rotate >> 1) & 0xC) * B8 | 7 * B4 | src2.code());
1937958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
1938958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1939958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1940958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid Assembler::sxth(Register dst, Register src, int rotate, Condition cond) {
1941958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Instruction details available in ARM DDI 0406C.b, A8.8.235.
1942958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // cond(31-28) | 01101011(27-20) | 1111(19-16) |
1943958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Rd(15-12) | rotate(11-10) | 00(9-8)| 0111(7-4) | Rm(3-0)
1944958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(!dst.is(pc));
1945958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(!src.is(pc));
1946958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(rotate == 0 || rotate == 8 || rotate == 16 || rotate == 24);
1947958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  emit(cond | 0x6B * B20 | 0xF * B16 | dst.code() * B12 |
1948958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier       ((rotate >> 1) & 0xC) * B8 | 7 * B4 | src.code());
1949958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
1950958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1951958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1952958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid Assembler::sxtah(Register dst, Register src1, Register src2, int rotate,
1953958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                      Condition cond) {
1954958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Instruction details available in ARM DDI 0406C.b, A8.8.235.
1955958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // cond(31-28) | 01101011(27-20) | Rn(19-16) |
1956958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Rd(15-12) | rotate(11-10) | 00(9-8)| 0111(7-4) | Rm(3-0)
1957958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(!dst.is(pc));
1958958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(!src1.is(pc));
1959958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(!src2.is(pc));
1960958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(rotate == 0 || rotate == 8 || rotate == 16 || rotate == 24);
1961958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  emit(cond | 0x6B * B20 | src1.code() * B16 | dst.code() * B12 |
1962958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier       ((rotate >> 1) & 0xC) * B8 | 7 * B4 | src2.code());
1963958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
1964958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1965958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1966958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid Assembler::uxtb(Register dst, Register src, int rotate, Condition cond) {
1967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8.8.274.
1968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // cond(31-28) | 01101110(27-20) | 1111(19-16) |
1969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Rd(15-12) | rotate(11-10) | 00(9-8)| 0111(7-4) | Rm(3-0)
1970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dst.is(pc));
1971958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(!src.is(pc));
1972958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(rotate == 0 || rotate == 8 || rotate == 16 || rotate == 24);
1973958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  emit(cond | 0x6E * B20 | 0xF * B16 | dst.code() * B12 |
1974958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier       ((rotate >> 1) & 0xC) * B8 | 7 * B4 | src.code());
1975958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
1976958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1977958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1978958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid Assembler::uxtab(Register dst, Register src1, Register src2, int rotate,
1979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      Condition cond) {
1980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8.8.271.
1981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // cond(31-28) | 01101110(27-20) | Rn(19-16) |
1982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Rd(15-12) | rotate(11-10) | 00(9-8)| 0111(7-4) | Rm(3-0)
1983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dst.is(pc));
1984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!src1.is(pc));
1985958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(!src2.is(pc));
1986958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(rotate == 0 || rotate == 8 || rotate == 16 || rotate == 24);
1987958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  emit(cond | 0x6E * B20 | src1.code() * B16 | dst.code() * B12 |
1988958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier       ((rotate >> 1) & 0xC) * B8 | 7 * B4 | src2.code());
1989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1992958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid Assembler::uxtb16(Register dst, Register src, int rotate, Condition cond) {
1993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8.8.275.
1994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // cond(31-28) | 01101100(27-20) | 1111(19-16) |
1995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Rd(15-12) | rotate(11-10) | 00(9-8)| 0111(7-4) | Rm(3-0)
1996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dst.is(pc));
1997958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(!src.is(pc));
1998958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(rotate == 0 || rotate == 8 || rotate == 16 || rotate == 24);
1999958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  emit(cond | 0x6C * B20 | 0xF * B16 | dst.code() * B12 |
2000958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier       ((rotate >> 1) & 0xC) * B8 | 7 * B4 | src.code());
2001958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
2002958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2003958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2004958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid Assembler::uxth(Register dst, Register src, int rotate, Condition cond) {
2005958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Instruction details available in ARM DDI 0406C.b, A8.8.276.
2006958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // cond(31-28) | 01101111(27-20) | 1111(19-16) |
2007958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Rd(15-12) | rotate(11-10) | 00(9-8)| 0111(7-4) | Rm(3-0)
2008958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(!dst.is(pc));
2009958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(!src.is(pc));
2010958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(rotate == 0 || rotate == 8 || rotate == 16 || rotate == 24);
2011958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  emit(cond | 0x6F * B20 | 0xF * B16 | dst.code() * B12 |
2012958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier       ((rotate >> 1) & 0xC) * B8 | 7 * B4 | src.code());
2013958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
2014958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2015958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2016958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid Assembler::uxtah(Register dst, Register src1, Register src2, int rotate,
2017958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                      Condition cond) {
2018958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Instruction details available in ARM DDI 0406C.b, A8.8.273.
2019958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // cond(31-28) | 01101111(27-20) | Rn(19-16) |
2020958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Rd(15-12) | rotate(11-10) | 00(9-8)| 0111(7-4) | Rm(3-0)
2021958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(!dst.is(pc));
2022958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(!src1.is(pc));
2023958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(!src2.is(pc));
2024958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(rotate == 0 || rotate == 8 || rotate == 16 || rotate == 24);
2025958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  emit(cond | 0x6F * B20 | src1.code() * B16 | dst.code() * B12 |
2026958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier       ((rotate >> 1) & 0xC) * B8 | 7 * B4 | src2.code());
2027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2030109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid Assembler::rbit(Register dst, Register src, Condition cond) {
2031109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Instruction details available in ARM DDI 0406C.b, A8.8.144.
2032109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // cond(31-28) | 011011111111(27-16) | Rd(15-12) | 11110011(11-4) | Rm(3-0)
2033109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  DCHECK(IsEnabled(ARMv7));
2034109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  DCHECK(!dst.is(pc));
2035109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  DCHECK(!src.is(pc));
2036109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  emit(cond | 0x6FF * B16 | dst.code() * B12 | 0xF3 * B4 | src.code());
2037109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
2038109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
2039109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
20403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Status register access instructions.
2041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::mrs(Register dst, SRegister s, Condition cond) {
2042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dst.is(pc));
2043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(cond | B24 | s | 15*B16 | dst.code()*B12);
2044a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2045a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::msr(SRegisterFieldMask fields, const Operand& src,
2048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Condition cond) {
20493b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK((fields & 0x000f0000) != 0);  // At least one field must be set.
20503b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK(((fields & 0xfff0ffff) == CPSR) || ((fields & 0xfff0ffff) == SPSR));
2051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Instr instr;
2052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!src.rm_.is_valid()) {
20533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // Immediate.
2054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    uint32_t rotate_imm;
2055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    uint32_t immed_8;
2056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (src.must_output_reloc_info(this) ||
2057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        !fits_shifter(src.imm32_, &rotate_imm, &immed_8, NULL)) {
20583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      // Immediate operand cannot be encoded, load it first to register ip.
2059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      move_32_bit_immediate(ip, src);
2060a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      msr(fields, Operand(ip), cond);
2061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return;
2062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    instr = I | rotate_imm*B8 | immed_8;
2064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
2065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!src.rs_.is_valid() && src.shift_imm_ == 0);  // only rm allowed
2066a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    instr = src.rm_.code();
2067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(cond | instr | B24 | B21 | fields | 15*B12);
2069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
20723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Load/Store instructions.
2073a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::ldr(Register dst, const MemOperand& src, Condition cond) {
2074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  addrmod2(cond | B26 | L, dst, src);
2075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2076a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2078a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::str(Register src, const MemOperand& dst, Condition cond) {
2079a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  addrmod2(cond | B26, src, dst);
2080a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2082a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2083a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::ldrb(Register dst, const MemOperand& src, Condition cond) {
2084a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  addrmod2(cond | B26 | B | L, dst, src);
2085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2086a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2087a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::strb(Register src, const MemOperand& dst, Condition cond) {
2089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  addrmod2(cond | B26 | B, src, dst);
2090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::ldrh(Register dst, const MemOperand& src, Condition cond) {
2094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  addrmod3(cond | L | B7 | H | B4, dst, src);
2095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::strh(Register src, const MemOperand& dst, Condition cond) {
2099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  addrmod3(cond | B7 | H | B4, src, dst);
2100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::ldrsb(Register dst, const MemOperand& src, Condition cond) {
2104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  addrmod3(cond | L | B7 | S6 | B4, dst, src);
2105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::ldrsh(Register dst, const MemOperand& src, Condition cond) {
2109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  addrmod3(cond | L | B7 | S6 | H | B4, dst, src);
2110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2113f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid Assembler::ldrd(Register dst1, Register dst2,
2114f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                     const MemOperand& src, Condition cond) {
2115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(src.rm().is(no_reg));
2116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dst1.is(lr));  // r14.
2117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(0, dst1.code() % 2);
2118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(dst1.code() + 1, dst2.code());
2119f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  addrmod3(cond | B7 | B6 | B4, dst1, src);
212025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen}
212125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
212225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
2123f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid Assembler::strd(Register src1, Register src2,
2124f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                     const MemOperand& dst, Condition cond) {
2125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(dst.rm().is(no_reg));
2126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!src1.is(lr));  // r14.
2127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(0, src1.code() % 2);
2128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(src1.code() + 1, src2.code());
2129f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  addrmod3(cond | B7 | B6 | B5 | B4, src1, dst);
213025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen}
213125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
213213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch// Load/Store exclusive instructions.
213313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid Assembler::ldrex(Register dst, Register src, Condition cond) {
213413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8.8.75.
213513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // cond(31-28) | 00011001(27-20) | Rn(19-16) | Rt(15-12) | 111110011111(11-0)
213613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  emit(cond | B24 | B23 | B20 | src.code() * B16 | dst.code() * B12 | 0xf9f);
213713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
213813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
213913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid Assembler::strex(Register src1, Register src2, Register dst,
214013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                      Condition cond) {
214113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8.8.212.
214213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // cond(31-28) | 00011000(27-20) | Rn(19-16) | Rd(15-12) | 11111001(11-4) |
214313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // Rt(3-0)
214413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  emit(cond | B24 | B23 | dst.code() * B16 | src1.code() * B12 | 0xf9 * B4 |
214513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch       src2.code());
214613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
214713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
214813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid Assembler::ldrexb(Register dst, Register src, Condition cond) {
214913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8.8.76.
215013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // cond(31-28) | 00011101(27-20) | Rn(19-16) | Rt(15-12) | 111110011111(11-0)
215113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  emit(cond | B24 | B23 | B22 | B20 | src.code() * B16 | dst.code() * B12 |
215213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch       0xf9f);
215313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
215413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
215513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid Assembler::strexb(Register src1, Register src2, Register dst,
215613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                       Condition cond) {
215713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8.8.213.
215813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // cond(31-28) | 00011100(27-20) | Rn(19-16) | Rd(15-12) | 11111001(11-4) |
215913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // Rt(3-0)
216013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  emit(cond | B24 | B23 | B22 | dst.code() * B16 | src1.code() * B12 |
216113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch       0xf9 * B4 | src2.code());
216213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
216313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
216413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid Assembler::ldrexh(Register dst, Register src, Condition cond) {
216513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8.8.78.
216613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // cond(31-28) | 00011111(27-20) | Rn(19-16) | Rt(15-12) | 111110011111(11-0)
216713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  emit(cond | B24 | B23 | B22 | B21 | B20 | src.code() * B16 |
216813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch       dst.code() * B12 | 0xf9f);
216913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
217013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
217113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid Assembler::strexh(Register src1, Register src2, Register dst,
217213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                       Condition cond) {
217313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8.8.215.
217413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // cond(31-28) | 00011110(27-20) | Rn(19-16) | Rd(15-12) | 11111001(11-4) |
217513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // Rt(3-0)
217613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  emit(cond | B24 | B23 | B22 | B21 | dst.code() * B16 | src1.code() * B12 |
217713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch       0xf9 * B4 | src2.code());
217813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
2179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Preload instructions.
2181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::pld(const MemOperand& address) {
2182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8.8.128.
2183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // 1111(31-28) | 0111(27-24) | U(23) | R(22) | 01(21-20) | Rn(19-16) |
2184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // 1111(15-12) | imm5(11-07) | type(6-5) | 0(4)| Rm(3-0) |
2185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(address.rm().is(no_reg));
2186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(address.am() == Offset);
2187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int U = B23;
2188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int offset = address.offset();
2189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (offset < 0) {
2190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    offset = -offset;
2191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    U = 0;
2192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(offset < 4096);
2194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  emit(kSpecialCondition | B26 | B24 | U | B22 | B20 | address.rn().code()*B16 |
2195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       0xf*B12 | offset);
2196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Load/Store multiple instructions.
2200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::ldm(BlockAddrMode am,
2201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Register base,
2202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    RegList dst,
2203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Condition cond) {
22043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // ABI stack constraint: ldmxx base, {..sp..}  base != sp  is not restartable.
2205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(base.is(sp) || (dst & sp.bit()) == 0);
2206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  addrmod4(cond | B27 | am | L, base, dst);
2208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
22093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Emit the constant pool after a function return implemented by ldm ..{..pc}.
2210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (cond == al && (dst & pc.bit()) != 0) {
2211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // There is a slight chance that the ldm instruction was actually a call,
2212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // in which case it would be wrong to return into the constant pool; we
2213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // recognize this case by checking if the emission of the pool was blocked
2214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // at the pc of the ldm instruction by a mov lr, pc instruction; if this is
2215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // the case, we emit a jump over the pool.
2216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CheckConstPool(true, no_const_pool_before_ == pc_offset() - kInstrSize);
2217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::stm(BlockAddrMode am,
2222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Register base,
2223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    RegList src,
2224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Condition cond) {
2225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  addrmod4(cond | B27 | am, base, src);
2226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
22293100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Exception-generating instructions and debugging support.
22303e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu// Stops with a non-negative code less than kNumOfWatchedStops support
22313e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu// enabling/disabling and a counter feature. See simulator-arm.h .
22323e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhuvoid Assembler::stop(const char* msg, Condition cond, int32_t code) {
2233402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu#ifndef __arm__
2234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(code >= kDefaultStopCode);
22353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  {
22363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // The Simulator will handle the stop instruction and get the message
22373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // address. It expects to find the address just after the svc instruction.
22383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    BlockConstPoolScope block_const_pool(this);
22393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (code >= 0) {
22403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      svc(kStopCode + code, cond);
22413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    } else {
22423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      svc(kStopCode + kMaxStopCode, cond);
22433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
2244f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // Do not embed the message string address! We used to do this, but that
2245f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // made snapshots created from position-independent executable builds
2246f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // non-deterministic.
2247f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // TODO(yangguo): remove this field entirely.
2248f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    nop();
22493e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  }
2250402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu#else  // def __arm__
22511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (cond != al) {
22521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    Label skip;
22531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    b(&skip, NegateCondition(cond));
22541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    bkpt(0);
22551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    bind(&skip);
22561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  } else {
22571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    bkpt(0);
22581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
2259402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu#endif  // def __arm__
2260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2262f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochvoid Assembler::bkpt(uint32_t imm16) {
2263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(is_uint16(imm16));
22641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  emit(al | B24 | B21 | (imm16 >> 4)*B8 | BKPT | (imm16 & 0xf));
2265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
22683e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhuvoid Assembler::svc(uint32_t imm24, Condition cond) {
2269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(is_uint24(imm24));
2270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(cond | 15*B24 | imm24);
2271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2274109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid Assembler::dmb(BarrierOption option) {
2275f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  if (CpuFeatures::IsSupported(ARMv7)) {
2276f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    // Details available in ARM DDI 0406C.b, A8-378.
2277f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    emit(kSpecialCondition | 0x57ff * B12 | 5 * B4 | option);
2278f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  } else {
2279f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    // Details available in ARM DDI 0406C.b, B3-1750.
2280f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    // CP15DMB: CRn=c7, opc1=0, CRm=c10, opc2=5, Rt is ignored.
2281f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    mcr(p15, 0, r0, cr7, cr10, 5);
2282f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  }
2283109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
2284109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
2285109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
2286109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid Assembler::dsb(BarrierOption option) {
2287f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  if (CpuFeatures::IsSupported(ARMv7)) {
2288f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    // Details available in ARM DDI 0406C.b, A8-380.
2289f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    emit(kSpecialCondition | 0x57ff * B12 | 4 * B4 | option);
2290f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  } else {
2291f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    // Details available in ARM DDI 0406C.b, B3-1750.
2292f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    // CP15DSB: CRn=c7, opc1=0, CRm=c10, opc2=4, Rt is ignored.
2293f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    mcr(p15, 0, r0, cr7, cr10, 4);
2294f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  }
2295109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
2296109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
2297109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
2298109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid Assembler::isb(BarrierOption option) {
2299f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  if (CpuFeatures::IsSupported(ARMv7)) {
2300f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    // Details available in ARM DDI 0406C.b, A8-389.
2301f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    emit(kSpecialCondition | 0x57ff * B12 | 6 * B4 | option);
2302f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  } else {
2303f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    // Details available in ARM DDI 0406C.b, B3-1750.
2304f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    // CP15ISB: CRn=c7, opc1=0, CRm=c5, opc2=4, Rt is ignored.
2305f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    mcr(p15, 0, r0, cr7, cr5, 4);
2306f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  }
2307109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
2308109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
2309109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
23103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Coprocessor instructions.
2311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::cdp(Coprocessor coproc,
2312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    int opcode_1,
2313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    CRegister crd,
2314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    CRegister crn,
2315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    CRegister crm,
2316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    int opcode_2,
2317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Condition cond) {
2318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(is_uint4(opcode_1) && is_uint3(opcode_2));
2319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(cond | B27 | B26 | B25 | (opcode_1 & 15)*B20 | crn.code()*B16 |
2320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       crd.code()*B12 | coproc*B8 | (opcode_2 & 7)*B5 | crm.code());
2321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2323f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochvoid Assembler::cdp2(Coprocessor coproc, int opcode_1, CRegister crd,
2324f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                     CRegister crn, CRegister crm, int opcode_2) {
23251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  cdp(coproc, opcode_1, crd, crn, crm, opcode_2, kSpecialCondition);
2326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::mcr(Coprocessor coproc,
2330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    int opcode_1,
2331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Register rd,
2332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    CRegister crn,
2333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    CRegister crm,
2334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    int opcode_2,
2335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Condition cond) {
2336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(is_uint3(opcode_1) && is_uint3(opcode_2));
2337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(cond | B27 | B26 | B25 | (opcode_1 & 7)*B21 | crn.code()*B16 |
2338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       rd.code()*B12 | coproc*B8 | (opcode_2 & 7)*B5 | B4 | crm.code());
2339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2341f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochvoid Assembler::mcr2(Coprocessor coproc, int opcode_1, Register rd,
2342f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                     CRegister crn, CRegister crm, int opcode_2) {
23431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  mcr(coproc, opcode_1, rd, crn, crm, opcode_2, kSpecialCondition);
2344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::mrc(Coprocessor coproc,
2348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    int opcode_1,
2349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Register rd,
2350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    CRegister crn,
2351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    CRegister crm,
2352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    int opcode_2,
2353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Condition cond) {
2354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(is_uint3(opcode_1) && is_uint3(opcode_2));
2355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(cond | B27 | B26 | B25 | (opcode_1 & 7)*B21 | L | crn.code()*B16 |
2356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       rd.code()*B12 | coproc*B8 | (opcode_2 & 7)*B5 | B4 | crm.code());
2357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2359f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochvoid Assembler::mrc2(Coprocessor coproc, int opcode_1, Register rd,
2360f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                     CRegister crn, CRegister crm, int opcode_2) {
23611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  mrc(coproc, opcode_1, rd, crn, crm, opcode_2, kSpecialCondition);
2362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::ldc(Coprocessor coproc,
2366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    CRegister crd,
2367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    const MemOperand& src,
2368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    LFlag l,
2369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Condition cond) {
2370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  addrmod5(cond | B27 | B26 | l | L | coproc*B8, crd, src);
2371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::ldc(Coprocessor coproc,
2375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    CRegister crd,
2376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Register rn,
2377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    int option,
2378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    LFlag l,
2379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Condition cond) {
23803100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Unindexed addressing.
2381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(is_uint8(option));
2382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(cond | B27 | B26 | U | l | L | rn.code()*B16 | crd.code()*B12 |
2383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       coproc*B8 | (option & 255));
2384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2386f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochvoid Assembler::ldc2(Coprocessor coproc, CRegister crd, const MemOperand& src,
2387f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                     LFlag l) {
23881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ldc(coproc, crd, src, l, kSpecialCondition);
2389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2391f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochvoid Assembler::ldc2(Coprocessor coproc, CRegister crd, Register rn, int option,
2392f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                     LFlag l) {
23931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ldc(coproc, crd, rn, option, l, kSpecialCondition);
2394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2397d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// Support for VFP.
239880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
2399d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid Assembler::vldr(const DwVfpRegister dst,
2400d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                     const Register base,
2401d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                     int offset,
2402d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                     const Condition cond) {
2403d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Ddst = MEM(Rbase + offset).
2404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8-924.
2405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // cond(31-28) | 1101(27-24)| U(23) | D(22) | 01(21-20) | Rbase(19-16) |
2406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Vd(15-12) | 1011(11-8) | offset
2407f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(VfpRegisterIsAvailable(dst));
2408b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int u = 1;
2409b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (offset < 0) {
2410014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CHECK(offset != kMinInt);
2411b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    offset = -offset;
2412b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    u = 0;
2413b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int vd, d;
2415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  dst.split_code(&vd, &d);
2416e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(offset >= 0);
2418e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if ((offset % 4) == 0 && (offset / 4) < 256) {
2419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    emit(cond | 0xD*B24 | u*B23 | d*B22 | B20 | base.code()*B16 | vd*B12 |
2420e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch         0xB*B8 | ((offset / 4) & 255));
2421e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  } else {
2422e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Larger offsets must be handled by computing the correct address
2423e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // in the ip register.
2424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!base.is(ip));
2425e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (u == 1) {
2426e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      add(ip, base, Operand(offset));
2427e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    } else {
2428e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      sub(ip, base, Operand(offset));
2429e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
2430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    emit(cond | 0xD*B24 | d*B22 | B20 | ip.code()*B16 | vd*B12 | 0xB*B8);
2431e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
2432e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2433e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2434e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2435e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid Assembler::vldr(const DwVfpRegister dst,
2436e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                     const MemOperand& operand,
2437e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                     const Condition cond) {
2438f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(VfpRegisterIsAvailable(dst));
2439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(operand.am_ == Offset);
2440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (operand.rm().is_valid()) {
2441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    add(ip, operand.rn(),
2442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Operand(operand.rm(), operand.shift_op_, operand.shift_imm_));
2443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    vldr(dst, ip, 0, cond);
2444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    vldr(dst, operand.rn(), operand.offset(), cond);
2446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2447d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
2448d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
2449d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
24506ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid Assembler::vldr(const SwVfpRegister dst,
24516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                     const Register base,
24526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                     int offset,
24536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                     const Condition cond) {
24546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Sdst = MEM(Rbase + offset).
24556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Instruction details available in ARM DDI 0406A, A8-628.
2456b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // cond(31-28) | 1101(27-24)| U001(23-20) | Rbase(19-16) |
24576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Vdst(15-12) | 1010(11-8) | offset
2458b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int u = 1;
2459b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (offset < 0) {
2460b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    offset = -offset;
2461b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    u = 0;
2462b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
246380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  int sd, d;
246480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  dst.split_code(&sd, &d);
2465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(offset >= 0);
2466e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2467e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if ((offset % 4) == 0 && (offset / 4) < 256) {
2468b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  emit(cond | u*B23 | d*B22 | 0xD1*B20 | base.code()*B16 | sd*B12 |
24696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block       0xA*B8 | ((offset / 4) & 255));
2470e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  } else {
2471e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Larger offsets must be handled by computing the correct address
2472e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // in the ip register.
2473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!base.is(ip));
2474e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (u == 1) {
2475e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      add(ip, base, Operand(offset));
2476e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    } else {
2477e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      sub(ip, base, Operand(offset));
2478e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
2479e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    emit(cond | d*B22 | 0xD1*B20 | ip.code()*B16 | sd*B12 | 0xA*B8);
2480e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
2481e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2482e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2483e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2484e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid Assembler::vldr(const SwVfpRegister dst,
2485e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                     const MemOperand& operand,
2486e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                     const Condition cond) {
2487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(operand.am_ == Offset);
2488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (operand.rm().is_valid()) {
2489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    add(ip, operand.rn(),
2490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Operand(operand.rm(), operand.shift_op_, operand.shift_imm_));
2491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    vldr(dst, ip, 0, cond);
2492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    vldr(dst, operand.rn(), operand.offset(), cond);
2494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
24956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
24966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
24976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2498d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid Assembler::vstr(const DwVfpRegister src,
2499d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                     const Register base,
2500d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                     int offset,
2501d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                     const Condition cond) {
2502d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // MEM(Rbase + offset) = Dsrc.
2503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8-1082.
2504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // cond(31-28) | 1101(27-24)| U(23) | D(22) | 00(21-20) | Rbase(19-16) |
2505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Vd(15-12) | 1011(11-8) | (offset/4)
2506f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(VfpRegisterIsAvailable(src));
2507b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int u = 1;
2508b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (offset < 0) {
2509014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CHECK(offset != kMinInt);
2510b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    offset = -offset;
2511b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    u = 0;
2512b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(offset >= 0);
2514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int vd, d;
2515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  src.split_code(&vd, &d);
2516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2517e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if ((offset % 4) == 0 && (offset / 4) < 256) {
2518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    emit(cond | 0xD*B24 | u*B23 | d*B22 | base.code()*B16 | vd*B12 | 0xB*B8 |
2519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         ((offset / 4) & 255));
2520e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  } else {
2521e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Larger offsets must be handled by computing the correct address
2522e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // in the ip register.
2523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!base.is(ip));
2524e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (u == 1) {
2525e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      add(ip, base, Operand(offset));
2526e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    } else {
2527e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      sub(ip, base, Operand(offset));
2528e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
2529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    emit(cond | 0xD*B24 | d*B22 | ip.code()*B16 | vd*B12 | 0xB*B8);
2530e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
2531e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2532e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2533e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2534e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid Assembler::vstr(const DwVfpRegister src,
2535e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                     const MemOperand& operand,
2536e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                     const Condition cond) {
2537f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(VfpRegisterIsAvailable(src));
2538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(operand.am_ == Offset);
2539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (operand.rm().is_valid()) {
2540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    add(ip, operand.rn(),
2541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Operand(operand.rm(), operand.shift_op_, operand.shift_imm_));
2542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    vstr(src, ip, 0, cond);
2543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    vstr(src, operand.rn(), operand.offset(), cond);
2545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2546d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
2547d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
2548d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
2549756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid Assembler::vstr(const SwVfpRegister src,
2550756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                     const Register base,
2551756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                     int offset,
2552756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                     const Condition cond) {
2553756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // MEM(Rbase + offset) = SSrc.
2554756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Instruction details available in ARM DDI 0406A, A8-786.
2555b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // cond(31-28) | 1101(27-24)| U000(23-20) | Rbase(19-16) |
2556756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Vdst(15-12) | 1010(11-8) | (offset/4)
2557b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int u = 1;
2558b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (offset < 0) {
2559014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CHECK(offset != kMinInt);
2560b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    offset = -offset;
2561b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    u = 0;
2562b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
256380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  int sd, d;
256480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  src.split_code(&sd, &d);
2565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(offset >= 0);
2566e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if ((offset % 4) == 0 && (offset / 4) < 256) {
2567e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    emit(cond | u*B23 | d*B22 | 0xD0*B20 | base.code()*B16 | sd*B12 |
2568e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch         0xA*B8 | ((offset / 4) & 255));
2569e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  } else {
2570e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Larger offsets must be handled by computing the correct address
2571e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // in the ip register.
2572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!base.is(ip));
2573e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (u == 1) {
2574e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      add(ip, base, Operand(offset));
2575e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    } else {
2576e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      sub(ip, base, Operand(offset));
2577e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
2578e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    emit(cond | d*B22 | 0xD0*B20 | ip.code()*B16 | sd*B12 | 0xA*B8);
2579e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
2580e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2581e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2582e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2583e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid Assembler::vstr(const SwVfpRegister src,
2584e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                     const MemOperand& operand,
2585e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                     const Condition cond) {
2586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(operand.am_ == Offset);
2587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (operand.rm().is_valid()) {
2588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    add(ip, operand.rn(),
2589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Operand(operand.rm(), operand.shift_op_, operand.shift_imm_));
2590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    vstr(src, ip, 0, cond);
2591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    vstr(src, operand.rn(), operand.offset(), cond);
2593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2594756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
2595756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
2596f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochvoid Assembler::vldm(BlockAddrMode am, Register base, DwVfpRegister first,
2597f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                     DwVfpRegister last, Condition cond) {
2598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8-922.
25998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // cond(31-28) | 110(27-25)| PUDW1(24-20) | Rbase(19-16) |
2600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // first(15-12) | 1011(11-8) | (count * 2)
2601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_LE(first.code(), last.code());
2602f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(VfpRegisterIsAvailable(last));
2603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(am == ia || am == ia_w || am == db_w);
2604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!base.is(pc));
26058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
26068b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  int sd, d;
26078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  first.split_code(&sd, &d);
26088b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  int count = last.code() - first.code() + 1;
2609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(count <= 16);
26108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  emit(cond | B27 | B26 | am | d*B22 | B20 | base.code()*B16 | sd*B12 |
26118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch       0xB*B8 | count*2);
26128b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch}
26138b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
2614f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochvoid Assembler::vstm(BlockAddrMode am, Register base, DwVfpRegister first,
2615f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                     DwVfpRegister last, Condition cond) {
2616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8-1080.
26178b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // cond(31-28) | 110(27-25)| PUDW0(24-20) | Rbase(19-16) |
26188b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // first(15-12) | 1011(11-8) | (count * 2)
2619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_LE(first.code(), last.code());
2620f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(VfpRegisterIsAvailable(last));
2621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(am == ia || am == ia_w || am == db_w);
2622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!base.is(pc));
26238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
26248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  int sd, d;
26258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  first.split_code(&sd, &d);
26268b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  int count = last.code() - first.code() + 1;
2627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(count <= 16);
26288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  emit(cond | B27 | B26 | am | d*B22 | base.code()*B16 | sd*B12 |
26298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch       0xB*B8 | count*2);
26308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch}
26318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
2632f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochvoid Assembler::vldm(BlockAddrMode am, Register base, SwVfpRegister first,
2633f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                     SwVfpRegister last, Condition cond) {
26348b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // Instruction details available in ARM DDI 0406A, A8-626.
26358b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // cond(31-28) | 110(27-25)| PUDW1(24-20) | Rbase(19-16) |
26368b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // first(15-12) | 1010(11-8) | (count/2)
2637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_LE(first.code(), last.code());
2638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(am == ia || am == ia_w || am == db_w);
2639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!base.is(pc));
26408b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
26418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  int sd, d;
26428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  first.split_code(&sd, &d);
26438b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  int count = last.code() - first.code() + 1;
26448b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  emit(cond | B27 | B26 | am | d*B22 | B20 | base.code()*B16 | sd*B12 |
26458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch       0xA*B8 | count);
26468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch}
26478b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
2648f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochvoid Assembler::vstm(BlockAddrMode am, Register base, SwVfpRegister first,
2649f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                     SwVfpRegister last, Condition cond) {
26508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // Instruction details available in ARM DDI 0406A, A8-784.
26518b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // cond(31-28) | 110(27-25)| PUDW0(24-20) | Rbase(19-16) |
26528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // first(15-12) | 1011(11-8) | (count/2)
2653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_LE(first.code(), last.code());
2654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(am == ia || am == ia_w || am == db_w);
2655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!base.is(pc));
26568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
26578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  int sd, d;
26588b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  first.split_code(&sd, &d);
26598b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  int count = last.code() - first.code() + 1;
26608b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  emit(cond | B27 | B26 | am | d*B22 | base.code()*B16 | sd*B12 |
26618b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch       0xA*B8 | count);
26628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch}
26638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
2664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
26653bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdochstatic void DoubleAsTwoUInt32(double d, uint32_t* lo, uint32_t* hi) {
26663bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  uint64_t i;
26673bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  memcpy(&i, &d, 8);
26683bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
26693bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  *lo = i & 0xffffffff;
26703bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  *hi = i >> 32;
26713bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch}
26723bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
2673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
26743bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch// Only works for little endian floating point formats.
26753bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch// We don't support VFP on the mixed endian floating point platform.
26763b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochstatic bool FitsVmovFPImmediate(double d, uint32_t* encoding) {
26773bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // VMOV can accept an immediate of the form:
26783bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  //
26793bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  //  +/- m * 2^(-n) where 16 <= m <= 31 and 0 <= n <= 7
26803bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  //
26813bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // The immediate is encoded using an 8-bit quantity, comprised of two
26823bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // 4-bit fields. For an 8-bit immediate of the form:
26833bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  //
26843bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  //  [abcdefgh]
26853bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  //
26863bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // where a is the MSB and h is the LSB, an immediate 64-bit double can be
26873bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // created of the form:
26883bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  //
26893bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  //  [aBbbbbbb,bbcdefgh,00000000,00000000,
26903bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  //      00000000,00000000,00000000,00000000]
26913bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  //
26923bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // where B = ~b.
26933bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  //
26943bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
26953bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  uint32_t lo, hi;
26963bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  DoubleAsTwoUInt32(d, &lo, &hi);
26973bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
26983bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // The most obvious constraint is the long block of zeroes.
26993bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  if ((lo != 0) || ((hi & 0xffff) != 0)) {
27003bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    return false;
27013bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  }
27023bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
27033b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Bits 61:54 must be all clear or all set.
27043bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  if (((hi & 0x3fc00000) != 0) && ((hi & 0x3fc00000) != 0x3fc00000)) {
27053bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    return false;
27063bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  }
27073bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
27083b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Bit 62 must be NOT bit 61.
27093bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  if (((hi ^ (hi << 1)) & (0x40000000)) == 0) {
27103bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    return false;
27113bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  }
27123bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
27133bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Create the encoded immediate in the form:
27143bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  //  [00000000,0000abcd,00000000,0000efgh]
27153bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  *encoding  = (hi >> 16) & 0xf;      // Low nybble.
27163bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  *encoding |= (hi >> 4) & 0x70000;   // Low three bits of the high nybble.
27173bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  *encoding |= (hi >> 12) & 0x80000;  // Top bit of the high nybble.
27183bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
27193bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  return true;
27203bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch}
27213bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
27223bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
27233b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid Assembler::vmov(const SwVfpRegister dst, float imm) {
27243b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  uint32_t enc;
2725f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  if (CpuFeatures::IsSupported(VFPv3) && FitsVmovFPImmediate(imm, &enc)) {
2726f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    CpuFeatureScope scope(this, VFPv3);
27273b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    // The float can be encoded in the instruction.
27283b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    //
27293b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    // Sd = immediate
27303b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    // Instruction details available in ARM DDI 0406C.b, A8-936.
27313b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | imm4H(19-16) |
27323b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    // Vd(15-12) | 101(11-9) | sz=0(8) | imm4L(3-0)
27333b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    int vd, d;
27343b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    dst.split_code(&vd, &d);
27353b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    emit(al | 0x1D * B23 | d * B22 | 0x3 * B20 | vd * B12 | 0x5 * B9 | enc);
27363b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
27373b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    mov(ip, Operand(bit_cast<int32_t>(imm)));
27383b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    vmov(dst, ip);
27393b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
27403b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
27413b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
27423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
27433bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdochvoid Assembler::vmov(const DwVfpRegister dst,
27443bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                     double imm,
2745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     const Register scratch) {
2746f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(VfpRegisterIsAvailable(dst));
2747f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(!scratch.is(ip));
27483bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  uint32_t enc;
2749014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // If the embedded constant pool is disabled, we can use the normal, inline
2750014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // constant pool. If the embedded constant pool is enabled (via
2751014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // FLAG_enable_embedded_constant_pool), we can only use it where the pool
2752014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // pointer (pp) is valid.
2753014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool can_use_pool =
2754014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      !FLAG_enable_embedded_constant_pool || is_constant_pool_available();
2755f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  if (CpuFeatures::IsSupported(VFPv3) && FitsVmovFPImmediate(imm, &enc)) {
2756f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    CpuFeatureScope scope(this, VFPv3);
27573bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    // The double can be encoded in the instruction.
2758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    //
2759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Dd = immediate
2760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Instruction details available in ARM DDI 0406C.b, A8-936.
2761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | imm4H(19-16) |
2762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Vd(15-12) | 101(11-9) | sz=1(8) | imm4L(3-0)
2763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int vd, d;
2764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    dst.split_code(&vd, &d);
2765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    emit(al | 0x1D*B23 | d*B22 | 0x3*B20 | vd*B12 | 0x5*B9 | B8 | enc);
2766f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  } else if (CpuFeatures::IsSupported(ARMv7) && FLAG_enable_vldr_imm &&
2767f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch             can_use_pool) {
2768f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    CpuFeatureScope scope(this, ARMv7);
2769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // TODO(jfb) Temporarily turned off until we have constant blinding or
2770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    //           some equivalent mitigation: an attacker can otherwise control
2771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    //           generated data which also happens to be executable, a Very Bad
2772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    //           Thing indeed.
2773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    //           Blinding gets tricky because we don't have xor, we probably
2774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    //           need to add/subtract without losing precision, which requires a
2775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    //           cookie value that Lithium is probably better positioned to
2776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    //           choose.
2777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    //           We could also add a few peepholes here like detecting 0.0 and
2778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    //           -0.0 and doing a vmov from the sequestered d14, forcing denorms
2779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    //           to zero (we set flush-to-zero), and normalizing NaN values.
2780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    //           We could also detect redundant values.
2781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    //           The code could also randomize the order of values, though
2782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    //           that's tricky because vldr has a limited reach. Furthermore
2783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    //           it breaks load locality.
2784014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    ConstantPoolEntry::Access access = ConstantPoolAddEntry(pc_offset(), imm);
2785014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (access == ConstantPoolEntry::OVERFLOWED) {
2786014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK(FLAG_enable_embedded_constant_pool);
2787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Emit instructions to load constant pool offset.
2788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      movw(ip, 0);
2789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      movt(ip, 0);
2790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Load from constant pool at offset.
2791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      vldr(dst, MemOperand(pp, ip));
2792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
2793014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK(access == ConstantPoolEntry::REGULAR);
2794014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      vldr(dst, MemOperand(FLAG_enable_embedded_constant_pool ? pp : pc, 0));
2795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
27963bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  } else {
2797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Synthesise the double from ARM immediates.
27983bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    uint32_t lo, hi;
27993bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    DoubleAsTwoUInt32(imm, &lo, &hi);
28003bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
2801958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (lo == hi) {
2802958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      // Move the low and high parts of the double to a D register in one
2803958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      // instruction.
2804958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      mov(ip, Operand(lo));
2805958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      vmov(dst, ip, ip);
2806958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    } else if (scratch.is(no_reg)) {
2807958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      mov(ip, Operand(lo));
2808958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      vmov(dst, VmovIndexLo, ip);
2809014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (((lo & 0xffff) == (hi & 0xffff)) &&
2810014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          CpuFeatures::IsSupported(ARMv7)) {
2811f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        CpuFeatureScope scope(this, ARMv7);
2812958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        movt(ip, hi >> 16);
2813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
2814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        mov(ip, Operand(hi));
2815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
2816958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      vmov(dst, VmovIndexHi, ip);
28173bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    } else {
2818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Move the low and high parts of the double to a D register in one
2819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // instruction.
28203bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      mov(ip, Operand(lo));
2821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mov(scratch, Operand(hi));
2822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      vmov(dst, ip, scratch);
28233bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    }
28243bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  }
28253bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch}
28263bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
28273bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
28283bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdochvoid Assembler::vmov(const SwVfpRegister dst,
28293bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                     const SwVfpRegister src,
28303bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                     const Condition cond) {
28313bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Sd = Sm
28323bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Instruction details available in ARM DDI 0406B, A8-642.
283380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  int sd, d, sm, m;
283480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  dst.split_code(&sd, &d);
283580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  src.split_code(&sm, &m);
283680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  emit(cond | 0xE*B24 | d*B22 | 0xB*B20 | sd*B12 | 0xA*B8 | B6 | m*B5 | sm);
28373bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch}
28383bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
28393bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
2840e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid Assembler::vmov(const DwVfpRegister dst,
28418defd9ff6930b4e24729971a61cf7469daf119beSteve Block                     const DwVfpRegister src,
28428defd9ff6930b4e24729971a61cf7469daf119beSteve Block                     const Condition cond) {
28438defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Dd = Dm
2844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8-938.
2845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | 0000(19-16) | Vd(15-12) |
2846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // 101(11-9) | sz=1(8) | 0(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
2847f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(VfpRegisterIsAvailable(dst));
2848f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(VfpRegisterIsAvailable(src));
2849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int vd, d;
2850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  dst.split_code(&vd, &d);
2851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int vm, m;
2852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  src.split_code(&vm, &m);
2853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  emit(cond | 0x1D*B23 | d*B22 | 0x3*B20 | vd*B12 | 0x5*B9 | B8 | B6 | m*B5 |
2854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       vm);
2855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::vmov(const DwVfpRegister dst,
2858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     const VmovIndex index,
2859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     const Register src,
2860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     const Condition cond) {
2861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Dd[index] = Rt
2862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8-940.
2863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // cond(31-28) | 1110(27-24) | 0(23) | opc1=0index(22-21) | 0(20) |
2864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Vd(19-16) | Rt(15-12) | 1011(11-8) | D(7) | opc2=00(6-5) | 1(4) | 0000(3-0)
2865f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(VfpRegisterIsAvailable(dst));
2866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(index.index == 0 || index.index == 1);
2867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int vd, d;
2868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  dst.split_code(&vd, &d);
2869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  emit(cond | 0xE*B24 | index.index*B21 | vd*B16 | src.code()*B12 | 0xB*B8 |
2870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       d*B7 | B4);
2871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::vmov(const Register dst,
2875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     const VmovIndex index,
2876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     const DwVfpRegister src,
2877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     const Condition cond) {
2878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Dd[index] = Rt
2879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8.8.342.
2880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // cond(31-28) | 1110(27-24) | U=0(23) | opc1=0index(22-21) | 1(20) |
2881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Vn(19-16) | Rt(15-12) | 1011(11-8) | N(7) | opc2=00(6-5) | 1(4) | 0000(3-0)
2882f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(VfpRegisterIsAvailable(src));
2883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(index.index == 0 || index.index == 1);
2884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int vn, n;
2885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  src.split_code(&vn, &n);
2886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  emit(cond | 0xE*B24 | index.index*B21 | B20 | vn*B16 | dst.code()*B12 |
2887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       0xB*B8 | n*B7 | B4);
28888defd9ff6930b4e24729971a61cf7469daf119beSteve Block}
28898defd9ff6930b4e24729971a61cf7469daf119beSteve Block
28908defd9ff6930b4e24729971a61cf7469daf119beSteve Block
28918defd9ff6930b4e24729971a61cf7469daf119beSteve Blockvoid Assembler::vmov(const DwVfpRegister dst,
2892e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     const Register src1,
2893e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     const Register src2,
2894e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     const Condition cond) {
2895d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Dm = <Rt,Rt2>.
2896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8-948.
2897d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // cond(31-28) | 1100(27-24)| 010(23-21) | op=0(20) | Rt2(19-16) |
2898d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Rt(15-12) | 1011(11-8) | 00(7-6) | M(5) | 1(4) | Vm
2899f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(VfpRegisterIsAvailable(dst));
2900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!src1.is(pc) && !src2.is(pc));
2901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int vm, m;
2902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  dst.split_code(&vm, &m);
2903d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  emit(cond | 0xC*B24 | B22 | src2.code()*B16 |
2904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       src1.code()*B12 | 0xB*B8 | m*B5 | B4 | vm);
2905d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2906d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2907d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2908e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid Assembler::vmov(const Register dst1,
2909e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     const Register dst2,
2910e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     const DwVfpRegister src,
2911e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     const Condition cond) {
2912d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // <Rt,Rt2> = Dm.
2913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8-948.
2914d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // cond(31-28) | 1100(27-24)| 010(23-21) | op=1(20) | Rt2(19-16) |
2915d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Rt(15-12) | 1011(11-8) | 00(7-6) | M(5) | 1(4) | Vm
2916f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(VfpRegisterIsAvailable(src));
2917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dst1.is(pc) && !dst2.is(pc));
2918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int vm, m;
2919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  src.split_code(&vm, &m);
2920d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  emit(cond | 0xC*B24 | B22 | B20 | dst2.code()*B16 |
2921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       dst1.code()*B12 | 0xB*B8 | m*B5 | B4 | vm);
2922d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2923d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2924d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2925e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid Assembler::vmov(const SwVfpRegister dst,
2926d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                     const Register src,
2927d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                     const Condition cond) {
2928d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Sn = Rt.
2929d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Instruction details available in ARM DDI 0406A, A8-642.
2930d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // cond(31-28) | 1110(27-24)| 000(23-21) | op=0(20) | Vn(19-16) |
2931d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Rt(15-12) | 1010(11-8) | N(7)=0 | 00(6-5) | 1(4) | 0000(3-0)
2932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!src.is(pc));
293380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  int sn, n;
293480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  dst.split_code(&sn, &n);
293580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  emit(cond | 0xE*B24 | sn*B16 | src.code()*B12 | 0xA*B8 | n*B7 | B4);
2936d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2937d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2938d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2939e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid Assembler::vmov(const Register dst,
2940e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     const SwVfpRegister src,
2941d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                     const Condition cond) {
2942d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Rt = Sn.
2943d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Instruction details available in ARM DDI 0406A, A8-642.
2944d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // cond(31-28) | 1110(27-24)| 000(23-21) | op=1(20) | Vn(19-16) |
2945d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Rt(15-12) | 1010(11-8) | N(7)=0 | 00(6-5) | 1(4) | 0000(3-0)
2946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dst.is(pc));
294780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  int sn, n;
294880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  src.split_code(&sn, &n);
294980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  emit(cond | 0xE*B24 | B20 | sn*B16 | dst.code()*B12 | 0xA*B8 | n*B7 | B4);
2950d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2951d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
29526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Type of data to read from or write to VFP register.
29536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Used as specifier in generic vcvt instruction.
29546ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockenum VFPType { S32, U32, F32, F64 };
29556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
29566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
29576ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic bool IsSignedVFPType(VFPType type) {
29586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  switch (type) {
29596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    case S32:
29606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return true;
29616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    case U32:
29626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return false;
29636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    default:
29646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      UNREACHABLE();
29656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return false;
29666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
29676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
29686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
29696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
29706ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic bool IsIntegerVFPType(VFPType type) {
29716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  switch (type) {
29726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    case S32:
29736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    case U32:
29746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return true;
29756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    case F32:
29766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    case F64:
29776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return false;
29786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    default:
29796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      UNREACHABLE();
29806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return false;
29816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
29826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
29836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
29846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
29856ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic bool IsDoubleVFPType(VFPType type) {
29866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  switch (type) {
29876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    case F32:
29886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return false;
29896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    case F64:
29906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return true;
29916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    default:
29926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      UNREACHABLE();
29936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return false;
29946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
29956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
29966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
29976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
299880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen// Split five bit reg_code based on size of reg_type.
299980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen//  32-bit register codes are Vm:M
300080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen//  64-bit register codes are M:Vm
300180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen// where Vm is four bits, and M is a single bit.
300280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenstatic void SplitRegCode(VFPType reg_type,
30036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                         int reg_code,
30046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                         int* vm,
30056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                         int* m) {
3006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((reg_code >= 0) && (reg_code <= 31));
300780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (IsIntegerVFPType(reg_type) || !IsDoubleVFPType(reg_type)) {
300880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // 32 bit type.
30096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    *m  = reg_code & 0x1;
30106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    *vm = reg_code >> 1;
30116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
301280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // 64 bit type.
30136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    *m  = (reg_code & 0x10) >> 4;
30146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    *vm = reg_code & 0x0F;
30156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
30166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
30176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
30186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
30196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Encode vcvt.src_type.dst_type instruction.
30206ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic Instr EncodeVCVT(const VFPType dst_type,
30216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                        const int dst_code,
30226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                        const VFPType src_type,
30236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                        const int src_code,
30241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                        VFPConversionMode mode,
30256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                        const Condition cond) {
3026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(src_type != dst_type);
302780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  int D, Vd, M, Vm;
302880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  SplitRegCode(src_type, src_code, &Vm, &M);
302980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  SplitRegCode(dst_type, dst_code, &Vd, &D);
303080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
30316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (IsIntegerVFPType(dst_type) || IsIntegerVFPType(src_type)) {
30326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Conversion between IEEE floating point and 32-bit integer.
30336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Instruction details available in ARM DDI 0406B, A8.6.295.
30346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 1(19) | opc2(18-16) |
30356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Vd(15-12) | 101(11-9) | sz(8) | op(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
3036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!IsIntegerVFPType(dst_type) || !IsIntegerVFPType(src_type));
30376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
303880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    int sz, opc2, op;
30396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
30406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (IsIntegerVFPType(dst_type)) {
30416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      opc2 = IsSignedVFPType(dst_type) ? 0x5 : 0x4;
30426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      sz = IsDoubleVFPType(src_type) ? 0x1 : 0x0;
304390bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner      op = mode;
30446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else {
3045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(IsIntegerVFPType(src_type));
30466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      opc2 = 0x0;
30476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      sz = IsDoubleVFPType(dst_type) ? 0x1 : 0x0;
30486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      op = IsSignedVFPType(src_type) ? 0x1 : 0x0;
30496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
30506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
30516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return (cond | 0xE*B24 | B23 | D*B22 | 0x3*B20 | B19 | opc2*B16 |
30526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            Vd*B12 | 0x5*B9 | sz*B8 | op*B7 | B6 | M*B5 | Vm);
30536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
30546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Conversion between IEEE double and single precision.
30556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Instruction details available in ARM DDI 0406B, A8.6.298.
30566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 0111(19-16) |
30576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Vd(15-12) | 101(11-9) | sz(8) | 1(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
305880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    int sz = IsDoubleVFPType(src_type) ? 0x1 : 0x0;
30596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return (cond | 0xE*B24 | B23 | D*B22 | 0x3*B20 | 0x7*B16 |
30606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            Vd*B12 | 0x5*B9 | sz*B8 | B7 | B6 | M*B5 | Vm);
30616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
30626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
30636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
30646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
30656ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid Assembler::vcvt_f64_s32(const DwVfpRegister dst,
30666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                             const SwVfpRegister src,
30671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                             VFPConversionMode mode,
30686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                             const Condition cond) {
3069f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(VfpRegisterIsAvailable(dst));
307090bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner  emit(EncodeVCVT(F64, dst.code(), S32, src.code(), mode, cond));
3071d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
3072d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3073d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
30746ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid Assembler::vcvt_f32_s32(const SwVfpRegister dst,
30756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                             const SwVfpRegister src,
30761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                             VFPConversionMode mode,
30776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                             const Condition cond) {
307890bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner  emit(EncodeVCVT(F32, dst.code(), S32, src.code(), mode, cond));
30796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
30806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
30816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
30826ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid Assembler::vcvt_f64_u32(const DwVfpRegister dst,
30836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                             const SwVfpRegister src,
30841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                             VFPConversionMode mode,
30856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                             const Condition cond) {
3086f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(VfpRegisterIsAvailable(dst));
308790bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner  emit(EncodeVCVT(F64, dst.code(), U32, src.code(), mode, cond));
30886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
30896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
30906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3091109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid Assembler::vcvt_f32_u32(const SwVfpRegister dst, const SwVfpRegister src,
3092109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                             VFPConversionMode mode, const Condition cond) {
3093109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  emit(EncodeVCVT(F32, dst.code(), U32, src.code(), mode, cond));
3094109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
3095109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
3096109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
3097109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid Assembler::vcvt_s32_f32(const SwVfpRegister dst, const SwVfpRegister src,
3098109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                             VFPConversionMode mode, const Condition cond) {
3099109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  emit(EncodeVCVT(S32, dst.code(), F32, src.code(), mode, cond));
3100109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
3101109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
3102109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
3103109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid Assembler::vcvt_u32_f32(const SwVfpRegister dst, const SwVfpRegister src,
3104109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                             VFPConversionMode mode, const Condition cond) {
3105109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  emit(EncodeVCVT(U32, dst.code(), F32, src.code(), mode, cond));
3106109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
3107109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
3108109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
31096ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid Assembler::vcvt_s32_f64(const SwVfpRegister dst,
31106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                             const DwVfpRegister src,
31111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                             VFPConversionMode mode,
31126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                             const Condition cond) {
3113f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(VfpRegisterIsAvailable(src));
311490bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner  emit(EncodeVCVT(S32, dst.code(), F64, src.code(), mode, cond));
31156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
31166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
31176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
31186ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid Assembler::vcvt_u32_f64(const SwVfpRegister dst,
31196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                             const DwVfpRegister src,
31201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                             VFPConversionMode mode,
31216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                             const Condition cond) {
3122f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(VfpRegisterIsAvailable(src));
312390bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner  emit(EncodeVCVT(U32, dst.code(), F64, src.code(), mode, cond));
31246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
31256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
31266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
31276ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid Assembler::vcvt_f64_f32(const DwVfpRegister dst,
31286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                             const SwVfpRegister src,
31291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                             VFPConversionMode mode,
31306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                             const Condition cond) {
3131f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(VfpRegisterIsAvailable(dst));
313290bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner  emit(EncodeVCVT(F64, dst.code(), F32, src.code(), mode, cond));
31336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
31346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
31356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
31366ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid Assembler::vcvt_f32_f64(const SwVfpRegister dst,
31376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                             const DwVfpRegister src,
31381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                             VFPConversionMode mode,
31396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                             const Condition cond) {
3140f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(VfpRegisterIsAvailable(src));
314190bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner  emit(EncodeVCVT(F32, dst.code(), F64, src.code(), mode, cond));
3142d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
3143d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3144d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::vcvt_f64_s32(const DwVfpRegister dst,
3146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                             int fraction_bits,
3147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                             const Condition cond) {
3148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8-874.
3149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | 1010(19-16) | Vd(15-12) |
3150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // 101(11-9) | sf=1(8) | sx=1(7) | 1(6) | i(5) | 0(4) | imm4(3-0)
3151f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(IsEnabled(VFPv3));
3152f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(VfpRegisterIsAvailable(dst));
3153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(fraction_bits > 0 && fraction_bits <= 32);
3154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int vd, d;
3155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  dst.split_code(&vd, &d);
3156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int imm5 = 32 - fraction_bits;
3157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int i = imm5 & 1;
3158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int imm4 = (imm5 >> 1) & 0xf;
3159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  emit(cond | 0xE*B24 | B23 | d*B22 | 0x3*B20 | B19 | 0x2*B16 |
3160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       vd*B12 | 0x5*B9 | B8 | B7 | B6 | i*B5 | imm4);
3161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
316444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::vneg(const DwVfpRegister dst,
316544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                     const DwVfpRegister src,
316644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                     const Condition cond) {
3167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8-968.
3168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | 0001(19-16) | Vd(15-12) |
3169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // 101(11-9) | sz=1(8) | 0(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
3170f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(VfpRegisterIsAvailable(dst));
3171f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(VfpRegisterIsAvailable(src));
3172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int vd, d;
3173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  dst.split_code(&vd, &d);
3174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int vm, m;
3175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  src.split_code(&vm, &m);
3176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  emit(cond | 0x1D*B23 | d*B22 | 0x3*B20 | B16 | vd*B12 | 0x5*B9 | B8 | B6 |
3178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       m*B5 | vm);
317944f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
318044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
318144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
3182014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::vneg(const SwVfpRegister dst, const SwVfpRegister src,
3183014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                     const Condition cond) {
3184014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Instruction details available in ARM DDI 0406C.b, A8-968.
3185014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | 0001(19-16) | Vd(15-12) |
3186014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // 101(11-9) | sz=0(8) | 0(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
3187014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int vd, d;
3188014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  dst.split_code(&vd, &d);
3189014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int vm, m;
3190014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  src.split_code(&vm, &m);
3191014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3192014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  emit(cond | 0x1D * B23 | d * B22 | 0x3 * B20 | B16 | vd * B12 | 0x5 * B9 |
3193014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch       B6 | m * B5 | vm);
3194014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3195014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3196014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
31971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Assembler::vabs(const DwVfpRegister dst,
31981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                     const DwVfpRegister src,
31991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                     const Condition cond) {
3200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8-524.
3201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | 0000(19-16) | Vd(15-12) |
3202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // 101(11-9) | sz=1(8) | 1(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
3203f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(VfpRegisterIsAvailable(dst));
3204f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(VfpRegisterIsAvailable(src));
3205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int vd, d;
3206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  dst.split_code(&vd, &d);
3207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int vm, m;
3208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  src.split_code(&vm, &m);
3209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  emit(cond | 0x1D*B23 | d*B22 | 0x3*B20 | vd*B12 | 0x5*B9 | B8 | B7 | B6 |
3210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       m*B5 | vm);
32111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
32121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
32131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3214014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::vabs(const SwVfpRegister dst, const SwVfpRegister src,
3215014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                     const Condition cond) {
3216014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Instruction details available in ARM DDI 0406C.b, A8-524.
3217014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | 0000(19-16) | Vd(15-12) |
3218014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // 101(11-9) | sz=0(8) | 1(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
3219014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int vd, d;
3220014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  dst.split_code(&vd, &d);
3221014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int vm, m;
3222014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  src.split_code(&vm, &m);
3223014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  emit(cond | 0x1D * B23 | d * B22 | 0x3 * B20 | vd * B12 | 0x5 * B9 | B7 | B6 |
3224014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch       m * B5 | vm);
3225014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3226014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3227014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3228e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid Assembler::vadd(const DwVfpRegister dst,
3229e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     const DwVfpRegister src1,
3230e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     const DwVfpRegister src2,
3231e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     const Condition cond) {
3232e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Dd = vadd(Dn, Dm) double precision floating point addition.
3233d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm.
3234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8-830.
3235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // cond(31-28) | 11100(27-23)| D(22) | 11(21-20) | Vn(19-16) |
3236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Vd(15-12) | 101(11-9) | sz=1(8) | N(7) | 0(6) | M(5) | 0(4) | Vm(3-0)
3237f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(VfpRegisterIsAvailable(dst));
3238f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(VfpRegisterIsAvailable(src1));
3239f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(VfpRegisterIsAvailable(src2));
3240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int vd, d;
3241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  dst.split_code(&vd, &d);
3242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int vn, n;
3243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  src1.split_code(&vn, &n);
3244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int vm, m;
3245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  src2.split_code(&vm, &m);
3246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  emit(cond | 0x1C*B23 | d*B22 | 0x3*B20 | vn*B16 | vd*B12 | 0x5*B9 | B8 |
3247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       n*B7 | m*B5 | vm);
3248d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
3249d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3250d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3251014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::vadd(const SwVfpRegister dst, const SwVfpRegister src1,
3252014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                     const SwVfpRegister src2, const Condition cond) {
3253014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Sd = vadd(Sn, Sm) single precision floating point addition.
3254014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Sd = D:Vd; Sm=M:Vm; Sn=N:Vm.
3255014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Instruction details available in ARM DDI 0406C.b, A8-830.
3256014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // cond(31-28) | 11100(27-23)| D(22) | 11(21-20) | Vn(19-16) |
3257014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Vd(15-12) | 101(11-9) | sz=0(8) | N(7) | 0(6) | M(5) | 0(4) | Vm(3-0)
3258014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int vd, d;
3259014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  dst.split_code(&vd, &d);
3260014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int vn, n;
3261014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  src1.split_code(&vn, &n);
3262014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int vm, m;
3263014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  src2.split_code(&vm, &m);
3264014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  emit(cond | 0x1C * B23 | d * B22 | 0x3 * B20 | vn * B16 | vd * B12 |
3265014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch       0x5 * B9 | n * B7 | m * B5 | vm);
3266014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3267014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3268014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3269e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid Assembler::vsub(const DwVfpRegister dst,
3270e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     const DwVfpRegister src1,
3271e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     const DwVfpRegister src2,
3272e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     const Condition cond) {
3273e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Dd = vsub(Dn, Dm) double precision floating point subtraction.
3274d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm.
3275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8-1086.
3276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // cond(31-28) | 11100(27-23)| D(22) | 11(21-20) | Vn(19-16) |
3277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Vd(15-12) | 101(11-9) | sz=1(8) | N(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
3278f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(VfpRegisterIsAvailable(dst));
3279f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(VfpRegisterIsAvailable(src1));
3280f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(VfpRegisterIsAvailable(src2));
3281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int vd, d;
3282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  dst.split_code(&vd, &d);
3283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int vn, n;
3284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  src1.split_code(&vn, &n);
3285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int vm, m;
3286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  src2.split_code(&vm, &m);
3287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  emit(cond | 0x1C*B23 | d*B22 | 0x3*B20 | vn*B16 | vd*B12 | 0x5*B9 | B8 |
3288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       n*B7 | B6 | m*B5 | vm);
3289d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
3290d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3291d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3292014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::vsub(const SwVfpRegister dst, const SwVfpRegister src1,
3293014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                     const SwVfpRegister src2, const Condition cond) {
3294014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Sd = vsub(Sn, Sm) single precision floating point subtraction.
3295014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Sd = D:Vd; Sm=M:Vm; Sn=N:Vm.
3296014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Instruction details available in ARM DDI 0406C.b, A8-1086.
3297014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // cond(31-28) | 11100(27-23)| D(22) | 11(21-20) | Vn(19-16) |
3298014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Vd(15-12) | 101(11-9) | sz=0(8) | N(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
3299014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int vd, d;
3300014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  dst.split_code(&vd, &d);
3301014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int vn, n;
3302014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  src1.split_code(&vn, &n);
3303014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int vm, m;
3304014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  src2.split_code(&vm, &m);
3305014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  emit(cond | 0x1C * B23 | d * B22 | 0x3 * B20 | vn * B16 | vd * B12 |
3306014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch       0x5 * B9 | n * B7 | B6 | m * B5 | vm);
3307014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3308014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3309014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3310e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid Assembler::vmul(const DwVfpRegister dst,
3311e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     const DwVfpRegister src1,
3312e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     const DwVfpRegister src2,
3313e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     const Condition cond) {
3314e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Dd = vmul(Dn, Dm) double precision floating point multiplication.
3315d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm.
3316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8-960.
3317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // cond(31-28) | 11100(27-23)| D(22) | 10(21-20) | Vn(19-16) |
3318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Vd(15-12) | 101(11-9) | sz=1(8) | N(7) | 0(6) | M(5) | 0(4) | Vm(3-0)
3319f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(VfpRegisterIsAvailable(dst));
3320f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(VfpRegisterIsAvailable(src1));
3321f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(VfpRegisterIsAvailable(src2));
3322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int vd, d;
3323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  dst.split_code(&vd, &d);
3324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int vn, n;
3325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  src1.split_code(&vn, &n);
3326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int vm, m;
3327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  src2.split_code(&vm, &m);
3328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  emit(cond | 0x1C*B23 | d*B22 | 0x2*B20 | vn*B16 | vd*B12 | 0x5*B9 | B8 |
3329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       n*B7 | m*B5 | vm);
3330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3333014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::vmul(const SwVfpRegister dst, const SwVfpRegister src1,
3334014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                     const SwVfpRegister src2, const Condition cond) {
3335014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Sd = vmul(Sn, Sm) single precision floating point multiplication.
3336014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Sd = D:Vd; Sm=M:Vm; Sn=N:Vm.
3337014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Instruction details available in ARM DDI 0406C.b, A8-960.
3338014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // cond(31-28) | 11100(27-23)| D(22) | 10(21-20) | Vn(19-16) |
3339014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Vd(15-12) | 101(11-9) | sz=0(8) | N(7) | 0(6) | M(5) | 0(4) | Vm(3-0)
3340014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int vd, d;
3341014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  dst.split_code(&vd, &d);
3342014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int vn, n;
3343014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  src1.split_code(&vn, &n);
3344014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int vm, m;
3345014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  src2.split_code(&vm, &m);
3346014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  emit(cond | 0x1C * B23 | d * B22 | 0x2 * B20 | vn * B16 | vd * B12 |
3347014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch       0x5 * B9 | n * B7 | m * B5 | vm);
3348014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3349014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3350014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::vmla(const DwVfpRegister dst,
3352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     const DwVfpRegister src1,
3353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     const DwVfpRegister src2,
3354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     const Condition cond) {
3355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8-932.
3356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // cond(31-28) | 11100(27-23) | D(22) | 00(21-20) | Vn(19-16) |
3357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Vd(15-12) | 101(11-9) | sz=1(8) | N(7) | op=0(6) | M(5) | 0(4) | Vm(3-0)
3358f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(VfpRegisterIsAvailable(dst));
3359f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(VfpRegisterIsAvailable(src1));
3360f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(VfpRegisterIsAvailable(src2));
3361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int vd, d;
3362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  dst.split_code(&vd, &d);
3363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int vn, n;
3364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  src1.split_code(&vn, &n);
3365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int vm, m;
3366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  src2.split_code(&vm, &m);
3367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  emit(cond | 0x1C*B23 | d*B22 | vn*B16 | vd*B12 | 0x5*B9 | B8 | n*B7 | m*B5 |
3368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       vm);
3369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3372014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::vmla(const SwVfpRegister dst, const SwVfpRegister src1,
3373014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                     const SwVfpRegister src2, const Condition cond) {
3374014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Instruction details available in ARM DDI 0406C.b, A8-932.
3375014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // cond(31-28) | 11100(27-23) | D(22) | 00(21-20) | Vn(19-16) |
3376014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Vd(15-12) | 101(11-9) | sz=0(8) | N(7) | op=0(6) | M(5) | 0(4) | Vm(3-0)
3377014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int vd, d;
3378014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  dst.split_code(&vd, &d);
3379014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int vn, n;
3380014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  src1.split_code(&vn, &n);
3381014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int vm, m;
3382014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  src2.split_code(&vm, &m);
3383014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  emit(cond | 0x1C * B23 | d * B22 | vn * B16 | vd * B12 | 0x5 * B9 | n * B7 |
3384014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch       m * B5 | vm);
3385014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3386014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3387014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::vmls(const DwVfpRegister dst,
3389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     const DwVfpRegister src1,
3390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     const DwVfpRegister src2,
3391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     const Condition cond) {
3392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8-932.
3393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // cond(31-28) | 11100(27-23) | D(22) | 00(21-20) | Vn(19-16) |
3394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Vd(15-12) | 101(11-9) | sz=1(8) | N(7) | op=1(6) | M(5) | 0(4) | Vm(3-0)
3395f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(VfpRegisterIsAvailable(dst));
3396f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(VfpRegisterIsAvailable(src1));
3397f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(VfpRegisterIsAvailable(src2));
3398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int vd, d;
3399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  dst.split_code(&vd, &d);
3400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int vn, n;
3401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  src1.split_code(&vn, &n);
3402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int vm, m;
3403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  src2.split_code(&vm, &m);
3404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  emit(cond | 0x1C*B23 | d*B22 | vn*B16 | vd*B12 | 0x5*B9 | B8 | n*B7 | B6 |
3405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       m*B5 | vm);
3406d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
3407d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3408d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3409014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::vmls(const SwVfpRegister dst, const SwVfpRegister src1,
3410014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                     const SwVfpRegister src2, const Condition cond) {
3411014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Instruction details available in ARM DDI 0406C.b, A8-932.
3412014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // cond(31-28) | 11100(27-23) | D(22) | 00(21-20) | Vn(19-16) |
3413014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Vd(15-12) | 101(11-9) | sz=0(8) | N(7) | op=1(6) | M(5) | 0(4) | Vm(3-0)
3414014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int vd, d;
3415014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  dst.split_code(&vd, &d);
3416014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int vn, n;
3417014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  src1.split_code(&vn, &n);
3418014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int vm, m;
3419014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  src2.split_code(&vm, &m);
3420014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  emit(cond | 0x1C * B23 | d * B22 | vn * B16 | vd * B12 | 0x5 * B9 | n * B7 |
3421014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch       B6 | m * B5 | vm);
3422014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3423014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3424014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3425e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid Assembler::vdiv(const DwVfpRegister dst,
3426e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     const DwVfpRegister src1,
3427e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     const DwVfpRegister src2,
3428e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     const Condition cond) {
3429e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Dd = vdiv(Dn, Dm) double precision floating point division.
3430d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm.
3431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8-882.
3432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // cond(31-28) | 11101(27-23)| D(22) | 00(21-20) | Vn(19-16) |
3433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Vd(15-12) | 101(11-9) | sz=1(8) | N(7) | 0(6) | M(5) | 0(4) | Vm(3-0)
3434f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(VfpRegisterIsAvailable(dst));
3435f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(VfpRegisterIsAvailable(src1));
3436f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(VfpRegisterIsAvailable(src2));
3437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int vd, d;
3438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  dst.split_code(&vd, &d);
3439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int vn, n;
3440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  src1.split_code(&vn, &n);
3441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int vm, m;
3442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  src2.split_code(&vm, &m);
3443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  emit(cond | 0x1D*B23 | d*B22 | vn*B16 | vd*B12 | 0x5*B9 | B8 | n*B7 | m*B5 |
3444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       vm);
3445d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
3446d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3447d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3448014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::vdiv(const SwVfpRegister dst, const SwVfpRegister src1,
3449014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                     const SwVfpRegister src2, const Condition cond) {
3450014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Sd = vdiv(Sn, Sm) single precision floating point division.
3451014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Sd = D:Vd; Sm=M:Vm; Sn=N:Vm.
3452014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Instruction details available in ARM DDI 0406C.b, A8-882.
3453014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // cond(31-28) | 11101(27-23)| D(22) | 00(21-20) | Vn(19-16) |
3454014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Vd(15-12) | 101(11-9) | sz=0(8) | N(7) | 0(6) | M(5) | 0(4) | Vm(3-0)
3455014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int vd, d;
3456014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  dst.split_code(&vd, &d);
3457014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int vn, n;
3458014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  src1.split_code(&vn, &n);
3459014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int vm, m;
3460014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  src2.split_code(&vm, &m);
3461014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  emit(cond | 0x1D * B23 | d * B22 | vn * B16 | vd * B12 | 0x5 * B9 | n * B7 |
3462014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch       m * B5 | vm);
3463014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3464014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3465014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3466e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid Assembler::vcmp(const DwVfpRegister src1,
3467e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     const DwVfpRegister src2,
3468d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                     const Condition cond) {
3469d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // vcmp(Dd, Dm) double precision floating point comparison.
3470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8-864.
3471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 0100(19-16) |
3472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Vd(15-12) | 101(11-9) | sz=1(8) | E=0(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
3473f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(VfpRegisterIsAvailable(src1));
3474f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(VfpRegisterIsAvailable(src2));
3475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int vd, d;
3476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  src1.split_code(&vd, &d);
3477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int vm, m;
3478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  src2.split_code(&vm, &m);
3479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  emit(cond | 0x1D*B23 | d*B22 | 0x3*B20 | 0x4*B16 | vd*B12 | 0x5*B9 | B8 | B6 |
3480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       m*B5 | vm);
3481d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
3482d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3483d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3484014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::vcmp(const SwVfpRegister src1, const SwVfpRegister src2,
3485014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                     const Condition cond) {
3486014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // vcmp(Sd, Sm) single precision floating point comparison.
3487014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Instruction details available in ARM DDI 0406C.b, A8-864.
3488014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 0100(19-16) |
3489014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Vd(15-12) | 101(11-9) | sz=0(8) | E=0(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
3490014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int vd, d;
3491014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  src1.split_code(&vd, &d);
3492014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int vm, m;
3493014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  src2.split_code(&vm, &m);
3494014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  emit(cond | 0x1D * B23 | d * B22 | 0x3 * B20 | 0x4 * B16 | vd * B12 |
3495014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch       0x5 * B9 | B6 | m * B5 | vm);
3496014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3497014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3498014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3499756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid Assembler::vcmp(const DwVfpRegister src1,
3500756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                     const double src2,
3501756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                     const Condition cond) {
3502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // vcmp(Dd, #0.0) double precision floating point comparison.
3503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8-864.
3504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 0101(19-16) |
3505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Vd(15-12) | 101(11-9) | sz=1(8) | E=0(7) | 1(6) | 0(5) | 0(4) | 0000(3-0)
3506f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(VfpRegisterIsAvailable(src1));
3507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(src2 == 0.0);
3508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int vd, d;
3509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  src1.split_code(&vd, &d);
3510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  emit(cond | 0x1D*B23 | d*B22 | 0x3*B20 | 0x5*B16 | vd*B12 | 0x5*B9 | B8 | B6);
3511756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
3512756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
3513756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
3514014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::vcmp(const SwVfpRegister src1, const float src2,
3515014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                     const Condition cond) {
3516014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // vcmp(Sd, #0.0) single precision floating point comparison.
3517014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Instruction details available in ARM DDI 0406C.b, A8-864.
3518014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 0101(19-16) |
3519014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Vd(15-12) | 101(11-9) | sz=0(8) | E=0(7) | 1(6) | 0(5) | 0(4) | 0000(3-0)
3520014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(src2 == 0.0);
3521014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int vd, d;
3522014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  src1.split_code(&vd, &d);
3523014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  emit(cond | 0x1D * B23 | d * B22 | 0x3 * B20 | 0x5 * B16 | vd * B12 |
3524014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch       0x5 * B9 | B6);
3525014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3526014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3527f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochvoid Assembler::vmaxnm(const DwVfpRegister dst, const DwVfpRegister src1,
3528f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                       const DwVfpRegister src2) {
3529f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // kSpecialCondition(31-28) | 11101(27-23) | D(22) | 00(21-20) | Vn(19-16) |
3530f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Vd(15-12) | 101(11-9) | sz=1(8) | N(7) | 0(6) | M(5) | 0(4) | Vm(3-0)
3531f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(IsEnabled(ARMv8));
3532f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  int vd, d;
3533f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  dst.split_code(&vd, &d);
3534f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  int vn, n;
3535f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  src1.split_code(&vn, &n);
3536f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  int vm, m;
3537f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  src2.split_code(&vm, &m);
3538f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
3539f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  emit(kSpecialCondition | 0x1D * B23 | d * B22 | vn * B16 | vd * B12 |
3540f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch       0x5 * B9 | B8 | n * B7 | m * B5 | vm);
3541f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch}
3542f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
3543f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochvoid Assembler::vmaxnm(const SwVfpRegister dst, const SwVfpRegister src1,
3544f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                       const SwVfpRegister src2) {
3545f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // kSpecialCondition(31-28) | 11101(27-23) | D(22) | 00(21-20) | Vn(19-16) |
3546f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Vd(15-12) | 101(11-9) | sz=0(8) | N(7) | 0(6) | M(5) | 0(4) | Vm(3-0)
3547f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(IsEnabled(ARMv8));
3548f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  int vd, d;
3549f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  dst.split_code(&vd, &d);
3550f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  int vn, n;
3551f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  src1.split_code(&vn, &n);
3552f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  int vm, m;
3553f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  src2.split_code(&vm, &m);
3554f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
3555f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  emit(kSpecialCondition | 0x1D * B23 | d * B22 | vn * B16 | vd * B12 |
3556f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch       0x5 * B9 | n * B7 | m * B5 | vm);
3557f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch}
3558f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
3559f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochvoid Assembler::vminnm(const DwVfpRegister dst, const DwVfpRegister src1,
3560f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                       const DwVfpRegister src2) {
3561f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // kSpecialCondition(31-28) | 11101(27-23) | D(22) | 00(21-20) | Vn(19-16) |
3562f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Vd(15-12) | 101(11-9) | sz=1(8) | N(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
3563f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(IsEnabled(ARMv8));
3564f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  int vd, d;
3565f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  dst.split_code(&vd, &d);
3566f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  int vn, n;
3567f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  src1.split_code(&vn, &n);
3568f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  int vm, m;
3569f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  src2.split_code(&vm, &m);
3570f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
3571f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  emit(kSpecialCondition | 0x1D * B23 | d * B22 | vn * B16 | vd * B12 |
3572f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch       0x5 * B9 | B8 | n * B7 | B6 | m * B5 | vm);
3573f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch}
3574f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
3575f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochvoid Assembler::vminnm(const SwVfpRegister dst, const SwVfpRegister src1,
3576f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                       const SwVfpRegister src2) {
3577f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // kSpecialCondition(31-28) | 11101(27-23) | D(22) | 00(21-20) | Vn(19-16) |
3578f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Vd(15-12) | 101(11-9) | sz=0(8) | N(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
3579f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(IsEnabled(ARMv8));
3580f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  int vd, d;
3581f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  dst.split_code(&vd, &d);
3582f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  int vn, n;
3583f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  src1.split_code(&vn, &n);
3584f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  int vm, m;
3585f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  src2.split_code(&vm, &m);
3586f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
3587f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  emit(kSpecialCondition | 0x1D * B23 | d * B22 | vn * B16 | vd * B12 |
3588f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch       0x5 * B9 | n * B7 | B6 | m * B5 | vm);
3589f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch}
3590f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
3591bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid Assembler::vsel(Condition cond, const DwVfpRegister dst,
3592bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                     const DwVfpRegister src1, const DwVfpRegister src2) {
3593bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // cond=kSpecialCondition(31-28) | 11100(27-23) | D(22) |
3594bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // vsel_cond=XX(21-20) | Vn(19-16) | Vd(15-12) | 101(11-9) | sz=1(8) | N(7) |
3595bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // 0(6) | M(5) | 0(4) | Vm(3-0)
3596f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(IsEnabled(ARMv8));
3597bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  int vd, d;
3598bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  dst.split_code(&vd, &d);
3599bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  int vn, n;
3600bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  src1.split_code(&vn, &n);
3601bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  int vm, m;
3602bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  src2.split_code(&vm, &m);
3603bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  int sz = 1;
3604bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
3605bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // VSEL has a special (restricted) condition encoding.
3606bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  //   eq(0b0000)... -> 0b00
3607bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  //   ge(0b1010)... -> 0b10
3608bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  //   gt(0b1100)... -> 0b11
3609bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  //   vs(0b0110)... -> 0b01
3610bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // No other conditions are supported.
3611bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  int vsel_cond = (cond >> 30) & 0x3;
3612bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if ((cond != eq) && (cond != ge) && (cond != gt) && (cond != vs)) {
3613bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    // We can implement some other conditions by swapping the inputs.
3614bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    DCHECK((cond == ne) | (cond == lt) | (cond == le) | (cond == vc));
3615bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    std::swap(vn, vm);
3616bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    std::swap(n, m);
3617bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
3618bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
3619bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  emit(kSpecialCondition | 0x1C * B23 | d * B22 | vsel_cond * B20 | vn * B16 |
3620bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch       vd * B12 | 0x5 * B9 | sz * B8 | n * B7 | m * B5 | vm);
3621bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
3622bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
3623bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid Assembler::vsel(Condition cond, const SwVfpRegister dst,
3624bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                     const SwVfpRegister src1, const SwVfpRegister src2) {
3625bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // cond=kSpecialCondition(31-28) | 11100(27-23) | D(22) |
3626bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // vsel_cond=XX(21-20) | Vn(19-16) | Vd(15-12) | 101(11-9) | sz=0(8) | N(7) |
3627bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // 0(6) | M(5) | 0(4) | Vm(3-0)
3628f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(IsEnabled(ARMv8));
3629bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  int vd, d;
3630bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  dst.split_code(&vd, &d);
3631bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  int vn, n;
3632bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  src1.split_code(&vn, &n);
3633bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  int vm, m;
3634bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  src2.split_code(&vm, &m);
3635bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  int sz = 0;
3636bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
3637bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // VSEL has a special (restricted) condition encoding.
3638bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  //   eq(0b0000)... -> 0b00
3639bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  //   ge(0b1010)... -> 0b10
3640bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  //   gt(0b1100)... -> 0b11
3641bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  //   vs(0b0110)... -> 0b01
3642bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // No other conditions are supported.
3643bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  int vsel_cond = (cond >> 30) & 0x3;
3644bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if ((cond != eq) && (cond != ge) && (cond != gt) && (cond != vs)) {
3645bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    // We can implement some other conditions by swapping the inputs.
3646bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    DCHECK((cond == ne) | (cond == lt) | (cond == le) | (cond == vc));
3647bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    std::swap(vn, vm);
3648bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    std::swap(n, m);
3649bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
3650bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
3651bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  emit(kSpecialCondition | 0x1C * B23 | d * B22 | vsel_cond * B20 | vn * B16 |
3652bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch       vd * B12 | 0x5 * B9 | sz * B8 | n * B7 | m * B5 | vm);
3653bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
3654014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3655014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::vsqrt(const DwVfpRegister dst,
3656014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                      const DwVfpRegister src,
3657014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                      const Condition cond) {
3658014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Instruction details available in ARM DDI 0406C.b, A8-1058.
3659014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 0001(19-16) |
3660014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Vd(15-12) | 101(11-9) | sz=1(8) | 11(7-6) | M(5) | 0(4) | Vm(3-0)
3661f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(VfpRegisterIsAvailable(dst));
3662f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(VfpRegisterIsAvailable(src));
3663014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int vd, d;
3664014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  dst.split_code(&vd, &d);
3665014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int vm, m;
3666014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  src.split_code(&vm, &m);
3667014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  emit(cond | 0x1D*B23 | d*B22 | 0x3*B20 | B16 | vd*B12 | 0x5*B9 | B8 | 0x3*B6 |
3668014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch       m*B5 | vm);
3669014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3670014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3671014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3672014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::vsqrt(const SwVfpRegister dst, const SwVfpRegister src,
3673014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                      const Condition cond) {
3674014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Instruction details available in ARM DDI 0406C.b, A8-1058.
3675014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 0001(19-16) |
3676014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Vd(15-12) | 101(11-9) | sz=0(8) | 11(7-6) | M(5) | 0(4) | Vm(3-0)
3677014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int vd, d;
3678014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  dst.split_code(&vd, &d);
3679014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int vm, m;
3680014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  src.split_code(&vm, &m);
3681014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  emit(cond | 0x1D * B23 | d * B22 | 0x3 * B20 | B16 | vd * B12 | 0x5 * B9 |
3682014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch       0x3 * B6 | m * B5 | vm);
3683014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3684014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3685014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
368690bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brennervoid Assembler::vmsr(Register dst, Condition cond) {
368790bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner  // Instruction details available in ARM DDI 0406A, A8-652.
368890bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner  // cond(31-28) | 1110 (27-24) | 1110(23-20)| 0001 (19-16) |
368990bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner  // Rt(15-12) | 1010 (11-8) | 0(7) | 00 (6-5) | 1(4) | 0000(3-0)
3690014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  emit(cond | 0xE * B24 | 0xE * B20 | B16 | dst.code() * B12 | 0xA * B8 | B4);
369190bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner}
369290bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner
369390bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner
3694d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid Assembler::vmrs(Register dst, Condition cond) {
3695d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Instruction details available in ARM DDI 0406A, A8-652.
3696d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // cond(31-28) | 1110 (27-24) | 1111(23-20)| 0001 (19-16) |
3697d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Rt(15-12) | 1010 (11-8) | 0(7) | 00 (6-5) | 1(4) | 0000(3-0)
3698014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  emit(cond | 0xE * B24 | 0xF * B20 | B16 | dst.code() * B12 | 0xA * B8 | B4);
3699d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
3700d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3701d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3702014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::vrinta(const SwVfpRegister dst, const SwVfpRegister src) {
3703014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // cond=kSpecialCondition(31-28) | 11101(27-23)| D(22) | 11(21-20) |
3704014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // 10(19-18) | RM=00(17-16) |  Vd(15-12) | 101(11-9) | sz=0(8) | 01(7-6) |
3705014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // M(5) | 0(4) | Vm(3-0)
3706f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(IsEnabled(ARMv8));
3707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int vd, d;
3708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  dst.split_code(&vd, &d);
3709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int vm, m;
3710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  src.split_code(&vm, &m);
3711014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  emit(kSpecialCondition | 0x1D * B23 | d * B22 | 0x3 * B20 | B19 | vd * B12 |
3712014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch       0x5 * B9 | B6 | m * B5 | vm);
3713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3716958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid Assembler::vrinta(const DwVfpRegister dst, const DwVfpRegister src) {
3717958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // cond=kSpecialCondition(31-28) | 11101(27-23)| D(22) | 11(21-20) |
3718958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // 10(19-18) | RM=00(17-16) |  Vd(15-12) | 101(11-9) | sz=1(8) | 01(7-6) |
3719958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // M(5) | 0(4) | Vm(3-0)
3720f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(IsEnabled(ARMv8));
3721958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int vd, d;
3722958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  dst.split_code(&vd, &d);
3723958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int vm, m;
3724958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  src.split_code(&vm, &m);
3725958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  emit(kSpecialCondition | 0x1D * B23 | d * B22 | 0x3 * B20 | B19 | vd * B12 |
3726958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier       0x5 * B9 | B8 | B6 | m * B5 | vm);
3727958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
3728958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
3729958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
3730014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::vrintn(const SwVfpRegister dst, const SwVfpRegister src) {
3731014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // cond=kSpecialCondition(31-28) | 11101(27-23)| D(22) | 11(21-20) |
3732014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // 10(19-18) | RM=01(17-16) |  Vd(15-12) | 101(11-9) | sz=0(8) | 01(7-6) |
3733014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // M(5) | 0(4) | Vm(3-0)
3734f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(IsEnabled(ARMv8));
3735014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int vd, d;
3736014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  dst.split_code(&vd, &d);
3737014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int vm, m;
3738014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  src.split_code(&vm, &m);
3739014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  emit(kSpecialCondition | 0x1D * B23 | d * B22 | 0x3 * B20 | B19 | 0x1 * B16 |
3740014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch       vd * B12 | 0x5 * B9 | B6 | m * B5 | vm);
3741014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3742014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3743014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3744958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid Assembler::vrintn(const DwVfpRegister dst, const DwVfpRegister src) {
3745958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // cond=kSpecialCondition(31-28) | 11101(27-23)| D(22) | 11(21-20) |
3746958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // 10(19-18) | RM=01(17-16) |  Vd(15-12) | 101(11-9) | sz=1(8) | 01(7-6) |
3747958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // M(5) | 0(4) | Vm(3-0)
3748f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(IsEnabled(ARMv8));
3749958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int vd, d;
3750958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  dst.split_code(&vd, &d);
3751958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int vm, m;
3752958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  src.split_code(&vm, &m);
3753958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  emit(kSpecialCondition | 0x1D * B23 | d * B22 | 0x3 * B20 | B19 | 0x1 * B16 |
3754958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier       vd * B12 | 0x5 * B9 | B8 | B6 | m * B5 | vm);
3755958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
3756958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
3757958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
3758014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::vrintp(const SwVfpRegister dst, const SwVfpRegister src) {
3759014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // cond=kSpecialCondition(31-28) | 11101(27-23)| D(22) | 11(21-20) |
3760014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // 10(19-18) | RM=10(17-16) |  Vd(15-12) | 101(11-9) | sz=0(8) | 01(7-6) |
3761014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // M(5) | 0(4) | Vm(3-0)
3762f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(IsEnabled(ARMv8));
3763014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int vd, d;
3764014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  dst.split_code(&vd, &d);
3765014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int vm, m;
3766014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  src.split_code(&vm, &m);
3767014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  emit(kSpecialCondition | 0x1D * B23 | d * B22 | 0x3 * B20 | B19 | 0x2 * B16 |
3768014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch       vd * B12 | 0x5 * B9 | B6 | m * B5 | vm);
3769014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3770014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3771014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3772958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid Assembler::vrintp(const DwVfpRegister dst, const DwVfpRegister src) {
3773958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // cond=kSpecialCondition(31-28) | 11101(27-23)| D(22) | 11(21-20) |
3774958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // 10(19-18) | RM=10(17-16) |  Vd(15-12) | 101(11-9) | sz=1(8) | 01(7-6) |
3775958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // M(5) | 0(4) | Vm(3-0)
3776f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(IsEnabled(ARMv8));
3777958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int vd, d;
3778958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  dst.split_code(&vd, &d);
3779958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int vm, m;
3780958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  src.split_code(&vm, &m);
3781958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  emit(kSpecialCondition | 0x1D * B23 | d * B22 | 0x3 * B20 | B19 | 0x2 * B16 |
3782958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier       vd * B12 | 0x5 * B9 | B8 | B6 | m * B5 | vm);
3783958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
3784958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
3785958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
3786014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::vrintm(const SwVfpRegister dst, const SwVfpRegister src) {
3787014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // cond=kSpecialCondition(31-28) | 11101(27-23)| D(22) | 11(21-20) |
3788014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // 10(19-18) | RM=11(17-16) |  Vd(15-12) | 101(11-9) | sz=0(8) | 01(7-6) |
3789014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // M(5) | 0(4) | Vm(3-0)
3790f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(IsEnabled(ARMv8));
3791014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int vd, d;
3792014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  dst.split_code(&vd, &d);
3793014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int vm, m;
3794014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  src.split_code(&vm, &m);
3795014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  emit(kSpecialCondition | 0x1D * B23 | d * B22 | 0x3 * B20 | B19 | 0x3 * B16 |
3796014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch       vd * B12 | 0x5 * B9 | B6 | m * B5 | vm);
3797014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3798014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3799014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3800958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid Assembler::vrintm(const DwVfpRegister dst, const DwVfpRegister src) {
3801958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // cond=kSpecialCondition(31-28) | 11101(27-23)| D(22) | 11(21-20) |
3802958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // 10(19-18) | RM=11(17-16) |  Vd(15-12) | 101(11-9) | sz=1(8) | 01(7-6) |
3803958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // M(5) | 0(4) | Vm(3-0)
3804f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(IsEnabled(ARMv8));
3805958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int vd, d;
3806958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  dst.split_code(&vd, &d);
3807958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int vm, m;
3808958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  src.split_code(&vm, &m);
3809958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  emit(kSpecialCondition | 0x1D * B23 | d * B22 | 0x3 * B20 | B19 | 0x3 * B16 |
3810958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier       vd * B12 | 0x5 * B9 | B8 | B6 | m * B5 | vm);
3811958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
3812958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
3813958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
3814014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::vrintz(const SwVfpRegister dst, const SwVfpRegister src,
3815014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                       const Condition cond) {
3816014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 011(19-17) | 0(16) |
3817014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Vd(15-12) | 101(11-9) | sz=0(8) | op=1(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
3818f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(IsEnabled(ARMv8));
3819014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int vd, d;
3820014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  dst.split_code(&vd, &d);
3821014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int vm, m;
3822014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  src.split_code(&vm, &m);
3823014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  emit(cond | 0x1D * B23 | d * B22 | 0x3 * B20 | 0x3 * B17 | vd * B12 |
3824014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch       0x5 * B9 | B7 | B6 | m * B5 | vm);
3825014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3826014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3827014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3828958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid Assembler::vrintz(const DwVfpRegister dst, const DwVfpRegister src,
3829958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                       const Condition cond) {
3830958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 011(19-17) | 0(16) |
3831958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Vd(15-12) | 101(11-9) | sz=1(8) | op=1(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
3832f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(IsEnabled(ARMv8));
3833958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int vd, d;
3834958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  dst.split_code(&vd, &d);
3835958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int vm, m;
3836958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  src.split_code(&vm, &m);
3837958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  emit(cond | 0x1D * B23 | d * B22 | 0x3 * B20 | 0x3 * B17 | vd * B12 |
3838958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier       0x5 * B9 | B8 | B7 | B6 | m * B5 | vm);
3839958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
3840958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
3841958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
3842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Support for NEON.
3843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::vld1(NeonSize size,
3845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     const NeonListOperand& dst,
3846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     const NeonMemOperand& src) {
3847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8.8.320.
3848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // 1111(31-28) | 01000(27-23) | D(22) | 10(21-20) | Rn(19-16) |
3849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Vd(15-12) | type(11-8) | size(7-6) | align(5-4) | Rm(3-0)
3850f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(IsEnabled(NEON));
3851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int vd, d;
3852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  dst.base().split_code(&vd, &d);
3853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  emit(0xFU*B28 | 4*B24 | d*B22 | 2*B20 | src.rn().code()*B16 | vd*B12 |
3854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       dst.type()*B8 | size*B6 | src.align()*B4 | src.rm().code());
3855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::vst1(NeonSize size,
3859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     const NeonListOperand& src,
3860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     const NeonMemOperand& dst) {
3861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8.8.404.
3862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // 1111(31-28) | 01000(27-23) | D(22) | 00(21-20) | Rn(19-16) |
3863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Vd(15-12) | type(11-8) | size(7-6) | align(5-4) | Rm(3-0)
3864f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(IsEnabled(NEON));
3865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int vd, d;
3866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  src.base().split_code(&vd, &d);
3867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  emit(0xFU*B28 | 4*B24 | d*B22 | dst.rn().code()*B16 | vd*B12 | src.type()*B8 |
3868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       size*B6 | dst.align()*B4 | dst.rm().code());
3869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::vmovl(NeonDataType dt, QwNeonRegister dst, DwVfpRegister src) {
3873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8.8.346.
3874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // 1111(31-28) | 001(27-25) | U(24) | 1(23) | D(22) | imm3(21-19) |
3875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // 000(18-16) | Vd(15-12) | 101000(11-6) | M(5) | 1(4) | Vm(3-0)
3876f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(IsEnabled(NEON));
3877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int vd, d;
3878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  dst.split_code(&vd, &d);
3879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int vm, m;
3880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  src.split_code(&vm, &m);
388162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int U = NeonU(dt);
388262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int imm3 = 1 << NeonSz(dt);
388362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  emit(0xFU * B28 | B25 | U * B24 | B23 | d * B22 | imm3 * B19 | vd * B12 |
388462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch       0xA * B8 | m * B5 | B4 | vm);
388562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
388662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
388762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochstatic int EncodeScalar(NeonDataType dt, int index) {
388862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int opc1_opc2 = 0;
388962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK_LE(0, index);
389062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  switch (dt) {
389162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case NeonS8:
389262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case NeonU8:
389362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      DCHECK_GT(8, index);
389462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      opc1_opc2 = 0x8 | index;
389562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      break;
389662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case NeonS16:
389762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case NeonU16:
389862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      DCHECK_GT(4, index);
389962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      opc1_opc2 = 0x1 | (index << 1);
390062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      break;
390162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case NeonS32:
390262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case NeonU32:
390362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      DCHECK_GT(2, index);
390462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      opc1_opc2 = index << 2;
390562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      break;
390662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    default:
390762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      UNREACHABLE();
390862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      break;
390962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
391062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return (opc1_opc2 >> 2) * B21 | (opc1_opc2 & 0x3) * B5;
39118defd9ff6930b4e24729971a61cf7469daf119beSteve Block}
39128defd9ff6930b4e24729971a61cf7469daf119beSteve Block
391362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid Assembler::vmov(NeonDataType dt, DwVfpRegister dst, int index,
391462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                     Register src) {
391562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8.8.940.
391662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // vmov ARM core register to scalar.
391762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(dt == NeonS32 || dt == NeonU32 || IsEnabled(NEON));
391862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int vd, d;
391962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  dst.split_code(&vd, &d);
392062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int opc1_opc2 = EncodeScalar(dt, index);
392162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  emit(0xEEu * B24 | vd * B16 | src.code() * B12 | 0xB * B8 | d * B7 | B4 |
392262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch       opc1_opc2);
392362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
3924f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
392562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid Assembler::vmov(NeonDataType dt, Register dst, DwVfpRegister src,
392662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                     int index) {
392762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8.8.942.
392862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // vmov Arm scalar to core register.
392962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(dt == NeonS32 || dt == NeonU32 || IsEnabled(NEON));
393062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int vn, n;
393162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  src.split_code(&vn, &n);
393262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int opc1_opc2 = EncodeScalar(dt, index);
393362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int u = NeonU(dt);
393462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  emit(0xEEu * B24 | u * B23 | B20 | vn * B16 | dst.code() * B12 | 0xB * B8 |
393562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch       n * B7 | B4 | opc1_opc2);
393662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
3937f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
393862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid Assembler::vmov(const QwNeonRegister dst, const QwNeonRegister src) {
393962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8-938.
394062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // vmov is encoded as vorr.
394162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  vorr(dst, src, src);
394262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
394362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
394462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid Assembler::vmvn(const QwNeonRegister dst, const QwNeonRegister src) {
394562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(IsEnabled(NEON));
394662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8-966.
394762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(VfpRegisterIsAvailable(dst));
394862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(VfpRegisterIsAvailable(src));
394962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int vd, d;
395062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  dst.split_code(&vd, &d);
395162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int vm, m;
395262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  src.split_code(&vm, &m);
395362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  emit(0x1E7U * B23 | d * B22 | 3 * B20 | vd * B12 | 0x17 * B6 | m * B5 | vm);
395462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
395562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
395662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid Assembler::vswp(DwVfpRegister dst, DwVfpRegister src) {
395762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8.8.418.
395862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // 1111(31-28) | 00111(27-23) | D(22) | 110010(21-16) |
395962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Vd(15-12) | 000000(11-6) | M(5) | 0(4) | Vm(3-0)
396062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(IsEnabled(NEON));
396162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int vd, d;
396262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  dst.split_code(&vd, &d);
396362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int vm, m;
396462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  src.split_code(&vm, &m);
396562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  emit(0xFU * B28 | 7 * B23 | d * B22 | 0x32 * B16 | vd * B12 | m * B5 | vm);
396662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
396762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
396862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid Assembler::vswp(QwNeonRegister dst, QwNeonRegister src) {
396962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8.8.418.
397062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // 1111(31-28) | 00111(27-23) | D(22) | 110010(21-16) |
397162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Vd(15-12) | 000000(11-6) | M(5) | 0(4) | Vm(3-0)
397262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(IsEnabled(NEON));
397362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int vd, d;
397462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  dst.split_code(&vd, &d);
397562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int vm, m;
397662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  src.split_code(&vm, &m);
397762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  emit(0xFU * B28 | 7 * B23 | d * B22 | 0x32 * B16 | vd * B12 | B6 | m * B5 |
397862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch       vm);
397962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
398062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
398162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid Assembler::vdup(NeonSize size, const QwNeonRegister dst,
398262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                     const Register src) {
398362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(IsEnabled(NEON));
398462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8-886.
398562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int B = 0, E = 0;
398662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  switch (size) {
398762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case Neon8:
398862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      B = 1;
398962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      break;
399062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case Neon16:
399162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      E = 1;
399262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      break;
399362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case Neon32:
399462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      break;
399562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    default:
399662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      UNREACHABLE();
399762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      break;
399862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
399962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int vd, d;
400062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  dst.split_code(&vd, &d);
400162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
400262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  emit(al | 0x1D * B23 | B * B22 | B21 | vd * B16 | src.code() * B12 |
400362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch       0xB * B8 | d * B7 | E * B5 | B4);
400462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
400562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
400662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid Assembler::vdup(const QwNeonRegister dst, const SwVfpRegister src) {
400762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(IsEnabled(NEON));
400862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8-884.
400962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int index = src.code() & 1;
401062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int d_reg = src.code() / 2;
401162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int imm4 = 4 | index << 3;  // esize = 32, index in bit 3.
401262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int vd, d;
401362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  dst.split_code(&vd, &d);
401462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int vm, m;
401562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DwVfpRegister::from_code(d_reg).split_code(&vm, &m);
401662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
401762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  emit(0x1E7U * B23 | d * B22 | 0x3 * B20 | imm4 * B16 | vd * B12 | 0x18 * B7 |
401862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch       B6 | m * B5 | vm);
401962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
402062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
402162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch// Encode NEON vcvt.src_type.dst_type instruction.
402262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochstatic Instr EncodeNeonVCVT(const VFPType dst_type, const QwNeonRegister dst,
402362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                            const VFPType src_type, const QwNeonRegister src) {
402462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(src_type != dst_type);
402562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(src_type == F32 || dst_type == F32);
402662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8.8.868.
402762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int vd, d;
402862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  dst.split_code(&vd, &d);
402962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int vm, m;
403062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  src.split_code(&vm, &m);
403162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
403262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int op = 0;
403362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (src_type == F32) {
403462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    DCHECK(dst_type == S32 || dst_type == U32);
403562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    op = dst_type == U32 ? 3 : 2;
4036f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  } else {
403762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    DCHECK(src_type == S32 || src_type == U32);
403862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    op = src_type == U32 ? 1 : 0;
4039f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  }
404062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
404162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return 0x1E7U * B23 | d * B22 | 0x3B * B16 | vd * B12 | 0x3 * B9 | op * B7 |
404262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch         B6 | m * B5 | vm;
404362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
404462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
404562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid Assembler::vcvt_f32_s32(const QwNeonRegister dst,
404662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                             const QwNeonRegister src) {
404762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(IsEnabled(NEON));
404862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(VfpRegisterIsAvailable(dst));
404962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(VfpRegisterIsAvailable(src));
405062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  emit(EncodeNeonVCVT(F32, dst, S32, src));
405162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
405262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
405362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid Assembler::vcvt_f32_u32(const QwNeonRegister dst,
405462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                             const QwNeonRegister src) {
405562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(IsEnabled(NEON));
405662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(VfpRegisterIsAvailable(dst));
405762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(VfpRegisterIsAvailable(src));
405862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  emit(EncodeNeonVCVT(F32, dst, U32, src));
405962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
406062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
406162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid Assembler::vcvt_s32_f32(const QwNeonRegister dst,
406262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                             const QwNeonRegister src) {
406362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(IsEnabled(NEON));
406462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(VfpRegisterIsAvailable(dst));
406562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(VfpRegisterIsAvailable(src));
406662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  emit(EncodeNeonVCVT(S32, dst, F32, src));
406762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
406862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
406962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid Assembler::vcvt_u32_f32(const QwNeonRegister dst,
407062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                             const QwNeonRegister src) {
407162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(IsEnabled(NEON));
407262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(VfpRegisterIsAvailable(dst));
407362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(VfpRegisterIsAvailable(src));
407462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  emit(EncodeNeonVCVT(U32, dst, F32, src));
407562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
407662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
407762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch// op is instr->Bits(11, 7).
407862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochstatic Instr EncodeNeonUnaryOp(int op, bool is_float, NeonSize size,
407962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                               const QwNeonRegister dst,
408062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                               const QwNeonRegister src) {
408162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK_IMPLIES(is_float, size == Neon32);
408262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int vd, d;
408362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  dst.split_code(&vd, &d);
408462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int vm, m;
408562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  src.split_code(&vm, &m);
408662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int F = is_float ? 1 : 0;
408762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return 0x1E7U * B23 | d * B22 | 0x3 * B20 | size * B18 | B16 | vd * B12 |
408862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch         F * B10 | B8 | op * B7 | B6 | m * B5 | vm;
408962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
409062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
409162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid Assembler::vabs(const QwNeonRegister dst, const QwNeonRegister src) {
409262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Qd = vabs.f<size>(Qn, Qm) SIMD floating point absolute value.
409362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8.8.824.
409462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(IsEnabled(NEON));
409562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  emit(EncodeNeonUnaryOp(0x6, true, Neon32, dst, src));
409662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
409762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
409862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid Assembler::vabs(NeonSize size, const QwNeonRegister dst,
409962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                     const QwNeonRegister src) {
410062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Qd = vabs.s<size>(Qn, Qm) SIMD integer absolute value.
410162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8.8.824.
410262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(IsEnabled(NEON));
410362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  emit(EncodeNeonUnaryOp(0x6, false, size, dst, src));
410462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
410562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
410662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid Assembler::vneg(const QwNeonRegister dst, const QwNeonRegister src) {
410762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Qd = vabs.f<size>(Qn, Qm) SIMD floating point negate.
410862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8.8.968.
410962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(IsEnabled(NEON));
411062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  emit(EncodeNeonUnaryOp(0x7, true, Neon32, dst, src));
411162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
411262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
411362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid Assembler::vneg(NeonSize size, const QwNeonRegister dst,
411462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                     const QwNeonRegister src) {
411562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Qd = vabs.s<size>(Qn, Qm) SIMD integer negate.
411662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8.8.968.
411762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(IsEnabled(NEON));
411862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  emit(EncodeNeonUnaryOp(0x7, false, size, dst, src));
411962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
412062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
412162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid Assembler::veor(DwVfpRegister dst, DwVfpRegister src1,
412262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                     DwVfpRegister src2) {
412362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Dd = veor(Dn, Dm) 64 bit integer exclusive OR.
412462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8.8.888.
412562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(IsEnabled(NEON));
412662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int vd, d;
412762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  dst.split_code(&vd, &d);
412862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int vn, n;
412962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  src1.split_code(&vn, &n);
413062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int vm, m;
413162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  src2.split_code(&vm, &m);
413262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  emit(0x1E6U * B23 | d * B22 | vn * B16 | vd * B12 | B8 | n * B7 | m * B5 |
413362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch       B4 | vm);
413462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
413562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
413662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochenum BinaryBitwiseOp { VAND, VBIC, VBIF, VBIT, VBSL, VEOR, VORR, VORN };
413762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
413862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochstatic Instr EncodeNeonBinaryBitwiseOp(BinaryBitwiseOp op,
413962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                       const QwNeonRegister dst,
414062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                       const QwNeonRegister src1,
414162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                       const QwNeonRegister src2) {
414262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int op_encoding = 0;
414362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  switch (op) {
414462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case VBIC:
414562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      op_encoding = 0x1 * B20;
414662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      break;
414762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case VBIF:
414862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      op_encoding = B24 | 0x3 * B20;
414962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      break;
415062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case VBIT:
415162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      op_encoding = B24 | 0x2 * B20;
415262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      break;
415362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case VBSL:
415462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      op_encoding = B24 | 0x1 * B20;
415562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      break;
415662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case VEOR:
415762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      op_encoding = B24;
415862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      break;
415962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case VORR:
416062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      op_encoding = 0x2 * B20;
416162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      break;
416262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case VORN:
416362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      op_encoding = 0x3 * B20;
416462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      break;
416562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case VAND:
416662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      // op_encoding is 0.
416762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      break;
416862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    default:
416962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      UNREACHABLE();
417062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      break;
417162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
417262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int vd, d;
417362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  dst.split_code(&vd, &d);
417462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int vn, n;
417562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  src1.split_code(&vn, &n);
417662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int vm, m;
417762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  src2.split_code(&vm, &m);
417862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return 0x1E4U * B23 | op_encoding | d * B22 | vn * B16 | vd * B12 | B8 |
417962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch         n * B7 | B6 | m * B5 | B4 | vm;
418062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
418162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
418262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid Assembler::vand(QwNeonRegister dst, QwNeonRegister src1,
418362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                     QwNeonRegister src2) {
418462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Qd = vand(Qn, Qm) SIMD AND.
418562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8.8.836.
418662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(IsEnabled(NEON));
418762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  emit(EncodeNeonBinaryBitwiseOp(VAND, dst, src1, src2));
418862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
418962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
419062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid Assembler::vbsl(QwNeonRegister dst, const QwNeonRegister src1,
419162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                     const QwNeonRegister src2) {
419262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(IsEnabled(NEON));
419362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Qd = vbsl(Qn, Qm) SIMD bitwise select.
419462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8-844.
419562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  emit(EncodeNeonBinaryBitwiseOp(VBSL, dst, src1, src2));
419662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
419762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
419862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid Assembler::veor(QwNeonRegister dst, QwNeonRegister src1,
419962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                     QwNeonRegister src2) {
420062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Qd = veor(Qn, Qm) SIMD exclusive OR.
420162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8.8.888.
420262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(IsEnabled(NEON));
420362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  emit(EncodeNeonBinaryBitwiseOp(VEOR, dst, src1, src2));
420462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
420562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
420662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid Assembler::vorr(QwNeonRegister dst, QwNeonRegister src1,
420762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                     QwNeonRegister src2) {
420862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Qd = vorr(Qn, Qm) SIMD OR.
420962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8.8.976.
421062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(IsEnabled(NEON));
421162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  emit(EncodeNeonBinaryBitwiseOp(VORR, dst, src1, src2));
421262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
421362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
421462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochenum FPBinOp {
421562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  VADDF,
421662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  VSUBF,
421762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  VMULF,
421862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  VMINF,
421962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  VMAXF,
422062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  VRECPS,
422162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  VRSQRTS,
422262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  VCEQF,
422362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  VCGEF,
422462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  VCGTF
422562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch};
422662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
422762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochstatic Instr EncodeNeonBinOp(FPBinOp op, QwNeonRegister dst,
422862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                             QwNeonRegister src1, QwNeonRegister src2) {
422962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int op_encoding = 0;
423062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  switch (op) {
423162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case VADDF:
423262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      op_encoding = 0xD * B8;
423362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      break;
423462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case VSUBF:
423562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      op_encoding = B21 | 0xD * B8;
423662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      break;
423762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case VMULF:
423862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      op_encoding = B24 | 0xD * B8 | B4;
423962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      break;
424062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case VMINF:
424162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      op_encoding = B21 | 0xF * B8;
424262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      break;
424362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case VMAXF:
424462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      op_encoding = 0xF * B8;
424562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      break;
424662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case VRECPS:
424762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      op_encoding = 0xF * B8 | B4;
424862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      break;
424962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case VRSQRTS:
425062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      op_encoding = B21 | 0xF * B8 | B4;
425162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      break;
425262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case VCEQF:
425362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      op_encoding = 0xE * B8;
425462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      break;
425562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case VCGEF:
425662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      op_encoding = B24 | 0xE * B8;
425762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      break;
425862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case VCGTF:
425962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      op_encoding = B24 | B21 | 0xE * B8;
426062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      break;
426162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    default:
426262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      UNREACHABLE();
426362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      break;
426462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
426562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int vd, d;
426662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  dst.split_code(&vd, &d);
426762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int vn, n;
426862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  src1.split_code(&vn, &n);
426962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int vm, m;
427062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  src2.split_code(&vm, &m);
427162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return 0x1E4U * B23 | d * B22 | vn * B16 | vd * B12 | n * B7 | B6 | m * B5 |
427262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch         vm | op_encoding;
427362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
427462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
427562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochenum IntegerBinOp {
427662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  VADD,
427762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  VQADD,
427862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  VSUB,
427962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  VQSUB,
428062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  VMUL,
428162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  VMIN,
428262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  VMAX,
428362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  VTST,
428462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  VCEQ,
428562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  VCGE,
428662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  VCGT
428762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch};
428862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
428962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochstatic Instr EncodeNeonBinOp(IntegerBinOp op, NeonDataType dt,
429062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                             const QwNeonRegister dst,
429162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                             const QwNeonRegister src1,
429262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                             const QwNeonRegister src2) {
429362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int op_encoding = 0;
429462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  switch (op) {
429562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case VADD:
429662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      op_encoding = 0x8 * B8;
429762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      break;
429862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case VQADD:
429962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      op_encoding = B4;
430062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      break;
430162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case VSUB:
430262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      op_encoding = B24 | 0x8 * B8;
430362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      break;
430462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case VQSUB:
430562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      op_encoding = 0x2 * B8 | B4;
430662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      break;
430762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case VMUL:
430862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      op_encoding = 0x9 * B8 | B4;
430962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      break;
431062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case VMIN:
431162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      op_encoding = 0x6 * B8 | B4;
431262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      break;
431362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case VMAX:
431462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      op_encoding = 0x6 * B8;
431562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      break;
431662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case VTST:
431762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      op_encoding = 0x8 * B8 | B4;
431862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      break;
431962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case VCEQ:
432062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      op_encoding = B24 | 0x8 * B8 | B4;
432162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      break;
432262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case VCGE:
432362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      op_encoding = 0x3 * B8 | B4;
432462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      break;
432562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case VCGT:
432662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      op_encoding = 0x3 * B8;
432762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      break;
432862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    default:
432962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      UNREACHABLE();
433062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      break;
433162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
433262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int vd, d;
433362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  dst.split_code(&vd, &d);
433462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int vn, n;
433562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  src1.split_code(&vn, &n);
433662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int vm, m;
433762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  src2.split_code(&vm, &m);
433862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int size = NeonSz(dt);
433962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int u = NeonU(dt);
434062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return 0x1E4U * B23 | u * B24 | d * B22 | size * B20 | vn * B16 | vd * B12 |
434162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch         n * B7 | B6 | m * B5 | vm | op_encoding;
434262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
434362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
434462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochstatic Instr EncodeNeonBinOp(IntegerBinOp op, NeonSize size,
434562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                             const QwNeonRegister dst,
434662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                             const QwNeonRegister src1,
434762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                             const QwNeonRegister src2) {
434862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Map NeonSize values to the signed values in NeonDataType, so the U bit
434962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // will be 0.
435062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return EncodeNeonBinOp(op, static_cast<NeonDataType>(size), dst, src1, src2);
435162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
435262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
435362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid Assembler::vadd(QwNeonRegister dst, QwNeonRegister src1,
435462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                     QwNeonRegister src2) {
435562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(IsEnabled(NEON));
435662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Qd = vadd(Qn, Qm) SIMD floating point addition.
435762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8-830.
435862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  emit(EncodeNeonBinOp(VADDF, dst, src1, src2));
435962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
436062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
436162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid Assembler::vadd(NeonSize size, QwNeonRegister dst, QwNeonRegister src1,
436262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                     QwNeonRegister src2) {
436362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(IsEnabled(NEON));
436462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Qd = vadd(Qn, Qm) SIMD integer addition.
436562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8-828.
436662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  emit(EncodeNeonBinOp(VADD, size, dst, src1, src2));
436762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
436862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
436962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid Assembler::vqadd(NeonDataType dt, QwNeonRegister dst, QwNeonRegister src1,
437062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                      QwNeonRegister src2) {
437162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(IsEnabled(NEON));
437262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Qd = vqadd(Qn, Qm) SIMD integer saturating addition.
437362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8-996.
437462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  emit(EncodeNeonBinOp(VQADD, dt, dst, src1, src2));
437562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
437662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
437762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid Assembler::vsub(QwNeonRegister dst, QwNeonRegister src1,
437862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                     QwNeonRegister src2) {
437962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(IsEnabled(NEON));
438062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Qd = vsub(Qn, Qm) SIMD floating point subtraction.
438162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8-1086.
438262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  emit(EncodeNeonBinOp(VSUBF, dst, src1, src2));
438362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
438462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
438562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid Assembler::vsub(NeonSize size, QwNeonRegister dst, QwNeonRegister src1,
438662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                     QwNeonRegister src2) {
438762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(IsEnabled(NEON));
438862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Qd = vsub(Qn, Qm) SIMD integer subtraction.
438962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8-1084.
439062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  emit(EncodeNeonBinOp(VSUB, size, dst, src1, src2));
439162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
439262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
439362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid Assembler::vqsub(NeonDataType dt, QwNeonRegister dst, QwNeonRegister src1,
439462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                      QwNeonRegister src2) {
439562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(IsEnabled(NEON));
439662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Qd = vqsub(Qn, Qm) SIMD integer saturating subtraction.
439762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8-1020.
439862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  emit(EncodeNeonBinOp(VQSUB, dt, dst, src1, src2));
439962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
440062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
440162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid Assembler::vmul(QwNeonRegister dst, QwNeonRegister src1,
440262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                     QwNeonRegister src2) {
440362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(IsEnabled(NEON));
440462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Qd = vadd(Qn, Qm) SIMD floating point multiply.
440562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8-958.
440662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  emit(EncodeNeonBinOp(VMULF, dst, src1, src2));
440762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
440862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
440962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid Assembler::vmul(NeonSize size, QwNeonRegister dst,
441062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                     const QwNeonRegister src1, const QwNeonRegister src2) {
441162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(IsEnabled(NEON));
441262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Qd = vadd(Qn, Qm) SIMD integer multiply.
441362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8-960.
441462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  emit(EncodeNeonBinOp(VMUL, size, dst, src1, src2));
441562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
441662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
441762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid Assembler::vmin(const QwNeonRegister dst, const QwNeonRegister src1,
441862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                     const QwNeonRegister src2) {
441962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(IsEnabled(NEON));
442062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Qd = vmin(Qn, Qm) SIMD floating point MIN.
442162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8-928.
442262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  emit(EncodeNeonBinOp(VMINF, dst, src1, src2));
442362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
442462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
442562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid Assembler::vmin(NeonDataType dt, QwNeonRegister dst, QwNeonRegister src1,
442662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                     QwNeonRegister src2) {
442762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(IsEnabled(NEON));
442862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Qd = vmin(Qn, Qm) SIMD integer MIN.
442962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8-926.
443062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  emit(EncodeNeonBinOp(VMIN, dt, dst, src1, src2));
443162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
443262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
443362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid Assembler::vmax(QwNeonRegister dst, QwNeonRegister src1,
443462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                     QwNeonRegister src2) {
443562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(IsEnabled(NEON));
443662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Qd = vmax(Qn, Qm) SIMD floating point MAX.
443762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8-928.
443862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  emit(EncodeNeonBinOp(VMAXF, dst, src1, src2));
443962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
444062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
444162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid Assembler::vmax(NeonDataType dt, QwNeonRegister dst, QwNeonRegister src1,
444262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                     QwNeonRegister src2) {
444362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(IsEnabled(NEON));
444462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Qd = vmax(Qn, Qm) SIMD integer MAX.
444562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8-926.
444662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  emit(EncodeNeonBinOp(VMAX, dt, dst, src1, src2));
444762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
444862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
444962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochenum NeonShiftOp { VSHL, VSHR };
445062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
445162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochstatic Instr EncodeNeonShiftOp(NeonShiftOp op, NeonDataType dt,
445262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                               QwNeonRegister dst, QwNeonRegister src,
445362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                               int shift) {
445462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int vd, d;
445562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  dst.split_code(&vd, &d);
445662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int vm, m;
445762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  src.split_code(&vm, &m);
445862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int size_in_bits = kBitsPerByte << NeonSz(dt);
445962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int op_encoding = 0;
446062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int imm6 = 0;
446162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (op == VSHL) {
446262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    DCHECK(shift >= 0 && size_in_bits > shift);
446362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    imm6 = size_in_bits + shift;
446462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    op_encoding = 0x5 * B8;
446562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  } else {
446662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    DCHECK_EQ(VSHR, op);
446762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    DCHECK(shift > 0 && size_in_bits >= shift);
446862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    imm6 = 2 * size_in_bits - shift;
446962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    op_encoding = NeonU(dt) * B24;
447062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
447162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return 0x1E5U * B23 | d * B22 | imm6 * B16 | vd * B12 | B6 | m * B5 | B4 |
447262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch         vm | op_encoding;
447362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
447462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
447562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid Assembler::vshl(NeonDataType dt, QwNeonRegister dst, QwNeonRegister src,
447662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                     int shift) {
447762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(IsEnabled(NEON));
447862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Qd = vshl(Qm, bits) SIMD shift left immediate.
447962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8-1046.
448062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  emit(EncodeNeonShiftOp(VSHL, dt, dst, src, shift));
448162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
448262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
448362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid Assembler::vshr(NeonDataType dt, QwNeonRegister dst, QwNeonRegister src,
448462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                     int shift) {
448562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(IsEnabled(NEON));
448662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Qd = vshl(Qm, bits) SIMD shift right immediate.
448762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8-1052.
448862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  emit(EncodeNeonShiftOp(VSHR, dt, dst, src, shift));
448962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
449062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
449162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochstatic Instr EncodeNeonEstimateOp(bool is_rsqrt, QwNeonRegister dst,
449262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                  QwNeonRegister src) {
449362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int vd, d;
449462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  dst.split_code(&vd, &d);
449562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int vm, m;
449662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  src.split_code(&vm, &m);
449762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int rsqrt = is_rsqrt ? 1 : 0;
449862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return 0x1E7U * B23 | d * B22 | 0x3B * B16 | vd * B12 | 0x5 * B8 |
449962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch         rsqrt * B7 | B6 | m * B5 | vm;
450062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
450162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
450262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid Assembler::vrecpe(QwNeonRegister dst, QwNeonRegister src) {
450362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(IsEnabled(NEON));
450462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Qd = vrecpe(Qm) SIMD reciprocal estimate.
450562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8-1024.
450662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  emit(EncodeNeonEstimateOp(false, dst, src));
450762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
450862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
450962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid Assembler::vrsqrte(QwNeonRegister dst, QwNeonRegister src) {
451062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(IsEnabled(NEON));
451162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Qd = vrsqrte(Qm) SIMD reciprocal square root estimate.
451262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8-1038.
451362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  emit(EncodeNeonEstimateOp(true, dst, src));
451462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
451562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
451662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid Assembler::vrecps(QwNeonRegister dst, QwNeonRegister src1,
451762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                       QwNeonRegister src2) {
451862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(IsEnabled(NEON));
451962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Qd = vrecps(Qn, Qm) SIMD reciprocal refinement step.
452062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8-1026.
452162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  emit(EncodeNeonBinOp(VRECPS, dst, src1, src2));
452262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
452362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
452462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid Assembler::vrsqrts(QwNeonRegister dst, QwNeonRegister src1,
452562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                        QwNeonRegister src2) {
452662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(IsEnabled(NEON));
452762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Qd = vrsqrts(Qn, Qm) SIMD reciprocal square root refinement step.
452862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8-1040.
452962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  emit(EncodeNeonBinOp(VRSQRTS, dst, src1, src2));
453062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
453162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
453262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid Assembler::vtst(NeonSize size, QwNeonRegister dst, QwNeonRegister src1,
453362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                     QwNeonRegister src2) {
453462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(IsEnabled(NEON));
453562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Qd = vtst(Qn, Qm) SIMD test integer operands.
453662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8-1098.
453762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  emit(EncodeNeonBinOp(VTST, size, dst, src1, src2));
453862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
453962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
454062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid Assembler::vceq(QwNeonRegister dst, QwNeonRegister src1,
454162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                     QwNeonRegister src2) {
454262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(IsEnabled(NEON));
454362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Qd = vceq(Qn, Qm) SIMD floating point compare equal.
454462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8-844.
454562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  emit(EncodeNeonBinOp(VCEQF, dst, src1, src2));
454662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
454762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
454862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid Assembler::vceq(NeonSize size, QwNeonRegister dst, QwNeonRegister src1,
454962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                     QwNeonRegister src2) {
455062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(IsEnabled(NEON));
455162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Qd = vceq(Qn, Qm) SIMD integer compare equal.
455262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8-844.
455362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  emit(EncodeNeonBinOp(VCEQ, size, dst, src1, src2));
455462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
455562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
455662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid Assembler::vcge(QwNeonRegister dst, QwNeonRegister src1,
455762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                     QwNeonRegister src2) {
455862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(IsEnabled(NEON));
455962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Qd = vcge(Qn, Qm) SIMD floating point compare greater or equal.
456062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8-848.
456162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  emit(EncodeNeonBinOp(VCGEF, dst, src1, src2));
456262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
456362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
456462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid Assembler::vcge(NeonDataType dt, QwNeonRegister dst, QwNeonRegister src1,
456562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                     QwNeonRegister src2) {
456662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(IsEnabled(NEON));
456762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Qd = vcge(Qn, Qm) SIMD integer compare greater or equal.
456862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8-848.
456962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  emit(EncodeNeonBinOp(VCGE, dt, dst, src1, src2));
457062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
457162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
457262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid Assembler::vcgt(QwNeonRegister dst, QwNeonRegister src1,
457362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                     QwNeonRegister src2) {
457462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(IsEnabled(NEON));
457562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Qd = vcgt(Qn, Qm) SIMD floating point compare greater than.
457662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8-852.
457762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  emit(EncodeNeonBinOp(VCGTF, dst, src1, src2));
457862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
457962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
458062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid Assembler::vcgt(NeonDataType dt, QwNeonRegister dst, QwNeonRegister src1,
458162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                     QwNeonRegister src2) {
458262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(IsEnabled(NEON));
458362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Qd = vcgt(Qn, Qm) SIMD integer compare greater than.
458462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8-852.
458562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  emit(EncodeNeonBinOp(VCGT, dt, dst, src1, src2));
458662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
458762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
458862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid Assembler::vext(QwNeonRegister dst, const QwNeonRegister src1,
458962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                     const QwNeonRegister src2, int bytes) {
459062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(IsEnabled(NEON));
459162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Qd = vext(Qn, Qm) SIMD byte extract.
459262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8-890.
459362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int vd, d;
459462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  dst.split_code(&vd, &d);
459562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int vn, n;
459662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  src1.split_code(&vn, &n);
459762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int vm, m;
459862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  src2.split_code(&vm, &m);
459962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK_GT(16, bytes);
460062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  emit(0x1E5U * B23 | d * B22 | 0x3 * B20 | vn * B16 | vd * B12 | bytes * B8 |
460162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch       n * B7 | B6 | m * B5 | vm);
460262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
460362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
460462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid Assembler::vzip(NeonSize size, QwNeonRegister dst,
460562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                     const QwNeonRegister src) {
460662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(IsEnabled(NEON));
460762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Qd = vzip.<size>(Qn, Qm) SIMD zip (interleave).
460862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8-1102.
460962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int vd, d;
461062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  dst.split_code(&vd, &d);
461162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int vm, m;
461262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  src.split_code(&vm, &m);
461362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int sz = static_cast<int>(size);
461462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  emit(0x1E7U * B23 | d * B22 | 0x3 * B20 | sz * B18 | 2 * B16 | vd * B12 |
461562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch       0x3 * B7 | B6 | m * B5 | vm);
461662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
461762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
461862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochstatic Instr EncodeNeonVREV(NeonSize op_size, NeonSize size,
461962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                            const QwNeonRegister dst,
462062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                            const QwNeonRegister src) {
462162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Qd = vrev<op_size>.<size>(Qn, Qm) SIMD scalar reverse.
462262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8-1028.
462362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK_GT(op_size, static_cast<int>(size));
462462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int vd, d;
462562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  dst.split_code(&vd, &d);
462662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int vm, m;
462762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  src.split_code(&vm, &m);
462862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int sz = static_cast<int>(size);
462962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int op = static_cast<int>(Neon64) - static_cast<int>(op_size);
463062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return 0x1E7U * B23 | d * B22 | 0x3 * B20 | sz * B18 | vd * B12 | op * B7 |
463162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch         B6 | m * B5 | vm;
463262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
463362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
463462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid Assembler::vrev16(NeonSize size, const QwNeonRegister dst,
463562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                       const QwNeonRegister src) {
463662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(IsEnabled(NEON));
463762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  emit(EncodeNeonVREV(Neon16, size, dst, src));
463862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
463962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
464062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid Assembler::vrev32(NeonSize size, const QwNeonRegister dst,
464162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                       const QwNeonRegister src) {
464262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(IsEnabled(NEON));
464362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  emit(EncodeNeonVREV(Neon32, size, dst, src));
464462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
464562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
464662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid Assembler::vrev64(NeonSize size, const QwNeonRegister dst,
464762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                       const QwNeonRegister src) {
464862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(IsEnabled(NEON));
464962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  emit(EncodeNeonVREV(Neon64, size, dst, src));
465062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
465162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
465262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch// Encode NEON vtbl / vtbx instruction.
465362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochstatic Instr EncodeNeonVTB(const DwVfpRegister dst, const NeonListOperand& list,
465462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                           const DwVfpRegister index, bool vtbx) {
465562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Dd = vtbl(table, Dm) SIMD vector permute, zero at out of range indices.
465662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8-1094.
465762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Dd = vtbx(table, Dm) SIMD vector permute, skip out of range indices.
465862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Instruction details available in ARM DDI 0406C.b, A8-1094.
465962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int vd, d;
466062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  dst.split_code(&vd, &d);
466162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int vn, n;
466262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  list.base().split_code(&vn, &n);
466362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int vm, m;
466462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  index.split_code(&vm, &m);
466562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int op = vtbx ? 1 : 0;  // vtbl = 0, vtbx = 1.
466662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return 0x1E7U * B23 | d * B22 | 0x3 * B20 | vn * B16 | vd * B12 | 0x2 * B10 |
466762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch         list.length() * B8 | n * B7 | op * B6 | m * B5 | vm;
466862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
466962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
467062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid Assembler::vtbl(const DwVfpRegister dst, const NeonListOperand& list,
467162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                     const DwVfpRegister index) {
467262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(IsEnabled(NEON));
467362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  emit(EncodeNeonVTB(dst, list, index, false));
467462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
467562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
467662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid Assembler::vtbx(const DwVfpRegister dst, const NeonListOperand& list,
467762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                     const DwVfpRegister index) {
467862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(IsEnabled(NEON));
467962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  emit(EncodeNeonVTB(dst, list, index, true));
4680f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch}
46818defd9ff6930b4e24729971a61cf7469daf119beSteve Block
46823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Pseudo instructions.
46836ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid Assembler::nop(int type) {
4684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // ARMv6{K/T2} and v7 have an actual NOP instruction but it serializes
4685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // some of the CPU's pipeline and has to issue. Older ARM chips simply used
4686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // MOV Rx, Rx as NOP and it performs better even in newer CPUs.
4687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // We therefore use MOV Rx, Rx, even on newer CPUs, and use Rx to encode
4688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // a type.
4689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(0 <= type && type <= 14);  // mov pc, pc isn't a nop.
46906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  emit(al | 13*B21 | type*B12 | type);
46916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
46926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
46936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool Assembler::IsMovT(Instr instr) {
4695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  instr &= ~(((kNumberOfConditions - 1) << 28) |  // Mask off conditions
4696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             ((kNumRegisters-1)*B12) |            // mask out register
4697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             EncodeMovwImmediate(0xFFFF));        // mask out immediate value
4698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return instr == kMovtPattern;
4699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool Assembler::IsMovW(Instr instr) {
4703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  instr &= ~(((kNumberOfConditions - 1) << 28) |  // Mask off conditions
4704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             ((kNumRegisters-1)*B12) |            // mask out destination
4705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             EncodeMovwImmediate(0xFFFF));        // mask out immediate value
4706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return instr == kMovwPattern;
4707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochInstr Assembler::GetMovTPattern() { return kMovtPattern; }
4711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochInstr Assembler::GetMovWPattern() { return kMovwPattern; }
4714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochInstr Assembler::EncodeMovwImmediate(uint32_t immediate) {
4717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(immediate < 0x10000);
4718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return ((immediate & 0xf000) << 4) | (immediate & 0xfff);
4719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochInstr Assembler::PatchMovwImmediate(Instr instruction, uint32_t immediate) {
4723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  instruction &= ~EncodeMovwImmediate(0xffff);
4724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return instruction | EncodeMovwImmediate(immediate);
4725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint Assembler::DecodeShiftImm(Instr instr) {
4729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int rotate = Instruction::RotateValue(instr) * 2;
4730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int immed8 = Instruction::Immed8Value(instr);
4731014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return base::bits::RotateRight32(immed8, rotate);
4732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochInstr Assembler::PatchShiftImm(Instr instr, int immed) {
4736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  uint32_t rotate_imm = 0;
4737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  uint32_t immed_8 = 0;
4738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool immed_fits = fits_shifter(immed, &rotate_imm, &immed_8, NULL);
4739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(immed_fits);
4740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  USE(immed_fits);
4741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return (instr & ~kOff12Mask) | (rotate_imm << 8) | immed_8;
4742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
47458a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wangbool Assembler::IsNop(Instr instr, int type) {
4746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(0 <= type && type <= 14);  // mov pc, pc isn't a nop.
47471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Check for mov rx, rx where x = type.
47488a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  return instr == (al | 13*B21 | type*B12 | type);
47498a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang}
47508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
47518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
4752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool Assembler::IsMovImmed(Instr instr) {
4753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return (instr & kMovImmedMask) == kMovImmedPattern;
4754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool Assembler::IsOrrImmed(Instr instr) {
4758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return (instr & kOrrImmedMask) == kOrrImmedPattern;
4759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// static
4763d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockbool Assembler::ImmediateFitsAddrMode1Instruction(int32_t imm32) {
4764d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  uint32_t dummy1;
4765d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  uint32_t dummy2;
4766d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  return fits_shifter(imm32, &dummy1, &dummy2, NULL);
4767d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
4768d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4769d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool Assembler::ImmediateFitsAddrMode2Instruction(int32_t imm32) {
4771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return is_uint12(abs(imm32));
4772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
47753100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Debugging.
4776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::RecordConstPool(int size) {
4777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // We only need this for debugger support, to correctly compute offsets in the
4778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // code.
4779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RecordRelocInfo(RelocInfo::CONST_POOL, static_cast<intptr_t>(size));
4780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::GrowBuffer() {
4784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!own_buffer_) FATAL("external code buffer is too small");
4785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
47863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Compute new buffer size.
4787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CodeDesc desc;  // the new buffer
4788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (buffer_size_ < 1 * MB) {
4789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    desc.buffer_size = 2*buffer_size_;
4790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
4791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    desc.buffer_size = buffer_size_ + 1*MB;
4792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
4793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_GT(desc.buffer_size, 0);  // no overflow
4794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
47953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set up new buffer.
4796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  desc.buffer = NewArray<byte>(desc.buffer_size);
4797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  desc.instr_size = pc_offset();
4799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  desc.reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
4800014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  desc.origin = this;
4801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
48023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Copy the data.
4803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int pc_delta = desc.buffer - buffer_;
4804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int rc_delta = (desc.buffer + desc.buffer_size) - (buffer_ + buffer_size_);
4805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MemMove(desc.buffer, buffer_, desc.instr_size);
4806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MemMove(reloc_info_writer.pos() + rc_delta, reloc_info_writer.pos(),
4807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          desc.reloc_size);
4808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
48093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Switch buffers.
4810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DeleteArray(buffer_);
4811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  buffer_ = desc.buffer;
4812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  buffer_size_ = desc.buffer_size;
4813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  pc_ += pc_delta;
4814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta,
4815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                               reloc_info_writer.last_pc() + pc_delta);
4816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
48173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // None of our relocation types are pc relative pointing outside the code
4818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // buffer nor pc absolute pointing inside the code buffer, so there is no need
48193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // to relocate any emitted relocation entries.
4820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4823b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Assembler::db(uint8_t data) {
4824014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // db is used to write raw data. The constant pool should be emitted or
4825014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // blocked before using db.
482613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  DCHECK(is_const_pool_blocked() || pending_32_bit_constants_.empty());
482713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  DCHECK(is_const_pool_blocked() || pending_64_bit_constants_.empty());
4828b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CheckBuffer();
4829b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  *reinterpret_cast<uint8_t*>(pc_) = data;
4830b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  pc_ += sizeof(uint8_t);
4831b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4832b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4833b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4834b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Assembler::dd(uint32_t data) {
4835014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // dd is used to write raw data. The constant pool should be emitted or
4836014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // blocked before using dd.
483713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  DCHECK(is_const_pool_blocked() || pending_32_bit_constants_.empty());
483813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  DCHECK(is_const_pool_blocked() || pending_64_bit_constants_.empty());
4839b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CheckBuffer();
4840b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  *reinterpret_cast<uint32_t*>(pc_) = data;
4841b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  pc_ += sizeof(uint32_t);
4842b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4843b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4844b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4845014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::dq(uint64_t value) {
4846014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // dq is used to write raw data. The constant pool should be emitted or
4847014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // blocked before using dq.
484813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  DCHECK(is_const_pool_blocked() || pending_32_bit_constants_.empty());
484913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  DCHECK(is_const_pool_blocked() || pending_64_bit_constants_.empty());
4850014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CheckBuffer();
4851014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  *reinterpret_cast<uint64_t*>(pc_) = value;
4852014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  pc_ += sizeof(uint64_t);
4853014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
4854014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
4855014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
4856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::emit_code_stub_address(Code* stub) {
4857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckBuffer();
4858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  *reinterpret_cast<uint32_t*>(pc_) =
4859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      reinterpret_cast<uint32_t>(stub->instruction_start());
4860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  pc_ += sizeof(uint32_t);
4861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
4865014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (RelocInfo::IsNone(rmode) ||
4866014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // Don't record external references unless the heap will be serialized.
4867014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      (rmode == RelocInfo::EXTERNAL_REFERENCE && !serializer_enabled() &&
4868014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch       !emit_debug_code())) {
4869014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return;
4870014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
4871014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(buffer_space() >= kMaxRelocSize);  // too late to grow buffer here
4872014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (rmode == RelocInfo::CODE_TARGET_WITH_ID) {
4873014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    data = RecordedAstId().ToInt();
4874014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    ClearRecordedAstId();
4875014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
4876014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  RelocInfo rinfo(isolate(), pc_, rmode, data, NULL);
4877014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  reloc_info_writer.Write(&rinfo);
4878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4881014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochConstantPoolEntry::Access Assembler::ConstantPoolAddEntry(int position,
4882014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                                          RelocInfo::Mode rmode,
4883014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                                          intptr_t value) {
4884f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DCHECK(rmode != RelocInfo::COMMENT && rmode != RelocInfo::CONST_POOL &&
4885f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch         rmode != RelocInfo::NONE64);
4886014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool sharing_ok = RelocInfo::IsNone(rmode) ||
4887014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                    !(serializer_enabled() || rmode < RelocInfo::CELL);
4888014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (FLAG_enable_embedded_constant_pool) {
4889014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return constant_pool_builder_.AddEntry(position, value, sharing_ok);
4890014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
489113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    DCHECK(pending_32_bit_constants_.size() < kMaxNumPending32Constants);
489213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (pending_32_bit_constants_.empty()) {
4893014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      first_const_pool_32_use_ = position;
4894257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
4895014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    ConstantPoolEntry entry(position, value, sharing_ok);
489613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    pending_32_bit_constants_.push_back(entry);
4897014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
4898014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Make sure the constant pool is not emitted in place of the next
4899014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // instruction for which we just recorded relocation info.
4900014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    BlockConstPoolFor(1);
4901014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return ConstantPoolEntry::REGULAR;
4902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
4903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4906014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochConstantPoolEntry::Access Assembler::ConstantPoolAddEntry(int position,
4907014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                                          double value) {
4908014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (FLAG_enable_embedded_constant_pool) {
4909014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return constant_pool_builder_.AddEntry(position, value);
4910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
491113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    DCHECK(pending_64_bit_constants_.size() < kMaxNumPending64Constants);
491213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (pending_64_bit_constants_.empty()) {
4913014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      first_const_pool_64_use_ = position;
4914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
4915014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    ConstantPoolEntry entry(position, value);
491613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    pending_64_bit_constants_.push_back(entry);
4917014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
4918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Make sure the constant pool is not emitted in place of the next
4919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // instruction for which we just recorded relocation info.
4920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    BlockConstPoolFor(1);
4921014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return ConstantPoolEntry::REGULAR;
4922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
49263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid Assembler::BlockConstPoolFor(int instructions) {
4927014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (FLAG_enable_embedded_constant_pool) {
4928014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Should be a no-op if using an embedded constant pool.
492913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    DCHECK(pending_32_bit_constants_.empty());
493013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    DCHECK(pending_64_bit_constants_.empty());
4931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
4932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
49343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  int pc_limit = pc_offset() + instructions * kInstrSize;
49353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (no_const_pool_before_ < pc_limit) {
4936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Max pool start (if we need a jump and an alignment).
4937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG
4938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int start = pc_limit + kInstrSize + 2 * kPointerSize;
493913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    DCHECK(pending_32_bit_constants_.empty() ||
4940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           (start - first_const_pool_32_use_ +
494113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                pending_64_bit_constants_.size() * kDoubleSize <
4942014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            kMaxDistToIntPool));
494313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    DCHECK(pending_64_bit_constants_.empty() ||
4944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           (start - first_const_pool_64_use_ < kMaxDistToFPPool));
4945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
49463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    no_const_pool_before_ = pc_limit;
4947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
4948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
49493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (next_buffer_check_ < no_const_pool_before_) {
49503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    next_buffer_check_ = no_const_pool_before_;
49513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
49523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
4953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
49553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid Assembler::CheckConstPool(bool force_emit, bool require_jump) {
4956014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (FLAG_enable_embedded_constant_pool) {
4957014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Should be a no-op if using an embedded constant pool.
495813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    DCHECK(pending_32_bit_constants_.empty());
495913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    DCHECK(pending_64_bit_constants_.empty());
4960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
4961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
49633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Some short sequence of instruction mustn't be broken up by constant pool
49643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // emission, such sequences are protected by calls to BlockConstPoolFor and
49653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // BlockConstPoolScope.
49663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (is_const_pool_blocked()) {
49673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // Something is wrong if emission is forced and blocked at the same time.
4968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!force_emit);
4969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
4970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
4971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
49723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // There is nothing to do if there are no pending constant pool entries.
497313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (pending_32_bit_constants_.empty() && pending_64_bit_constants_.empty()) {
49743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Calculate the offset of the next check.
49753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    next_buffer_check_ = pc_offset() + kCheckPoolInterval;
49763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return;
49773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
49783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the code buffer is large enough before emitting the constant
49803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // pool (include the jump over the pool and the constant pool marker and
49813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // the gap to the relocation information).
49823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  int jump_instr = require_jump ? kInstrSize : 0;
4983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int size_up_to_marker = jump_instr + kInstrSize;
4984014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int estimated_size_after_marker =
498513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      pending_32_bit_constants_.size() * kPointerSize;
498613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  bool has_int_values = !pending_32_bit_constants_.empty();
498713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  bool has_fp_values = !pending_64_bit_constants_.empty();
4988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool require_64_bit_align = false;
4989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (has_fp_values) {
4990014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    require_64_bit_align =
4991014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        !IsAligned(reinterpret_cast<intptr_t>(pc_ + size_up_to_marker),
4992014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                   kDoubleAlignment);
4993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (require_64_bit_align) {
4994014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      estimated_size_after_marker += kInstrSize;
4995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
499613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    estimated_size_after_marker +=
499713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        pending_64_bit_constants_.size() * kDoubleSize;
4998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4999014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int estimated_size = size_up_to_marker + estimated_size_after_marker;
5000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // We emit a constant pool when:
5002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  * requested to do so by parameter force_emit (e.g. after each function).
5003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  * the distance from the first instruction accessing the constant pool to
5004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //    any of the constant pool entries will exceed its limit the next
5005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //    time the pool is checked. This is overly restrictive, but we don't emit
5006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //    constant pool entries in-order so it's conservatively correct.
5007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  * the instruction doesn't require a jump after itself to jump over the
5008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //    constant pool, and we're getting close to running out of range.
5009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!force_emit) {
5010014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(has_fp_values || has_int_values);
5011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bool need_emit = false;
5012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (has_fp_values) {
5013014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // The 64-bit constants are always emitted before the 32-bit constants, so
5014014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // we can ignore the effect of the 32-bit constants on estimated_size.
5015014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      int dist64 = pc_offset() + estimated_size -
501613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                   pending_32_bit_constants_.size() * kPointerSize -
5017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   first_const_pool_64_use_;
5018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if ((dist64 >= kMaxDistToFPPool - kCheckPoolInterval) ||
5019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          (!require_jump && (dist64 >= kMaxDistToFPPool / 2))) {
5020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        need_emit = true;
5021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
5022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
5023014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (has_int_values) {
5024014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      int dist32 = pc_offset() + estimated_size - first_const_pool_32_use_;
5025014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if ((dist32 >= kMaxDistToIntPool - kCheckPoolInterval) ||
5026014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          (!require_jump && (dist32 >= kMaxDistToIntPool / 2))) {
5027014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        need_emit = true;
5028014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
5029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
5030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!need_emit) return;
5031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5033014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Deduplicate constants.
5034014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int size_after_marker = estimated_size_after_marker;
5035c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  for (size_t i = 0; i < pending_64_bit_constants_.size(); i++) {
5036014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    ConstantPoolEntry& entry = pending_64_bit_constants_[i];
5037014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(!entry.is_merged());
5038c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    for (size_t j = 0; j < i; j++) {
5039014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (entry.value64() == pending_64_bit_constants_[j].value64()) {
5040014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        DCHECK(!pending_64_bit_constants_[j].is_merged());
5041014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        entry.set_merged_index(j);
5042014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        size_after_marker -= kDoubleSize;
5043014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
5044014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
5045014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
5046014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
5047014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
5048c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  for (size_t i = 0; i < pending_32_bit_constants_.size(); i++) {
5049014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    ConstantPoolEntry& entry = pending_32_bit_constants_[i];
5050014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(!entry.is_merged());
5051014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (!entry.sharing_ok()) continue;
5052c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    for (size_t j = 0; j < i; j++) {
5053014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (entry.value() == pending_32_bit_constants_[j].value()) {
5054014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        DCHECK(!pending_32_bit_constants_[j].is_merged());
5055014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        entry.set_merged_index(j);
5056014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        size_after_marker -= kPointerSize;
5057014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
5058014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
5059014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
5060014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
5061014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
5062014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int size = size_up_to_marker + size_after_marker;
5063014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
5064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int needed_space = size + kGap;
50653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  while (buffer_space() <= needed_space) GrowBuffer();
50663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
50673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  {
50683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Block recursive calls to CheckConstPool.
50693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    BlockConstPoolScope block_const_pool(this);
5070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    RecordComment("[ Constant Pool");
5071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    RecordConstPool(size);
50723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
5073014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Label size_check;
5074014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bind(&size_check);
5075014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
50763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Emit jump over constant pool if necessary.
50773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    Label after_pool;
50783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (require_jump) {
50793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      b(&after_pool);
5080a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
5081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Put down constant pool marker "Undefined instruction".
5083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // The data size helps disassembly know what to print.
5084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    emit(kConstantPoolMarker |
5085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         EncodeConstantPoolLength(size_after_marker / kPointerSize));
5086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (require_64_bit_align) {
5088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      emit(kConstantPoolMarker);
5089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
50903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
5091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Emit 64-bit constant pool entries first: their range is smaller than
5092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // 32-bit entries.
5093c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    for (size_t i = 0; i < pending_64_bit_constants_.size(); i++) {
5094014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      ConstantPoolEntry& entry = pending_64_bit_constants_[i];
50953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
5096014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Instr instr = instr_at(entry.position());
5097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Instruction to patch must be 'vldr rd, [pc, #offset]' with offset == 0.
5098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK((IsVldrDPcImmediateOffset(instr) &&
5099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              GetVldrDRegisterImmediateOffset(instr) == 0));
51003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
5101014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      int delta = pc_offset() - entry.position() - kPcLoadDelta;
5102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(is_uint10(delta));
5103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5104014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (entry.is_merged()) {
5105014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        ConstantPoolEntry& merged =
5106014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            pending_64_bit_constants_[entry.merged_index()];
5107014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        DCHECK(entry.value64() == merged.value64());
5108014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Instr merged_instr = instr_at(merged.position());
5109014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        DCHECK(IsVldrDPcImmediateOffset(merged_instr));
5110014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        delta = GetVldrDRegisterImmediateOffset(merged_instr);
5111014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        delta += merged.position() - entry.position();
5112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
5113014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      instr_at_put(entry.position(),
5114014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                   SetVldrDRegisterImmediateOffset(instr, delta));
5115014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (!entry.is_merged()) {
5116014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        DCHECK(IsAligned(reinterpret_cast<intptr_t>(pc_), kDoubleAlignment));
5117014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        dq(entry.value64());
5118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
51193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
5120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Emit 32-bit constant pool entries.
5122c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    for (size_t i = 0; i < pending_32_bit_constants_.size(); i++) {
5123014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      ConstantPoolEntry& entry = pending_32_bit_constants_[i];
5124014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Instr instr = instr_at(entry.position());
5125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // 64-bit loads shouldn't get here.
5127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(!IsVldrDPcImmediateOffset(instr));
5128014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK(!IsMovW(instr));
5129014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK(IsLdrPcImmediateOffset(instr) &&
5130014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch             GetLdrRegisterImmediateOffset(instr) == 0);
5131014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
5132014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      int delta = pc_offset() - entry.position() - kPcLoadDelta;
5133014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK(is_uint12(delta));
5134014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // 0 is the smallest delta:
5135014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      //   ldr rd, [pc, #0]
5136014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      //   constant pool marker
5137014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      //   data
5138014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
5139014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (entry.is_merged()) {
5140014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        DCHECK(entry.sharing_ok());
5141014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        ConstantPoolEntry& merged =
5142014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            pending_32_bit_constants_[entry.merged_index()];
5143014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        DCHECK(entry.value() == merged.value());
5144014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Instr merged_instr = instr_at(merged.position());
5145014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        DCHECK(IsLdrPcImmediateOffset(merged_instr));
5146014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        delta = GetLdrRegisterImmediateOffset(merged_instr);
5147014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        delta += merged.position() - entry.position();
5148014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
5149014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      instr_at_put(entry.position(),
5150014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                   SetLdrRegisterImmediateOffset(instr, delta));
5151014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (!entry.is_merged()) {
5152014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        emit(entry.value());
5153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
5154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
5155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
515613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    pending_32_bit_constants_.clear();
515713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    pending_64_bit_constants_.clear();
5158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    first_const_pool_32_use_ = -1;
5159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    first_const_pool_64_use_ = -1;
51603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
51613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    RecordComment("]");
51623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
5163014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK_EQ(size, SizeOfCodeGeneratedSince(&size_check));
5164014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
51653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (after_pool.is_linked()) {
51663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      bind(&after_pool);
51673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
5168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
5169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Since a constant pool was just emitted, move the check offset forward by
5171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the standard interval.
51723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  next_buffer_check_ = pc_offset() + kCheckPoolInterval;
5173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5176014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::PatchConstantPoolAccessInstruction(
5177014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    int pc_offset, int offset, ConstantPoolEntry::Access access,
5178014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    ConstantPoolEntry::Type type) {
5179014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(FLAG_enable_embedded_constant_pool);
5180014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Address pc = buffer_ + pc_offset;
5181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5182014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Patch vldr/ldr instruction with correct offset.
5183014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Instr instr = instr_at(pc);
5184014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (access == ConstantPoolEntry::OVERFLOWED) {
5185014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (CpuFeatures::IsSupported(ARMv7)) {
5186f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      CpuFeatureScope scope(this, ARMv7);
5187014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // Instructions to patch must be 'movw rd, [#0]' and 'movt rd, [#0].
5188014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Instr next_instr = instr_at(pc + kInstrSize);
5189014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK((IsMovW(instr) && Instruction::ImmedMovwMovtValue(instr) == 0));
5190014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK((IsMovT(next_instr) &&
5191014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              Instruction::ImmedMovwMovtValue(next_instr) == 0));
5192014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      instr_at_put(pc, PatchMovwImmediate(instr, offset & 0xffff));
5193014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      instr_at_put(pc + kInstrSize,
5194014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                   PatchMovwImmediate(next_instr, offset >> 16));
5195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
5196014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // Instructions to patch must be 'mov rd, [#0]' and 'orr rd, rd, [#0].
5197014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Instr instr_2 = instr_at(pc + kInstrSize);
5198014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Instr instr_3 = instr_at(pc + 2 * kInstrSize);
5199014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Instr instr_4 = instr_at(pc + 3 * kInstrSize);
5200014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK((IsMovImmed(instr) && Instruction::Immed8Value(instr) == 0));
5201014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK((IsOrrImmed(instr_2) && Instruction::Immed8Value(instr_2) == 0) &&
5202014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch             GetRn(instr_2).is(GetRd(instr_2)));
5203014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK((IsOrrImmed(instr_3) && Instruction::Immed8Value(instr_3) == 0) &&
5204014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch             GetRn(instr_3).is(GetRd(instr_3)));
5205014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK((IsOrrImmed(instr_4) && Instruction::Immed8Value(instr_4) == 0) &&
5206014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch             GetRn(instr_4).is(GetRd(instr_4)));
5207014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      instr_at_put(pc, PatchShiftImm(instr, (offset & kImm8Mask)));
5208014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      instr_at_put(pc + kInstrSize,
5209014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                   PatchShiftImm(instr_2, (offset & (kImm8Mask << 8))));
5210014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      instr_at_put(pc + 2 * kInstrSize,
5211014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                   PatchShiftImm(instr_3, (offset & (kImm8Mask << 16))));
5212014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      instr_at_put(pc + 3 * kInstrSize,
5213014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                   PatchShiftImm(instr_4, (offset & (kImm8Mask << 24))));
5214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
5215014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else if (type == ConstantPoolEntry::DOUBLE) {
5216014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Instruction to patch must be 'vldr rd, [pp, #0]'.
5217014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK((IsVldrDPpImmediateOffset(instr) &&
5218014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            GetVldrDRegisterImmediateOffset(instr) == 0));
5219014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(is_uint10(offset));
5220014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    instr_at_put(pc, SetVldrDRegisterImmediateOffset(instr, offset));
5221014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
5222014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Instruction to patch must be 'ldr rd, [pp, #0]'.
5223014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK((IsLdrPpImmediateOffset(instr) &&
5224014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            GetLdrRegisterImmediateOffset(instr) == 0));
5225014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(is_uint12(offset));
5226014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    instr_at_put(pc, SetLdrRegisterImmediateOffset(instr, offset));
5227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5231014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace internal
5232014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace v8
5233f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
5234f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif  // V8_TARGET_ARCH_ARM
5235