code_generator_arm.cc revision c6b4dd8980350aaf250f0185f73e9c42ec17cd57
164339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert/*
264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert * Copyright (C) 2014 The Android Open Source Project
3b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
4b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Licensed under the Apache License, Version 2.0 (the "License");
58de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert * you may not use this file except in compliance with the License.
6b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * You may obtain a copy of the License at
7b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
8b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *      http://www.apache.org/licenses/LICENSE-2.0
9b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
10b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Unless required by applicable law or agreed to in writing, software
11b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * distributed under the License is distributed on an "AS IS" BASIS,
12b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * See the License for the specific language governing permissions and
14b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * limitations under the License.
15b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
168de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert
17b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "code_generator_arm.h"
18b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
19b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "arch/arm/instruction_set_features_arm.h"
20c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru#include "entrypoints/quick/quick_entrypoints.h"
21c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru#include "gc/accounting/card_table.h"
221b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert#include "intrinsics.h"
23b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "intrinsics_arm.h"
24b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "mirror/array-inl.h"
25b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "mirror/art_method.h"
26b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "mirror/class.h"
27b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "thread.h"
28b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "utils/arm/assembler_arm.h"
29b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "utils/arm/managed_register_arm.h"
30b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "utils/assembler.h"
31b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "utils/stack_checks.h"
32b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
33b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querunamespace art {
34b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
35b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querunamespace arm {
36b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
37b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic bool ExpectedPairLayout(Location location) {
38b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // We expected this for both core and fpu register pairs.
39b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return ((location.low() & 1) == 0) && (location.low() + 1 == location.high());
40b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
41b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
42b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic constexpr int kCurrentMethodStackOffset = 0;
43b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
44b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// We unconditionally allocate R5 to ensure we can do long operations
45b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// with baseline.
46103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusstatic constexpr Register kCoreSavedRegisterForBaseline = R5;
47b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic constexpr Register kCoreCalleeSaves[] =
48b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    { R5, R6, R7, R8, R10, R11, PC };
49b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic constexpr SRegister kFpuCalleeSaves[] =
50b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    { S16, S17, S18, S19, S20, S21, S22, S23, S24, S25, S26, S27, S28, S29, S30, S31 };
51b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
52b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// D31 cannot be split into two S registers, and the register allocator only works on
53b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// S registers. Therefore there is no need to block it.
54b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic constexpr DRegister DTMP = D31;
55b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
56b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define __ reinterpret_cast<ArmAssembler*>(codegen->GetAssembler())->
57b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define QUICK_ENTRY_POINT(x) QUICK_ENTRYPOINT_OFFSET(kArmWordSize, x).Int32Value()
58b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
5959d709d503bab6e2b61931737e662dd293b40578ccorneliusclass NullCheckSlowPathARM : public SlowPathCodeARM {
60b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru public:
61b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  explicit NullCheckSlowPathARM(HNullCheck* instruction) : instruction_(instruction) {}
62b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
63b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
64b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    CodeGeneratorARM* arm_codegen = down_cast<CodeGeneratorARM*>(codegen);
65b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    __ Bind(GetEntryLabel());
6659d709d503bab6e2b61931737e662dd293b40578ccornelius    arm_codegen->InvokeRuntime(
67b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        QUICK_ENTRY_POINT(pThrowNullPointer), instruction_, instruction_->GetDexPc(), this);
68b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
69b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
70c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru private:
71b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  HNullCheck* const instruction_;
7259d709d503bab6e2b61931737e662dd293b40578ccornelius  DISALLOW_COPY_AND_ASSIGN(NullCheckSlowPathARM);
73b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
74b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
75b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruclass DivZeroCheckSlowPathARM : public SlowPathCodeARM {
76b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru public:
77b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  explicit DivZeroCheckSlowPathARM(HDivZeroCheck* instruction) : instruction_(instruction) {}
78b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
79b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
80b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    CodeGeneratorARM* arm_codegen = down_cast<CodeGeneratorARM*>(codegen);
81b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    __ Bind(GetEntryLabel());
82b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    arm_codegen->InvokeRuntime(
83b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        QUICK_ENTRY_POINT(pThrowDivZero), instruction_, instruction_->GetDexPc(), this);
84b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
85b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
86b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru private:
87b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  HDivZeroCheck* const instruction_;
88b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  DISALLOW_COPY_AND_ASSIGN(DivZeroCheckSlowPathARM);
89b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
90b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
9159d709d503bab6e2b61931737e662dd293b40578ccorneliusclass SuspendCheckSlowPathARM : public SlowPathCodeARM {
92b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru public:
9359d709d503bab6e2b61931737e662dd293b40578ccornelius  SuspendCheckSlowPathARM(HSuspendCheck* instruction, HBasicBlock* successor)
94b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      : instruction_(instruction), successor_(successor) {}
95b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
96b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
97b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    CodeGeneratorARM* arm_codegen = down_cast<CodeGeneratorARM*>(codegen);
98b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    __ Bind(GetEntryLabel());
99b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    SaveLiveRegisters(codegen, instruction_->GetLocations());
100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    arm_codegen->InvokeRuntime(
101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        QUICK_ENTRY_POINT(pTestSuspend), instruction_, instruction_->GetDexPc(), this);
102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    RestoreLiveRegisters(codegen, instruction_->GetLocations());
103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (successor_ == nullptr) {
104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      __ b(GetReturnLabel());
10559d709d503bab6e2b61931737e662dd293b40578ccornelius    } else {
106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      __ b(arm_codegen->GetLabelOf(successor_));
107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
10959d709d503bab6e2b61931737e662dd293b40578ccornelius
110b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  Label* GetReturnLabel() {
111b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    DCHECK(successor_ == nullptr);
11259d709d503bab6e2b61931737e662dd293b40578ccornelius    return &return_label_;
113b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
114b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
115b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru private:
116b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  HSuspendCheck* const instruction_;
117b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // If not null, the block to branch to after the suspend check.
118b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  HBasicBlock* const successor_;
119b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
120b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // If `successor_` is null, the label to branch to after the suspend check.
121b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  Label return_label_;
122b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
123b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  DISALLOW_COPY_AND_ASSIGN(SuspendCheckSlowPathARM);
124b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
125b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
126b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruclass BoundsCheckSlowPathARM : public SlowPathCodeARM {
127b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru public:
128b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  BoundsCheckSlowPathARM(HBoundsCheck* instruction,
129b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                         Location index_location,
130b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                         Location length_location)
131b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      : instruction_(instruction),
132b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        index_location_(index_location),
133b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        length_location_(length_location) {}
134b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
135b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
136b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    CodeGeneratorARM* arm_codegen = down_cast<CodeGeneratorARM*>(codegen);
137b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    __ Bind(GetEntryLabel());
138b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // We're moving two locations to locations that could overlap, so we need a parallel
139b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // move resolver.
140b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    InvokeRuntimeCallingConvention calling_convention;
141b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    codegen->EmitParallelMoves(
142b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        index_location_,
143b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        Location::RegisterLocation(calling_convention.GetRegisterAt(0)),
144b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        length_location_,
145b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        Location::RegisterLocation(calling_convention.GetRegisterAt(1)));
146b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    arm_codegen->InvokeRuntime(
147b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        QUICK_ENTRY_POINT(pThrowArrayBounds), instruction_, instruction_->GetDexPc(), this);
148b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
149b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
150b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru private:
151b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  HBoundsCheck* const instruction_;
152b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  const Location index_location_;
153b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  const Location length_location_;
154b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
155b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  DISALLOW_COPY_AND_ASSIGN(BoundsCheckSlowPathARM);
156b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
157b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
158b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruclass LoadClassSlowPathARM : public SlowPathCodeARM {
159b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru public:
160b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  LoadClassSlowPathARM(HLoadClass* cls,
161b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                       HInstruction* at,
162b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                       uint32_t dex_pc,
163b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                       bool do_clinit)
164b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      : cls_(cls), at_(at), dex_pc_(dex_pc), do_clinit_(do_clinit) {
165b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    DCHECK(at->IsLoadClass() || at->IsClinitCheck());
166b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
167b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
168b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    LocationSummary* locations = at_->GetLocations();
170b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    CodeGeneratorARM* arm_codegen = down_cast<CodeGeneratorARM*>(codegen);
172b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    __ Bind(GetEntryLabel());
173b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    SaveLiveRegisters(codegen, locations);
174b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
175b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    InvokeRuntimeCallingConvention calling_convention;
176b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    __ LoadImmediate(calling_convention.GetRegisterAt(0), cls_->GetTypeIndex());
177b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    arm_codegen->LoadCurrentMethod(calling_convention.GetRegisterAt(1));
178b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t entry_point_offset = do_clinit_
179b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ? QUICK_ENTRY_POINT(pInitializeStaticStorage)
180b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        : QUICK_ENTRY_POINT(pInitializeType);
181b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    arm_codegen->InvokeRuntime(entry_point_offset, at_, dex_pc_, this);
182b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
183b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Move the class to the desired location.
184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    Location out = locations->Out();
185b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (out.IsValid()) {
186b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      DCHECK(out.IsRegister() && !locations->GetLiveRegisters()->ContainsCoreRegister(out.reg()));
187f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius      arm_codegen->Move32(locations->Out(), Location::RegisterLocation(R0));
1881b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    }
189f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    RestoreLiveRegisters(codegen, locations);
190f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    __ b(GetExitLabel());
191f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius  }
192f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
193f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius private:
194f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius  // The class this slow path will load.
195f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius  HLoadClass* const cls_;
196f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
197f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius  // The instruction where this slow path is happening.
198f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius  // (Might be the load class or an initialization check).
199f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius  HInstruction* const at_;
200f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
201b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // The dex PC of `at_`.
202f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius  const uint32_t dex_pc_;
203f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
204b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // Whether to initialize the class.
205f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius  const bool do_clinit_;
206b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
207f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius  DISALLOW_COPY_AND_ASSIGN(LoadClassSlowPathARM);
208f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius};
209b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
210f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusclass LoadStringSlowPathARM : public SlowPathCodeARM {
211f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius public:
212f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius  explicit LoadStringSlowPathARM(HLoadString* instruction) : instruction_(instruction) {}
213f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
214b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
215f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    LocationSummary* locations = instruction_->GetLocations();
216b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    DCHECK(!locations->GetLiveRegisters()->ContainsCoreRegister(locations->Out().reg()));
217f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
218f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    CodeGeneratorARM* arm_codegen = down_cast<CodeGeneratorARM*>(codegen);
219f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    __ Bind(GetEntryLabel());
220f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    SaveLiveRegisters(codegen, locations);
221f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
222f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    InvokeRuntimeCallingConvention calling_convention;
22350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    arm_codegen->LoadCurrentMethod(calling_convention.GetRegisterAt(1));
224f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    __ LoadImmediate(calling_convention.GetRegisterAt(0), instruction_->GetStringIndex());
22550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    arm_codegen->InvokeRuntime(
226f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        QUICK_ENTRY_POINT(pResolveString), instruction_, instruction_->GetDexPc(), this);
227f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    arm_codegen->Move32(locations->Out(), Location::RegisterLocation(R0));
228f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
229f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    RestoreLiveRegisters(codegen, locations);
230f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    __ b(GetExitLabel());
231f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius  }
232b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
233b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru private:
234b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  HLoadString* const instruction_;
235b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
236b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  DISALLOW_COPY_AND_ASSIGN(LoadStringSlowPathARM);
237b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
238b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
239b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruclass TypeCheckSlowPathARM : public SlowPathCodeARM {
240b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru public:
241b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  TypeCheckSlowPathARM(HInstruction* instruction,
242b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                       Location class_to_check,
243b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                       Location object_class,
244b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                       uint32_t dex_pc)
245b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      : instruction_(instruction),
246b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        class_to_check_(class_to_check),
247b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        object_class_(object_class),
248b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        dex_pc_(dex_pc) {}
249b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
250b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
251b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    LocationSummary* locations = instruction_->GetLocations();
252b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    DCHECK(instruction_->IsCheckCast()
253b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru           || !locations->GetLiveRegisters()->ContainsCoreRegister(locations->Out().reg()));
254b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
255b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    CodeGeneratorARM* arm_codegen = down_cast<CodeGeneratorARM*>(codegen);
256b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    __ Bind(GetEntryLabel());
257b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    SaveLiveRegisters(codegen, locations);
258b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
259b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // We're moving two locations to locations that could overlap, so we need a parallel
260b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // move resolver.
261b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    InvokeRuntimeCallingConvention calling_convention;
262b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    codegen->EmitParallelMoves(
263b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        class_to_check_,
264b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        Location::RegisterLocation(calling_convention.GetRegisterAt(0)),
265b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        object_class_,
266b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        Location::RegisterLocation(calling_convention.GetRegisterAt(1)));
267b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
268b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (instruction_->IsInstanceOf()) {
269b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      arm_codegen->InvokeRuntime(
270b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          QUICK_ENTRY_POINT(pInstanceofNonTrivial), instruction_, dex_pc_, this);
271b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      arm_codegen->Move32(locations->Out(), Location::RegisterLocation(R0));
272b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
273b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      DCHECK(instruction_->IsCheckCast());
274b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      arm_codegen->InvokeRuntime(QUICK_ENTRY_POINT(pCheckCast), instruction_, dex_pc_, this);
275b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
276b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
277b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    RestoreLiveRegisters(codegen, locations);
278b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    __ b(GetExitLabel());
279b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
280b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
281b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru private:
282b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  HInstruction* const instruction_;
283b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  const Location class_to_check_;
284b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  const Location object_class_;
285b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  uint32_t dex_pc_;
286b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
287b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  DISALLOW_COPY_AND_ASSIGN(TypeCheckSlowPathARM);
288b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
289b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
290b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruclass DeoptimizationSlowPathARM : public SlowPathCodeARM {
291b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru public:
292b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  explicit DeoptimizationSlowPathARM(HInstruction* instruction)
293b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    : instruction_(instruction) {}
294b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
295b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
296b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    __ Bind(GetEntryLabel());
297b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    SaveLiveRegisters(codegen, instruction_->GetLocations());
298b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    DCHECK(instruction_->IsDeoptimize());
299b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    HDeoptimize* deoptimize = instruction_->AsDeoptimize();
300b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint32_t dex_pc = deoptimize->GetDexPc();
301b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    CodeGeneratorARM* arm_codegen = down_cast<CodeGeneratorARM*>(codegen);
302b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    arm_codegen->InvokeRuntime(QUICK_ENTRY_POINT(pDeoptimize), instruction_, dex_pc, this);
303b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
304b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
305b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru private:
306b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  HInstruction* const instruction_;
307b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  DISALLOW_COPY_AND_ASSIGN(DeoptimizationSlowPathARM);
308b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
309b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
310b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#undef __
311b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
312b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#undef __
313b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define __ reinterpret_cast<ArmAssembler*>(GetAssembler())->
314b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
315b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruinline Condition ARMCondition(IfCondition cond) {
316b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  switch (cond) {
317b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case kCondEQ: return EQ;
318b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case kCondNE: return NE;
319b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case kCondLT: return LT;
320b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case kCondLE: return LE;
321b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case kCondGT: return GT;
322b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case kCondGE: return GE;
323b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    default:
324b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      LOG(FATAL) << "Unknown if condition";
325b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
326b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return EQ;        // Unreachable.
327b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
328b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
329b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruinline Condition ARMOppositeCondition(IfCondition cond) {
330b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  switch (cond) {
331b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case kCondEQ: return NE;
332b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case kCondNE: return EQ;
333b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case kCondLT: return GE;
334b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case kCondLE: return GT;
335b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case kCondGT: return LE;
336b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case kCondGE: return LT;
337b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    default:
338b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      LOG(FATAL) << "Unknown if condition";
339b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
340b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return EQ;        // Unreachable.
341b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
342b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
343b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid CodeGeneratorARM::DumpCoreRegister(std::ostream& stream, int reg) const {
344b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  stream << ArmManagedRegister::FromCoreRegister(Register(reg));
345b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
346b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
347b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid CodeGeneratorARM::DumpFloatingPointRegister(std::ostream& stream, int reg) const {
348b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  stream << ArmManagedRegister::FromSRegister(SRegister(reg));
349b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
350b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
351b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querusize_t CodeGeneratorARM::SaveCoreRegister(size_t stack_index, uint32_t reg_id) {
352b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  __ StoreToOffset(kStoreWord, static_cast<Register>(reg_id), SP, stack_index);
353b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return kArmWordSize;
354b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
355b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
356b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querusize_t CodeGeneratorARM::RestoreCoreRegister(size_t stack_index, uint32_t reg_id) {
357b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  __ LoadFromOffset(kLoadWord, static_cast<Register>(reg_id), SP, stack_index);
358b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return kArmWordSize;
359b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
360b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
361b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querusize_t CodeGeneratorARM::SaveFloatingPointRegister(size_t stack_index, uint32_t reg_id) {
362b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  __ StoreSToOffset(static_cast<SRegister>(reg_id), SP, stack_index);
363b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return kArmWordSize;
364b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
365b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
366b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querusize_t CodeGeneratorARM::RestoreFloatingPointRegister(size_t stack_index, uint32_t reg_id) {
367b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  __ LoadSFromOffset(static_cast<SRegister>(reg_id), SP, stack_index);
368b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return kArmWordSize;
369b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
370b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
371b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruCodeGeneratorARM::CodeGeneratorARM(HGraph* graph,
372b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                   const ArmInstructionSetFeatures& isa_features,
373b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                   const CompilerOptions& compiler_options)
374b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    : CodeGenerator(graph,
375b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    kNumberOfCoreRegisters,
376b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    kNumberOfSRegisters,
377b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    kNumberOfRegisterPairs,
378b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    ComputeRegisterMask(reinterpret_cast<const int*>(kCoreCalleeSaves),
379b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                        arraysize(kCoreCalleeSaves)),
380b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    ComputeRegisterMask(reinterpret_cast<const int*>(kFpuCalleeSaves),
381b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                        arraysize(kFpuCalleeSaves)),
382b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    compiler_options),
383b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      block_labels_(graph->GetArena(), 0),
384b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      location_builder_(graph, this),
385b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      instruction_visitor_(graph, this),
386b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      move_resolver_(graph->GetArena(), this),
387b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      assembler_(true),
388b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      isa_features_(isa_features) {
389b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // Save the PC register to mimic Quick.
390b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  AddAllocatedRegister(Location::RegisterLocation(PC));
391b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
392b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
393b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruLocation CodeGeneratorARM::AllocateFreeRegister(Primitive::Type type) const {
394b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  switch (type) {
395b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimLong: {
396b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      size_t reg = FindFreeEntry(blocked_register_pairs_, kNumberOfRegisterPairs);
397b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      ArmManagedRegister pair =
398b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          ArmManagedRegister::FromRegisterPair(static_cast<RegisterPair>(reg));
399b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      DCHECK(!blocked_core_registers_[pair.AsRegisterPairLow()]);
400b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      DCHECK(!blocked_core_registers_[pair.AsRegisterPairHigh()]);
401b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
402b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      blocked_core_registers_[pair.AsRegisterPairLow()] = true;
403b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      blocked_core_registers_[pair.AsRegisterPairHigh()] = true;
404b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      UpdateBlockedPairRegisters();
405b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      return Location::RegisterPairLocation(pair.AsRegisterPairLow(), pair.AsRegisterPairHigh());
406b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
407b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
408b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimByte:
409b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimBoolean:
410b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimChar:
411b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimShort:
412b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimInt:
413b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimNot: {
414b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      int reg = FindFreeEntry(blocked_core_registers_, kNumberOfCoreRegisters);
415b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      // Block all register pairs that contain `reg`.
416b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      for (int i = 0; i < kNumberOfRegisterPairs; i++) {
417b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ArmManagedRegister current =
418b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            ArmManagedRegister::FromRegisterPair(static_cast<RegisterPair>(i));
419b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (current.AsRegisterPairLow() == reg || current.AsRegisterPairHigh() == reg) {
420b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          blocked_register_pairs_[i] = true;
421b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
422b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      }
423b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      return Location::RegisterLocation(reg);
424b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
425b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
426b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimFloat: {
427b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      int reg = FindFreeEntry(blocked_fpu_registers_, kNumberOfSRegisters);
428b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      return Location::FpuRegisterLocation(reg);
429b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
430b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
431b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimDouble: {
432b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      int reg = FindTwoFreeConsecutiveAlignedEntries(blocked_fpu_registers_, kNumberOfSRegisters);
433b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      DCHECK_EQ(reg % 2, 0);
434b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      return Location::FpuRegisterPairLocation(reg, reg + 1);
435b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
436b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
437b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimVoid:
438b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      LOG(FATAL) << "Unreachable type " << type;
439b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
440b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
441b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return Location();
442b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
443b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
444b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid CodeGeneratorARM::SetupBlockedRegisters(bool is_baseline) const {
445b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // Don't allocate the dalvik style register pair passing.
446b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  blocked_register_pairs_[R1_R2] = true;
447b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
448b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // Stack register, LR and PC are always reserved.
449b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  blocked_core_registers_[SP] = true;
450b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  blocked_core_registers_[LR] = true;
451b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  blocked_core_registers_[PC] = true;
452b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
453b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // Reserve thread register.
454b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  blocked_core_registers_[TR] = true;
455b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
456b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // Reserve temp register.
457b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  blocked_core_registers_[IP] = true;
458b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
459b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if (is_baseline) {
460b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (size_t i = 0; i < arraysize(kCoreCalleeSaves); ++i) {
461b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      blocked_core_registers_[kCoreCalleeSaves[i]] = true;
462b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
463b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
464b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    blocked_core_registers_[kCoreSavedRegisterForBaseline] = false;
465b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
466b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (size_t i = 0; i < arraysize(kFpuCalleeSaves); ++i) {
467b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      blocked_fpu_registers_[kFpuCalleeSaves[i]] = true;
468b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
469b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
470b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
471b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  UpdateBlockedPairRegisters();
472b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
473b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
474b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid CodeGeneratorARM::UpdateBlockedPairRegisters() const {
475b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  for (int i = 0; i < kNumberOfRegisterPairs; i++) {
476b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ArmManagedRegister current =
477b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ArmManagedRegister::FromRegisterPair(static_cast<RegisterPair>(i));
478b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (blocked_core_registers_[current.AsRegisterPairLow()]
479b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        || blocked_core_registers_[current.AsRegisterPairHigh()]) {
480b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      blocked_register_pairs_[i] = true;
481b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
48227f654740f2a26ad62a5c155af9199af9e69b889claireho  }
48327f654740f2a26ad62a5c155af9199af9e69b889claireho}
48427f654740f2a26ad62a5c155af9199af9e69b889claireho
48527f654740f2a26ad62a5c155af9199af9e69b889clairehoInstructionCodeGeneratorARM::InstructionCodeGeneratorARM(HGraph* graph, CodeGeneratorARM* codegen)
48627f654740f2a26ad62a5c155af9199af9e69b889claireho      : HGraphVisitor(graph),
48727f654740f2a26ad62a5c155af9199af9e69b889claireho        assembler_(codegen->GetAssembler()),
48827f654740f2a26ad62a5c155af9199af9e69b889claireho        codegen_(codegen) {}
489b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
49027f654740f2a26ad62a5c155af9199af9e69b889clairehostatic uint32_t LeastSignificantBit(uint32_t mask) {
49127f654740f2a26ad62a5c155af9199af9e69b889claireho  // ffs starts at 1.
49227f654740f2a26ad62a5c155af9199af9e69b889claireho  return ffs(mask) - 1;
49327f654740f2a26ad62a5c155af9199af9e69b889claireho}
49427f654740f2a26ad62a5c155af9199af9e69b889claireho
49527f654740f2a26ad62a5c155af9199af9e69b889clairehovoid CodeGeneratorARM::ComputeSpillMask() {
49627f654740f2a26ad62a5c155af9199af9e69b889claireho  core_spill_mask_ = allocated_registers_.GetCoreRegisters() & core_callee_save_mask_;
49727f654740f2a26ad62a5c155af9199af9e69b889claireho  // Save one extra register for baseline. Note that on thumb2, there is no easy
49827f654740f2a26ad62a5c155af9199af9e69b889claireho  // instruction to restore just the PC, so this actually helps both baseline
49927f654740f2a26ad62a5c155af9199af9e69b889claireho  // and non-baseline to save and restore at least two registers at entry and exit.
500b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  core_spill_mask_ |= (1 << kCoreSavedRegisterForBaseline);
501b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  DCHECK_NE(core_spill_mask_, 0u) << "At least the return address register must be saved";
502b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  fpu_spill_mask_ = allocated_registers_.GetFloatingPointRegisters() & fpu_callee_save_mask_;
503b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // We use vpush and vpop for saving and restoring floating point registers, which take
504b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // a SRegister and the number of registers to save/restore after that SRegister. We
505b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // therefore update the `fpu_spill_mask_` to also contain those registers not allocated,
506b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // but in the range.
507b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if (fpu_spill_mask_ != 0) {
508b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint32_t least_significant_bit = LeastSignificantBit(fpu_spill_mask_);
509b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint32_t most_significant_bit = MostSignificantBit(fpu_spill_mask_);
510b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (uint32_t i = least_significant_bit + 1 ; i < most_significant_bit; ++i) {
511b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      fpu_spill_mask_ |= (1 << i);
512b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
513b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
514b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
515b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
516b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic dwarf::Reg DWARFReg(Register reg) {
517b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return dwarf::Reg::ArmCore(static_cast<int>(reg));
518b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
519b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
520b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic dwarf::Reg DWARFReg(SRegister reg) {
521b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return dwarf::Reg::ArmFp(static_cast<int>(reg));
522b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
523b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
524b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid CodeGeneratorARM::GenerateFrameEntry() {
525b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  bool skip_overflow_check =
526b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      IsLeafMethod() && !FrameNeedsStackCheck(GetFrameSize(), InstructionSet::kArm);
527b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  DCHECK(GetCompilerOptions().GetImplicitStackOverflowChecks());
528b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  __ Bind(&frame_entry_label_);
529b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
530b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if (HasEmptyFrame()) {
531b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return;
532b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
533b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
534b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if (!skip_overflow_check) {
535b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    __ AddConstant(IP, SP, -static_cast<int32_t>(GetStackOverflowReservedBytes(kArm)));
536b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    __ LoadFromOffset(kLoadWord, IP, IP, 0);
537b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    RecordPcInfo(nullptr, 0);
538b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
539b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
540b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // PC is in the list of callee-save to mimic Quick, but we need to push
541b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // LR at entry instead.
542b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  uint32_t push_mask = (core_spill_mask_ & (~(1 << PC))) | 1 << LR;
543b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  __ PushList(push_mask);
544b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  __ cfi().AdjustCFAOffset(kArmWordSize * POPCOUNT(push_mask));
545b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  __ cfi().RelOffsetForMany(DWARFReg(Register(0)), 0, push_mask, kArmWordSize);
546b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if (fpu_spill_mask_ != 0) {
547b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    SRegister start_register = SRegister(LeastSignificantBit(fpu_spill_mask_));
548b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    __ vpushs(start_register, POPCOUNT(fpu_spill_mask_));
549b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    __ cfi().AdjustCFAOffset(kArmWordSize * POPCOUNT(fpu_spill_mask_));
550b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    __ cfi().RelOffsetForMany(DWARFReg(SRegister(0)), 0, fpu_spill_mask_, kArmWordSize);
551b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
552b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  int adjust = GetFrameSize() - FrameEntrySpillSize();
553b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  __ AddConstant(SP, -adjust);
554b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  __ cfi().AdjustCFAOffset(adjust);
555b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  __ StoreToOffset(kStoreWord, R0, SP, 0);
556b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
557b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
558b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid CodeGeneratorARM::GenerateFrameExit() {
559b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if (HasEmptyFrame()) {
560b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    __ bx(LR);
561b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return;
562b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
563b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  int adjust = GetFrameSize() - FrameEntrySpillSize();
564b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  __ AddConstant(SP, adjust);
565b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  __ cfi().AdjustCFAOffset(-adjust);
566b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if (fpu_spill_mask_ != 0) {
567b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    SRegister start_register = SRegister(LeastSignificantBit(fpu_spill_mask_));
568b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    __ vpops(start_register, POPCOUNT(fpu_spill_mask_));
569b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    __ cfi().AdjustCFAOffset(-kArmPointerSize * POPCOUNT(fpu_spill_mask_));
570b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    __ cfi().RestoreMany(DWARFReg(SRegister(0)), fpu_spill_mask_);
571b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
572b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  __ PopList(core_spill_mask_);
573b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
574b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
575b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid CodeGeneratorARM::Bind(HBasicBlock* block) {
576b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  __ Bind(GetLabelOf(block));
577b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
578b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
579b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruLocation CodeGeneratorARM::GetStackLocation(HLoadLocal* load) const {
580b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  switch (load->GetType()) {
581b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimLong:
582b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimDouble:
583b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      return Location::DoubleStackSlot(GetStackSlot(load->GetLocal()));
584b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
585b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimInt:
586b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimNot:
587b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimFloat:
588b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      return Location::StackSlot(GetStackSlot(load->GetLocal()));
589b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
590b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimBoolean:
591b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimByte:
592b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimChar:
593b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimShort:
594b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimVoid:
595b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      LOG(FATAL) << "Unexpected type " << load->GetType();
596b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      UNREACHABLE();
597b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
598b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
599b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  LOG(FATAL) << "Unreachable";
600b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  UNREACHABLE();
601b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
602b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
603b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruLocation InvokeDexCallingConventionVisitor::GetNextLocation(Primitive::Type type) {
604b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  switch (type) {
605b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimBoolean:
606b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimByte:
607b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimChar:
608b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimShort:
609b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimInt:
610b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimNot: {
611b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      uint32_t index = gp_index_++;
612b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      uint32_t stack_index = stack_index_++;
613b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      if (index < calling_convention.GetNumberOfRegisters()) {
614b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return Location::RegisterLocation(calling_convention.GetRegisterAt(index));
615b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      } else {
616b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return Location::StackSlot(calling_convention.GetStackOffsetOf(stack_index));
617b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      }
618b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
619b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
620b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimLong: {
621b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      uint32_t index = gp_index_;
622b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      uint32_t stack_index = stack_index_;
623b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      gp_index_ += 2;
624b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      stack_index_ += 2;
625b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      if (index + 1 < calling_convention.GetNumberOfRegisters()) {
626b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (calling_convention.GetRegisterAt(index) == R1) {
627b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          // Skip R1, and use R2_R3 instead.
628b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          gp_index_++;
629b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          index++;
630b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
631b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      }
632b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      if (index + 1 < calling_convention.GetNumberOfRegisters()) {
633b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        DCHECK_EQ(calling_convention.GetRegisterAt(index) + 1,
634b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  calling_convention.GetRegisterAt(index + 1));
635b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return Location::RegisterPairLocation(calling_convention.GetRegisterAt(index),
636b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                              calling_convention.GetRegisterAt(index + 1));
637b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      } else {
638b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return Location::DoubleStackSlot(calling_convention.GetStackOffsetOf(stack_index));
639b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      }
640b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
641b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
642b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimFloat: {
643b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      uint32_t stack_index = stack_index_++;
644b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      if (float_index_ % 2 == 0) {
645b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        float_index_ = std::max(double_index_, float_index_);
646b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      }
647b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      if (float_index_ < calling_convention.GetNumberOfFpuRegisters()) {
648b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return Location::FpuRegisterLocation(calling_convention.GetFpuRegisterAt(float_index_++));
649b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      } else {
650b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return Location::StackSlot(calling_convention.GetStackOffsetOf(stack_index));
651b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      }
652b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
653b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
654b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimDouble: {
655b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      double_index_ = std::max(double_index_, RoundUp(float_index_, 2));
656b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      uint32_t stack_index = stack_index_;
657b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      stack_index_ += 2;
658b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      if (double_index_ + 1 < calling_convention.GetNumberOfFpuRegisters()) {
659b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uint32_t index = double_index_;
660b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        double_index_ += 2;
661b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        Location result = Location::FpuRegisterPairLocation(
662b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          calling_convention.GetFpuRegisterAt(index),
663b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          calling_convention.GetFpuRegisterAt(index + 1));
664b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        DCHECK(ExpectedPairLayout(result));
665b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return result;
666b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      } else {
667b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return Location::DoubleStackSlot(calling_convention.GetStackOffsetOf(stack_index));
668b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      }
669b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
670b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
671b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimVoid:
672b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      LOG(FATAL) << "Unexpected parameter type " << type;
673b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      break;
674b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
675b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return Location();
676b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
677b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
678b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruLocation InvokeDexCallingConventionVisitor::GetReturnLocation(Primitive::Type type) {
679b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  switch (type) {
6806d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru    case Primitive::kPrimBoolean:
681b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimByte:
682b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimChar:
683b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimShort:
684b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimInt:
685b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimNot: {
686b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      return Location::RegisterLocation(R0);
687b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
688b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
689b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimFloat: {
690b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      return Location::FpuRegisterLocation(S0);
691b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
692b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
693b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimLong: {
694b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      return Location::RegisterPairLocation(R0, R1);
695b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
696b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
697b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimDouble: {
698b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      return Location::FpuRegisterPairLocation(S0, S1);
699b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
700b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
701b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimVoid:
702b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      return Location();
703b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
704b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  UNREACHABLE();
705b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
706b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
707b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid CodeGeneratorARM::Move32(Location destination, Location source) {
708b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if (source.Equals(destination)) {
709b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return;
710b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
711b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if (destination.IsRegister()) {
712b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (source.IsRegister()) {
713b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      __ Mov(destination.AsRegister<Register>(), source.AsRegister<Register>());
714b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else if (source.IsFpuRegister()) {
715b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      __ vmovrs(destination.AsRegister<Register>(), source.AsFpuRegister<SRegister>());
716b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
717b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      __ LoadFromOffset(kLoadWord, destination.AsRegister<Register>(), SP, source.GetStackIndex());
718b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
719b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else if (destination.IsFpuRegister()) {
720b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (source.IsRegister()) {
721b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      __ vmovsr(destination.AsFpuRegister<SRegister>(), source.AsRegister<Register>());
722b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else if (source.IsFpuRegister()) {
723b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      __ vmovs(destination.AsFpuRegister<SRegister>(), source.AsFpuRegister<SRegister>());
724b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
725b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      __ LoadSFromOffset(destination.AsFpuRegister<SRegister>(), SP, source.GetStackIndex());
726b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
727b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else {
728b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    DCHECK(destination.IsStackSlot()) << destination;
729b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (source.IsRegister()) {
730b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      __ StoreToOffset(kStoreWord, source.AsRegister<Register>(), SP, destination.GetStackIndex());
731b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else if (source.IsFpuRegister()) {
732b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      __ StoreSToOffset(source.AsFpuRegister<SRegister>(), SP, destination.GetStackIndex());
733b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
734b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      DCHECK(source.IsStackSlot()) << source;
735b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      __ LoadFromOffset(kLoadWord, IP, SP, source.GetStackIndex());
736b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      __ StoreToOffset(kStoreWord, IP, SP, destination.GetStackIndex());
737b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
738b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
739b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
740b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
741b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid CodeGeneratorARM::Move64(Location destination, Location source) {
742b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if (source.Equals(destination)) {
743b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return;
744b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
745b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if (destination.IsRegisterPair()) {
746b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (source.IsRegisterPair()) {
747b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      EmitParallelMoves(
748b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          Location::RegisterLocation(source.AsRegisterPairHigh<Register>()),
749b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          Location::RegisterLocation(destination.AsRegisterPairHigh<Register>()),
750b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          Location::RegisterLocation(source.AsRegisterPairLow<Register>()),
751b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          Location::RegisterLocation(destination.AsRegisterPairLow<Register>()));
752b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else if (source.IsFpuRegister()) {
753b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      UNIMPLEMENTED(FATAL);
754b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
755b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      DCHECK(source.IsDoubleStackSlot());
756b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      DCHECK(ExpectedPairLayout(destination));
757b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      __ LoadFromOffset(kLoadWordPair, destination.AsRegisterPairLow<Register>(),
758b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        SP, source.GetStackIndex());
759b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
760b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else if (destination.IsFpuRegisterPair()) {
761b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (source.IsDoubleStackSlot()) {
762b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      __ LoadDFromOffset(FromLowSToD(destination.AsFpuRegisterPairLow<SRegister>()),
763b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                         SP,
764b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                         source.GetStackIndex());
765b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
766b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      UNIMPLEMENTED(FATAL);
767b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
768b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else {
769b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    DCHECK(destination.IsDoubleStackSlot());
770b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (source.IsRegisterPair()) {
771b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      // No conflict possible, so just do the moves.
772b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      if (source.AsRegisterPairLow<Register>() == R1) {
773b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        DCHECK_EQ(source.AsRegisterPairHigh<Register>(), R2);
774b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        __ StoreToOffset(kStoreWord, R1, SP, destination.GetStackIndex());
775b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        __ StoreToOffset(kStoreWord, R2, SP, destination.GetHighStackIndex(kArmWordSize));
776b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      } else {
777b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        __ StoreToOffset(kStoreWordPair, source.AsRegisterPairLow<Register>(),
778b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                         SP, destination.GetStackIndex());
779b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      }
780b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else if (source.IsFpuRegisterPair()) {
781b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      __ StoreDToOffset(FromLowSToD(source.AsFpuRegisterPairLow<SRegister>()),
782b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        SP,
7836d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru                        destination.GetStackIndex());
784b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
7856d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru      DCHECK(source.IsDoubleStackSlot());
786b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      EmitParallelMoves(
7876d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru          Location::StackSlot(source.GetStackIndex()),
788b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          Location::StackSlot(destination.GetStackIndex()),
7896d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru          Location::StackSlot(source.GetHighStackIndex(kArmWordSize)),
790b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          Location::StackSlot(destination.GetHighStackIndex(kArmWordSize)));
7916d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru    }
792b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
793b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
794b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
795b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid CodeGeneratorARM::Move(HInstruction* instruction, Location location, HInstruction* move_for) {
796b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  LocationSummary* locations = instruction->GetLocations();
797b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if (locations != nullptr && locations->Out().Equals(location)) {
798b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return;
799b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
800b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
801b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if (locations != nullptr && locations->Out().IsConstant()) {
802b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    HConstant* const_to_move = locations->Out().GetConstant();
803b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (const_to_move->IsIntConstant() || const_to_move->IsNullConstant()) {
804b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      int32_t value = GetInt32ValueOf(const_to_move);
805b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      if (location.IsRegister()) {
806b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        __ LoadImmediate(location.AsRegister<Register>(), value);
807b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      } else {
808b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        DCHECK(location.IsStackSlot());
809b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        __ LoadImmediate(IP, value);
810b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        __ StoreToOffset(kStoreWord, IP, SP, location.GetStackIndex());
811b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      }
812b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
813b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      DCHECK(const_to_move->IsLongConstant()) << const_to_move->DebugName();
814b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      int64_t value = const_to_move->AsLongConstant()->GetValue();
815b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      if (location.IsRegisterPair()) {
816b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        __ LoadImmediate(location.AsRegisterPairLow<Register>(), Low32Bits(value));
817b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        __ LoadImmediate(location.AsRegisterPairHigh<Register>(), High32Bits(value));
818b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      } else {
819b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        DCHECK(location.IsDoubleStackSlot());
820b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        __ LoadImmediate(IP, Low32Bits(value));
821b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        __ StoreToOffset(kStoreWord, IP, SP, location.GetStackIndex());
822b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        __ LoadImmediate(IP, High32Bits(value));
823b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        __ StoreToOffset(kStoreWord, IP, SP, location.GetHighStackIndex(kArmWordSize));
824b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      }
825b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
826b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else if (instruction->IsLoadLocal()) {
827b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint32_t stack_slot = GetStackSlot(instruction->AsLoadLocal()->GetLocal());
828b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    switch (instruction->GetType()) {
829b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      case Primitive::kPrimBoolean:
830b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      case Primitive::kPrimByte:
831b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      case Primitive::kPrimChar:
832b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      case Primitive::kPrimShort:
833b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      case Primitive::kPrimInt:
834b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      case Primitive::kPrimNot:
835b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      case Primitive::kPrimFloat:
836b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        Move32(location, Location::StackSlot(stack_slot));
837b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        break;
838b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
839b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      case Primitive::kPrimLong:
840b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      case Primitive::kPrimDouble:
841b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        Move64(location, Location::DoubleStackSlot(stack_slot));
842b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        break;
843b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
844b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      default:
845b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        LOG(FATAL) << "Unexpected type " << instruction->GetType();
846b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
847b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else if (instruction->IsTemporary()) {
848b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    Location temp_location = GetTemporaryLocation(instruction->AsTemporary());
849b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (temp_location.IsStackSlot()) {
850b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      Move32(location, temp_location);
851b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
852b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      DCHECK(temp_location.IsDoubleStackSlot());
853b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      Move64(location, temp_location);
854b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
855b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else {
856b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    DCHECK((instruction->GetNext() == move_for) || instruction->GetNext()->IsTemporary());
857b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    switch (instruction->GetType()) {
858b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      case Primitive::kPrimBoolean:
859b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      case Primitive::kPrimByte:
860b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      case Primitive::kPrimChar:
861b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      case Primitive::kPrimShort:
862b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      case Primitive::kPrimNot:
863b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      case Primitive::kPrimInt:
864b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      case Primitive::kPrimFloat:
865b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        Move32(location, locations->Out());
866b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        break;
867c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert
868c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert      case Primitive::kPrimLong:
869b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      case Primitive::kPrimDouble:
870b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        Move64(location, locations->Out());
871b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        break;
872b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
873b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      default:
874b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        LOG(FATAL) << "Unexpected type " << instruction->GetType();
875b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
876b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
877b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
878b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
879b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid CodeGeneratorARM::InvokeRuntime(int32_t entry_point_offset,
880b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                     HInstruction* instruction,
881b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                     uint32_t dex_pc,
882b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                     SlowPathCode* slow_path) {
883b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  __ LoadFromOffset(kLoadWord, LR, TR, entry_point_offset);
884b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  __ blx(LR);
885b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  RecordPcInfo(instruction, dex_pc, slow_path);
886b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  DCHECK(instruction->IsSuspendCheck()
887b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      || instruction->IsBoundsCheck()
888b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      || instruction->IsNullCheck()
889b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      || instruction->IsDivZeroCheck()
890b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      || instruction->GetLocations()->CanCall()
891b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      || !IsLeafMethod());
892b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
893b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
894b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid LocationsBuilderARM::VisitGoto(HGoto* got) {
895b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  got->SetLocations(nullptr);
896b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
897b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
8988393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Corneliusvoid InstructionCodeGeneratorARM::VisitGoto(HGoto* got) {
8998393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius  HBasicBlock* successor = got->GetSuccessor();
900b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  DCHECK(!successor->IsExitBlock());
901b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
902b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  HBasicBlock* block = got->GetBlock();
903b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  HInstruction* previous = got->GetPrevious();
904b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
905b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  HLoopInformation* info = block->GetLoopInformation();
906b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if (info != nullptr && info->IsBackEdge(*block) && info->HasSuspendCheck()) {
907b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    codegen_->ClearSpillSlotsFromLoopPhisInStackMap(info->GetSuspendCheck());
908b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    GenerateSuspendCheck(info->GetSuspendCheck(), successor);
909b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return;
910b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
911b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
912b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if (block->IsEntryBlock() && (previous != nullptr) && previous->IsSuspendCheck()) {
913b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    GenerateSuspendCheck(previous->AsSuspendCheck(), nullptr);
914b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
915b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  if (!codegen_->GoesToNextBlock(got->GetBlock(), successor)) {
916b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    __ b(codegen_->GetLabelOf(successor));
917b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
918b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
919b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
920b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid LocationsBuilderARM::VisitExit(HExit* exit) {
921b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  exit->SetLocations(nullptr);
922b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
923b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
924b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid InstructionCodeGeneratorARM::VisitExit(HExit* exit) {
925b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  UNUSED(exit);
926b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
927b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
928b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid InstructionCodeGeneratorARM::GenerateTestAndBranch(HInstruction* instruction,
929b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                                        Label* true_target,
930b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                                        Label* false_target,
931b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                                        Label* always_true_target) {
932b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  HInstruction* cond = instruction->InputAt(0);
933b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  if (cond->IsIntConstant()) {
934b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Constant condition, statically compared against 1.
935b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t cond_value = cond->AsIntConstant()->GetValue();
936b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (cond_value == 1) {
937b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho      if (always_true_target != nullptr) {
938b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        __ b(always_true_target);
939b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho      }
940b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho      return;
941b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    } else {
942b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho      DCHECK_EQ(cond_value, 0);
943b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
944b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  } else {
945b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (!cond->IsCondition() || cond->AsCondition()->NeedsMaterialization()) {
946b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      // Condition has been materialized, compare the output to 0
947b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      DCHECK(instruction->GetLocations()->InAt(0).IsRegister());
948b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      __ cmp(instruction->GetLocations()->InAt(0).AsRegister<Register>(),
949b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             ShifterOperand(0));
950b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      __ b(true_target, NE);
951b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
952b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      // Condition has not been materialized, use its inputs as the
953b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      // comparison and its condition as the branch condition.
954b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      LocationSummary* locations = cond->GetLocations();
955b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      DCHECK(locations->InAt(0).IsRegister()) << locations->InAt(0);
956b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      Register left = locations->InAt(0).AsRegister<Register>();
957b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      if (locations->InAt(1).IsRegister()) {
9588393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        __ cmp(left, ShifterOperand(locations->InAt(1).AsRegister<Register>()));
959b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      } else {
960b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        DCHECK(locations->InAt(1).IsConstant());
961b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        HConstant* constant = locations->InAt(1).GetConstant();
962b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t value = CodeGenerator::GetInt32ValueOf(constant);
963b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ShifterOperand operand;
964b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (GetAssembler()->ShifterOperandCanHold(R0, left, CMP, value, &operand)) {
965b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          __ cmp(left, operand);
9666d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru        } else {
967b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          Register temp = IP;
968b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          __ LoadImmediate(temp, value);
969b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          __ cmp(left, ShifterOperand(temp));
970b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
971b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      }
972b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      __ b(true_target, ARMCondition(cond->AsCondition()->GetCondition()));
973b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
974b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
975b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if (false_target != nullptr) {
976b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    __ b(false_target);
977b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
978b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
979b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
980b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid LocationsBuilderARM::VisitIf(HIf* if_instr) {
981b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  LocationSummary* locations =
982b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      new (GetGraph()->GetArena()) LocationSummary(if_instr, LocationSummary::kNoCall);
983b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  HInstruction* cond = if_instr->InputAt(0);
984b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if (!cond->IsCondition() || cond->AsCondition()->NeedsMaterialization()) {
985b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    locations->SetInAt(0, Location::RequiresRegister());
986b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
987b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
988b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
989b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid InstructionCodeGeneratorARM::VisitIf(HIf* if_instr) {
990b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  Label* true_target = codegen_->GetLabelOf(if_instr->IfTrueSuccessor());
991b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  Label* false_target = codegen_->GetLabelOf(if_instr->IfFalseSuccessor());
992b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  Label* always_true_target = true_target;
993b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if (codegen_->GoesToNextBlock(if_instr->GetBlock(),
994b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                if_instr->IfTrueSuccessor())) {
995b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    always_true_target = nullptr;
996b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
997b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if (codegen_->GoesToNextBlock(if_instr->GetBlock(),
998b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                if_instr->IfFalseSuccessor())) {
999b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    false_target = nullptr;
1000b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1001b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  GenerateTestAndBranch(if_instr, true_target, false_target, always_true_target);
1002b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1003b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1004b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid LocationsBuilderARM::VisitDeoptimize(HDeoptimize* deoptimize) {
1005b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  LocationSummary* locations = new (GetGraph()->GetArena())
1006b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      LocationSummary(deoptimize, LocationSummary::kCallOnSlowPath);
1007b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  HInstruction* cond = deoptimize->InputAt(0);
1008b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  DCHECK(cond->IsCondition());
1009b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if (cond->AsCondition()->NeedsMaterialization()) {
1010b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    locations->SetInAt(0, Location::RequiresRegister());
1011b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1012b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1013b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1014b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid InstructionCodeGeneratorARM::VisitDeoptimize(HDeoptimize* deoptimize) {
1015b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  SlowPathCodeARM* slow_path = new (GetGraph()->GetArena())
1016b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      DeoptimizationSlowPathARM(deoptimize);
1017b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  codegen_->AddSlowPath(slow_path);
1018b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  Label* slow_path_entry = slow_path->GetEntryLabel();
1019b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  GenerateTestAndBranch(deoptimize, slow_path_entry, nullptr, slow_path_entry);
1020b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1021b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1022b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid LocationsBuilderARM::VisitCondition(HCondition* comp) {
1023b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  LocationSummary* locations =
1024b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      new (GetGraph()->GetArena()) LocationSummary(comp, LocationSummary::kNoCall);
1025b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  locations->SetInAt(0, Location::RequiresRegister());
1026b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  locations->SetInAt(1, Location::RegisterOrConstant(comp->InputAt(1)));
1027b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if (comp->NeedsMaterialization()) {
1028b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
1029b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1030b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1031b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1032b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid InstructionCodeGeneratorARM::VisitCondition(HCondition* comp) {
1033b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if (!comp->NeedsMaterialization()) return;
1034b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  LocationSummary* locations = comp->GetLocations();
1035b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  Register left = locations->InAt(0).AsRegister<Register>();
1036b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1037b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if (locations->InAt(1).IsRegister()) {
1038b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    __ cmp(left, ShifterOperand(locations->InAt(1).AsRegister<Register>()));
1039b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else {
1040b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    DCHECK(locations->InAt(1).IsConstant());
1041b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t value = CodeGenerator::GetInt32ValueOf(locations->InAt(1).GetConstant());
1042b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ShifterOperand operand;
1043b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (GetAssembler()->ShifterOperandCanHold(R0, left, CMP, value, &operand)) {
1044b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      __ cmp(left, operand);
1045b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
1046b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      Register temp = IP;
1047b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      __ LoadImmediate(temp, value);
1048b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      __ cmp(left, ShifterOperand(temp));
1049b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1050b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1051b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  __ it(ARMCondition(comp->GetCondition()), kItElse);
1052b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  __ mov(locations->Out().AsRegister<Register>(), ShifterOperand(1),
1053b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         ARMCondition(comp->GetCondition()));
1054b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  __ mov(locations->Out().AsRegister<Register>(), ShifterOperand(0),
1055b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         ARMOppositeCondition(comp->GetCondition()));
1056b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1057b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1058b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid LocationsBuilderARM::VisitEqual(HEqual* comp) {
1059b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  VisitCondition(comp);
1060b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1061b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1062b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid InstructionCodeGeneratorARM::VisitEqual(HEqual* comp) {
1063b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  VisitCondition(comp);
1064b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1065b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1066b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid LocationsBuilderARM::VisitNotEqual(HNotEqual* comp) {
1067b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  VisitCondition(comp);
1068b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1069b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1070b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid InstructionCodeGeneratorARM::VisitNotEqual(HNotEqual* comp) {
1071b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  VisitCondition(comp);
1072b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1073b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1074b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid LocationsBuilderARM::VisitLessThan(HLessThan* comp) {
1075b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  VisitCondition(comp);
1076b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1077b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1078b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid InstructionCodeGeneratorARM::VisitLessThan(HLessThan* comp) {
1079b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  VisitCondition(comp);
1080b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
10816d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru
1082b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid LocationsBuilderARM::VisitLessThanOrEqual(HLessThanOrEqual* comp) {
1083b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  VisitCondition(comp);
1084b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1085b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1086b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid InstructionCodeGeneratorARM::VisitLessThanOrEqual(HLessThanOrEqual* comp) {
1087b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  VisitCondition(comp);
1088b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1089b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1090b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid LocationsBuilderARM::VisitGreaterThan(HGreaterThan* comp) {
1091b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  VisitCondition(comp);
10926d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru}
1093b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1094b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid InstructionCodeGeneratorARM::VisitGreaterThan(HGreaterThan* comp) {
1095b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  VisitCondition(comp);
1096b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1097b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1098b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid LocationsBuilderARM::VisitGreaterThanOrEqual(HGreaterThanOrEqual* comp) {
1099b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  VisitCondition(comp);
1100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
11016d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru
1102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid InstructionCodeGeneratorARM::VisitGreaterThanOrEqual(HGreaterThanOrEqual* comp) {
1103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  VisitCondition(comp);
1104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid LocationsBuilderARM::VisitLocal(HLocal* local) {
1107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  local->SetLocations(nullptr);
1108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
11106d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queruvoid InstructionCodeGeneratorARM::VisitLocal(HLocal* local) {
1111b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  DCHECK_EQ(local->GetBlock(), GetGraph()->GetEntryBlock());
1112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1113b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1114b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid LocationsBuilderARM::VisitLoadLocal(HLoadLocal* load) {
11156d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru  load->SetLocations(nullptr);
1116b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1117b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1118b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid InstructionCodeGeneratorARM::VisitLoadLocal(HLoadLocal* load) {
1119b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // Nothing to do, this is driven by the code generator.
1120b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  UNUSED(load);
1121b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1122b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1123b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid LocationsBuilderARM::VisitStoreLocal(HStoreLocal* store) {
1124b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  LocationSummary* locations =
1125b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      new (GetGraph()->GetArena()) LocationSummary(store, LocationSummary::kNoCall);
1126b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  switch (store->InputAt(1)->GetType()) {
1127b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimBoolean:
1128b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimByte:
1129b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimChar:
1130b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimShort:
1131b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimInt:
1132b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimNot:
1133b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimFloat:
1134f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius      locations->SetInAt(1, Location::StackSlot(codegen_->GetStackSlot(store->GetLocal())));
1135b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      break;
1136b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1137b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimLong:
1138b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimDouble:
11396d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru      locations->SetInAt(1, Location::DoubleStackSlot(codegen_->GetStackSlot(store->GetLocal())));
1140b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      break;
1141b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1142f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    default:
1143f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius      LOG(FATAL) << "Unexpected local type " << store->InputAt(1)->GetType();
1144b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1145b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1146b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1147b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid InstructionCodeGeneratorARM::VisitStoreLocal(HStoreLocal* store) {
1148b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  UNUSED(store);
1149b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1150b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1151b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid LocationsBuilderARM::VisitIntConstant(HIntConstant* constant) {
1152b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  LocationSummary* locations =
1153b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      new (GetGraph()->GetArena()) LocationSummary(constant, LocationSummary::kNoCall);
1154b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  locations->SetOut(Location::ConstantLocation(constant));
1155b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1156b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1157b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid InstructionCodeGeneratorARM::VisitIntConstant(HIntConstant* constant) {
1158b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // Will be generated at use site.
1159b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  UNUSED(constant);
1160b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1161b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1162b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid LocationsBuilderARM::VisitNullConstant(HNullConstant* constant) {
1163b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  LocationSummary* locations =
1164b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      new (GetGraph()->GetArena()) LocationSummary(constant, LocationSummary::kNoCall);
1165b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  locations->SetOut(Location::ConstantLocation(constant));
1166b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1167b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1168b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid InstructionCodeGeneratorARM::VisitNullConstant(HNullConstant* constant) {
1169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // Will be generated at use site.
1170b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  UNUSED(constant);
1171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1172b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1173b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid LocationsBuilderARM::VisitLongConstant(HLongConstant* constant) {
1174b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  LocationSummary* locations =
1175b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      new (GetGraph()->GetArena()) LocationSummary(constant, LocationSummary::kNoCall);
1176b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  locations->SetOut(Location::ConstantLocation(constant));
1177b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1178b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1179b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid InstructionCodeGeneratorARM::VisitLongConstant(HLongConstant* constant) {
1180b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // Will be generated at use site.
1181b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  UNUSED(constant);
1182b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1183b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid LocationsBuilderARM::VisitFloatConstant(HFloatConstant* constant) {
1185b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  LocationSummary* locations =
1186b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      new (GetGraph()->GetArena()) LocationSummary(constant, LocationSummary::kNoCall);
1187b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  locations->SetOut(Location::ConstantLocation(constant));
1188b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1189b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1190b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid InstructionCodeGeneratorARM::VisitFloatConstant(HFloatConstant* constant) {
1191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // Will be generated at use site.
1192b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  UNUSED(constant);
1193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1194b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1195b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid LocationsBuilderARM::VisitDoubleConstant(HDoubleConstant* constant) {
1196b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  LocationSummary* locations =
1197b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      new (GetGraph()->GetArena()) LocationSummary(constant, LocationSummary::kNoCall);
1198b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  locations->SetOut(Location::ConstantLocation(constant));
1199b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1200b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1201b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid InstructionCodeGeneratorARM::VisitDoubleConstant(HDoubleConstant* constant) {
1202b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // Will be generated at use site.
1203b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  UNUSED(constant);
1204b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1205b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1206b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid LocationsBuilderARM::VisitReturnVoid(HReturnVoid* ret) {
1207b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  ret->SetLocations(nullptr);
1208b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1209b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1210b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid InstructionCodeGeneratorARM::VisitReturnVoid(HReturnVoid* ret) {
1211b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  UNUSED(ret);
1212b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  __ cfi().RememberState();
1213b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  codegen_->GenerateFrameExit();
1214b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  __ cfi().RestoreState();
1215b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  __ cfi().DefCFAOffset(codegen_->GetFrameSize());
1216b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1217b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1218b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid LocationsBuilderARM::VisitReturn(HReturn* ret) {
1219b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  LocationSummary* locations =
1220b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      new (GetGraph()->GetArena()) LocationSummary(ret, LocationSummary::kNoCall);
1221b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  locations->SetInAt(0, parameter_visitor_.GetReturnLocation(ret->InputAt(0)->GetType()));
1222b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1223b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1224b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid InstructionCodeGeneratorARM::VisitReturn(HReturn* ret) {
1225b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  UNUSED(ret);
1226b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  __ cfi().RememberState();
1227b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  codegen_->GenerateFrameExit();
1228b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  __ cfi().RestoreState();
1229b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  __ cfi().DefCFAOffset(codegen_->GetFrameSize());
1230b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1231b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1232b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid LocationsBuilderARM::VisitInvokeStaticOrDirect(HInvokeStaticOrDirect* invoke) {
1233b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  IntrinsicLocationsBuilderARM intrinsic(GetGraph()->GetArena(),
12346d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru                                         codegen_->GetInstructionSetFeatures());
1235b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if (intrinsic.TryDispatch(invoke)) {
1236b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return;
1237b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1238b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
12396d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru  HandleInvoke(invoke);
1240b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1241b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1242b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid CodeGeneratorARM::LoadCurrentMethod(Register reg) {
1243b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  DCHECK(RequiresCurrentMethod());
12446d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru  __ LoadFromOffset(kLoadWord, reg, SP, kCurrentMethodStackOffset);
1245b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1246b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1247b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic bool TryGenerateIntrinsicCode(HInvoke* invoke, CodeGeneratorARM* codegen) {
1248b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if (invoke->GetLocations()->Intrinsified()) {
12496d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru    IntrinsicCodeGeneratorARM intrinsic(codegen);
1250b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    intrinsic.Dispatch(invoke);
1251b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return true;
1252b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1253b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return false;
12546d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru}
1255b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1256b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid InstructionCodeGeneratorARM::VisitInvokeStaticOrDirect(HInvokeStaticOrDirect* invoke) {
1257b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if (TryGenerateIntrinsicCode(invoke, codegen_)) {
1258b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return;
1259b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1260b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1261b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  Register temp = invoke->GetLocations()->GetTemp(0).AsRegister<Register>();
1262b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1263b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  codegen_->GenerateStaticOrDirectCall(invoke, temp);
1264b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  codegen_->RecordPcInfo(invoke, invoke->GetDexPc());
1265b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1266b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1267b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid LocationsBuilderARM::HandleInvoke(HInvoke* invoke) {
1268b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  LocationSummary* locations =
1269b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      new (GetGraph()->GetArena()) LocationSummary(invoke, LocationSummary::kCall);
1270b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  locations->AddTemp(Location::RegisterLocation(R0));
1271b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1272b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  InvokeDexCallingConventionVisitor calling_convention_visitor;
1273b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  for (size_t i = 0; i < invoke->InputCount(); i++) {
1274b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    HInstruction* input = invoke->InputAt(i);
1275b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    locations->SetInAt(i, calling_convention_visitor.GetNextLocation(input->GetType()));
1276b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1277b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1278b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  locations->SetOut(calling_convention_visitor.GetReturnLocation(invoke->GetType()));
1279b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1280b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1281b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid LocationsBuilderARM::VisitInvokeVirtual(HInvokeVirtual* invoke) {
1282b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  IntrinsicLocationsBuilderARM intrinsic(GetGraph()->GetArena(),
1283b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                         codegen_->GetInstructionSetFeatures());
1284b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if (intrinsic.TryDispatch(invoke)) {
1285b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return;
1286b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1287b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1288b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  HandleInvoke(invoke);
1289b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1290b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1291b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid InstructionCodeGeneratorARM::VisitInvokeVirtual(HInvokeVirtual* invoke) {
1292b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if (TryGenerateIntrinsicCode(invoke, codegen_)) {
1293b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return;
1294b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1295b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1296b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  Register temp = invoke->GetLocations()->GetTemp(0).AsRegister<Register>();
1297b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  uint32_t method_offset = mirror::Class::EmbeddedVTableOffset().Uint32Value() +
1298b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          invoke->GetVTableIndex() * sizeof(mirror::Class::VTableEntry);
1299b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  LocationSummary* locations = invoke->GetLocations();
1300b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  Location receiver = locations->InAt(0);
1301b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  uint32_t class_offset = mirror::Object::ClassOffset().Int32Value();
1302b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // temp = object->GetClass();
1303b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if (receiver.IsStackSlot()) {
1304b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    __ LoadFromOffset(kLoadWord, temp, SP, receiver.GetStackIndex());
1305b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    __ LoadFromOffset(kLoadWord, temp, temp, class_offset);
1306b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else {
1307b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    __ LoadFromOffset(kLoadWord, temp, receiver.AsRegister<Register>(), class_offset);
1308b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1309b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  codegen_->MaybeRecordImplicitNullCheck(invoke);
1310b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // temp = temp->GetMethodAt(method_offset);
1311b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  uint32_t entry_point = mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset(
1312b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      kArmWordSize).Int32Value();
1313b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  __ LoadFromOffset(kLoadWord, temp, temp, method_offset);
1314b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // LR = temp->GetEntryPoint();
1315b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  __ LoadFromOffset(kLoadWord, LR, temp, entry_point);
1316b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // LR();
1317b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  __ blx(LR);
1318b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  DCHECK(!codegen_->IsLeafMethod());
1319b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  codegen_->RecordPcInfo(invoke, invoke->GetDexPc());
1320b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1321b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1322b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid LocationsBuilderARM::VisitInvokeInterface(HInvokeInterface* invoke) {
1323b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  HandleInvoke(invoke);
1324b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // Add the hidden argument.
1325b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  invoke->GetLocations()->AddTemp(Location::RegisterLocation(R12));
1326b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1327b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1328b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid InstructionCodeGeneratorARM::VisitInvokeInterface(HInvokeInterface* invoke) {
132950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho  // TODO: b/18116999, our IMTs can miss an IncompatibleClassChangeError.
1330b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  Register temp = invoke->GetLocations()->GetTemp(0).AsRegister<Register>();
1331b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  uint32_t method_offset = mirror::Class::EmbeddedImTableOffset().Uint32Value() +
1332b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          (invoke->GetImtIndex() % mirror::Class::kImtSize) * sizeof(mirror::Class::ImTableEntry);
1333b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  LocationSummary* locations = invoke->GetLocations();
1334b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  Location receiver = locations->InAt(0);
1335b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  uint32_t class_offset = mirror::Object::ClassOffset().Int32Value();
1336b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1337b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // Set the hidden argument.
1338b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  __ LoadImmediate(invoke->GetLocations()->GetTemp(1).AsRegister<Register>(),
1339b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                   invoke->GetDexMethodIndex());
134027f654740f2a26ad62a5c155af9199af9e69b889claireho
134127f654740f2a26ad62a5c155af9199af9e69b889claireho  // temp = object->GetClass();
134227f654740f2a26ad62a5c155af9199af9e69b889claireho  if (receiver.IsStackSlot()) {
134327f654740f2a26ad62a5c155af9199af9e69b889claireho    __ LoadFromOffset(kLoadWord, temp, SP, receiver.GetStackIndex());
134427f654740f2a26ad62a5c155af9199af9e69b889claireho    __ LoadFromOffset(kLoadWord, temp, temp, class_offset);
134527f654740f2a26ad62a5c155af9199af9e69b889claireho  } else {
134627f654740f2a26ad62a5c155af9199af9e69b889claireho    __ LoadFromOffset(kLoadWord, temp, receiver.AsRegister<Register>(), class_offset);
1347b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1348b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  codegen_->MaybeRecordImplicitNullCheck(invoke);
1349b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // temp = temp->GetImtEntryAt(method_offset);
1350b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  uint32_t entry_point = mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset(
1351b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      kArmWordSize).Int32Value();
1352b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  __ LoadFromOffset(kLoadWord, temp, temp, method_offset);
1353b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // LR = temp->GetEntryPoint();
1354b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  __ LoadFromOffset(kLoadWord, LR, temp, entry_point);
1355b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // LR();
1356b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  __ blx(LR);
1357b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  DCHECK(!codegen_->IsLeafMethod());
1358b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  codegen_->RecordPcInfo(invoke, invoke->GetDexPc());
1359b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1360b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1361b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid LocationsBuilderARM::VisitNeg(HNeg* neg) {
1362b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  LocationSummary* locations =
1363b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      new (GetGraph()->GetArena()) LocationSummary(neg, LocationSummary::kNoCall);
1364b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  switch (neg->GetResultType()) {
1365b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimInt: {
1366b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      locations->SetInAt(0, Location::RequiresRegister());
1367b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
1368b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      break;
1369b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1370b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimLong: {
1371b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      locations->SetInAt(0, Location::RequiresRegister());
1372b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      locations->SetOut(Location::RequiresRegister(), Location::kOutputOverlap);
1373b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      break;
1374b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1375b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1376b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimFloat:
1377b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimDouble:
1378b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      locations->SetInAt(0, Location::RequiresFpuRegister());
13796d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru      locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
1380b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      break;
1381b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1382b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    default:
1383b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      LOG(FATAL) << "Unexpected neg type " << neg->GetResultType();
1384b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1385b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1386b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1387b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid InstructionCodeGeneratorARM::VisitNeg(HNeg* neg) {
1388b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  LocationSummary* locations = neg->GetLocations();
1389b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  Location out = locations->Out();
1390b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  Location in = locations->InAt(0);
1391b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  switch (neg->GetResultType()) {
1392b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimInt:
1393b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      DCHECK(in.IsRegister());
1394b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      __ rsb(out.AsRegister<Register>(), in.AsRegister<Register>(), ShifterOperand(0));
1395b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      break;
1396b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1397b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimLong:
13988393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius      DCHECK(in.IsRegisterPair());
1399b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      // out.lo = 0 - in.lo (and update the carry/borrow (C) flag)
1400b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      __ rsbs(out.AsRegisterPairLow<Register>(),
1401b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              in.AsRegisterPairLow<Register>(),
1402b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              ShifterOperand(0));
1403b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      // We cannot emit an RSC (Reverse Subtract with Carry)
1404b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      // instruction here, as it does not exist in the Thumb-2
1405b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      // instruction set.  We use the following approach
1406b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      // using SBC and SUB instead.
1407b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      //
1408b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      // out.hi = -C
1409b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      __ sbc(out.AsRegisterPairHigh<Register>(),
1410b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             out.AsRegisterPairHigh<Register>(),
1411b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             ShifterOperand(out.AsRegisterPairHigh<Register>()));
1412b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      // out.hi = out.hi - in.hi
1413b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      __ sub(out.AsRegisterPairHigh<Register>(),
1414b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             out.AsRegisterPairHigh<Register>(),
1415b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             ShifterOperand(in.AsRegisterPairHigh<Register>()));
1416b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      break;
1417b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1418b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimFloat:
14198393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius      DCHECK(in.IsFpuRegister());
1420b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      __ vnegs(out.AsFpuRegister<SRegister>(), in.AsFpuRegister<SRegister>());
1421b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      break;
1422b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1423b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimDouble:
1424b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      DCHECK(in.IsFpuRegisterPair());
1425b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      __ vnegd(FromLowSToD(out.AsFpuRegisterPairLow<SRegister>()),
1426b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru               FromLowSToD(in.AsFpuRegisterPairLow<SRegister>()));
1427b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      break;
1428b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1429b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    default:
1430b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      LOG(FATAL) << "Unexpected neg type " << neg->GetResultType();
1431b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1432b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1433b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1434b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid LocationsBuilderARM::VisitTypeConversion(HTypeConversion* conversion) {
1435b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  Primitive::Type result_type = conversion->GetResultType();
1436b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  Primitive::Type input_type = conversion->GetInputType();
1437b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  DCHECK_NE(result_type, input_type);
1438b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1439b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // The float-to-long and double-to-long type conversions rely on a
1440b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // call to the runtime.
1441b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  LocationSummary::CallKind call_kind =
1442b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      ((input_type == Primitive::kPrimFloat || input_type == Primitive::kPrimDouble)
1443b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru       && result_type == Primitive::kPrimLong)
1444b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      ? LocationSummary::kCall
1445b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      : LocationSummary::kNoCall;
1446b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  LocationSummary* locations =
1447b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      new (GetGraph()->GetArena()) LocationSummary(conversion, call_kind);
1448b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1449b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // The Java language does not allow treating boolean as an integral type but
1450b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // our bit representation makes it safe.
1451b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1452b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  switch (result_type) {
1453b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimByte:
1454b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      switch (input_type) {
1455b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case Primitive::kPrimBoolean:
1456b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          // Boolean input is a result of code transformations.
1457b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case Primitive::kPrimShort:
1458b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case Primitive::kPrimInt:
1459b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case Primitive::kPrimChar:
1460b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          // Processing a Dex `int-to-byte' instruction.
1461b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          locations->SetInAt(0, Location::RequiresRegister());
1462b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
1463b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          break;
14646d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru
1465b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        default:
1466b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          LOG(FATAL) << "Unexpected type conversion from " << input_type
14676d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru                     << " to " << result_type;
1468b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      }
1469b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      break;
1470b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1471b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimShort:
1472b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      switch (input_type) {
1473b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case Primitive::kPrimBoolean:
1474b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          // Boolean input is a result of code transformations.
1475b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case Primitive::kPrimByte:
1476b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case Primitive::kPrimInt:
1477b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case Primitive::kPrimChar:
1478b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          // Processing a Dex `int-to-short' instruction.
1479b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          locations->SetInAt(0, Location::RequiresRegister());
1480b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
1481b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          break;
1482b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1483b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        default:
1484b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          LOG(FATAL) << "Unexpected type conversion from " << input_type
1485b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                     << " to " << result_type;
1486b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      }
1487b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      break;
1488b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1489b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimInt:
1490b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      switch (input_type) {
1491b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case Primitive::kPrimLong:
1492b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          // Processing a Dex `long-to-int' instruction.
14936d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru          locations->SetInAt(0, Location::Any());
14946d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru          locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
14956d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru          break;
1496b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1497b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case Primitive::kPrimFloat:
1498b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          // Processing a Dex `float-to-int' instruction.
1499b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          locations->SetInAt(0, Location::RequiresFpuRegister());
1500b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          locations->SetOut(Location::RequiresRegister());
1501b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          locations->AddTemp(Location::RequiresFpuRegister());
1502b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          break;
1503b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1504b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case Primitive::kPrimDouble:
1505b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          // Processing a Dex `double-to-int' instruction.
1506b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          locations->SetInAt(0, Location::RequiresFpuRegister());
1507b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          locations->SetOut(Location::RequiresRegister());
1508b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          locations->AddTemp(Location::RequiresFpuRegister());
1509b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          break;
1510b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1511b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        default:
1512b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          LOG(FATAL) << "Unexpected type conversion from " << input_type
1513b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                     << " to " << result_type;
1514b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      }
1515b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      break;
1516b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1517b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimLong:
1518b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      switch (input_type) {
1519b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case Primitive::kPrimBoolean:
1520b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          // Boolean input is a result of code transformations.
1521b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case Primitive::kPrimByte:
1522b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case Primitive::kPrimShort:
1523b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case Primitive::kPrimInt:
1524b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case Primitive::kPrimChar:
1525b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          // Processing a Dex `int-to-long' instruction.
1526b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          locations->SetInAt(0, Location::RequiresRegister());
1527b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
1528b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          break;
1529b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1530b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case Primitive::kPrimFloat: {
1531b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          // Processing a Dex `float-to-long' instruction.
1532b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          InvokeRuntimeCallingConvention calling_convention;
1533b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          locations->SetInAt(0, Location::FpuRegisterLocation(
1534b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              calling_convention.GetFpuRegisterAt(0)));
1535b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          locations->SetOut(Location::RegisterPairLocation(R0, R1));
1536b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          break;
1537b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1538b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1539b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case Primitive::kPrimDouble: {
1540b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          // Processing a Dex `double-to-long' instruction.
1541b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          InvokeRuntimeCallingConvention calling_convention;
1542b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          locations->SetInAt(0, Location::FpuRegisterPairLocation(
1543b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              calling_convention.GetFpuRegisterAt(0),
1544b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              calling_convention.GetFpuRegisterAt(1)));
1545b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          locations->SetOut(Location::RegisterPairLocation(R0, R1));
1546b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          break;
1547b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1548b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1549b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        default:
1550b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          LOG(FATAL) << "Unexpected type conversion from " << input_type
15516d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru                     << " to " << result_type;
1552b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      }
1553b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      break;
1554b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
155564339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    case Primitive::kPrimChar:
1556b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      switch (input_type) {
1557b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case Primitive::kPrimBoolean:
1558b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          // Boolean input is a result of code transformations.
1559b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case Primitive::kPrimByte:
1560b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case Primitive::kPrimShort:
1561b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case Primitive::kPrimInt:
1562b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          // Processing a Dex `int-to-char' instruction.
1563b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          locations->SetInAt(0, Location::RequiresRegister());
1564b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
1565b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          break;
1566b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1567b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        default:
1568b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          LOG(FATAL) << "Unexpected type conversion from " << input_type
1569b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                     << " to " << result_type;
1570b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      }
1571b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      break;
1572b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1573b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimFloat:
1574b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      switch (input_type) {
1575b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case Primitive::kPrimBoolean:
1576b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          // Boolean input is a result of code transformations.
1577b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case Primitive::kPrimByte:
1578b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case Primitive::kPrimShort:
1579b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case Primitive::kPrimInt:
1580b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case Primitive::kPrimChar:
1581b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          // Processing a Dex `int-to-float' instruction.
1582b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          locations->SetInAt(0, Location::RequiresRegister());
1583b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          locations->SetOut(Location::RequiresFpuRegister());
1584b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          break;
1585b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1586b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case Primitive::kPrimLong:
1587b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          // Processing a Dex `long-to-float' instruction.
1588b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          locations->SetInAt(0, Location::RequiresRegister());
1589b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          locations->SetOut(Location::RequiresFpuRegister());
1590b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          locations->AddTemp(Location::RequiresRegister());
1591b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          locations->AddTemp(Location::RequiresRegister());
1592b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          locations->AddTemp(Location::RequiresFpuRegister());
1593b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          locations->AddTemp(Location::RequiresFpuRegister());
1594b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          break;
1595b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1596b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case Primitive::kPrimDouble:
1597b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          // Processing a Dex `double-to-float' instruction.
1598b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          locations->SetInAt(0, Location::RequiresFpuRegister());
1599b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
1600b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          break;
1601b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1602b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        default:
1603b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          LOG(FATAL) << "Unexpected type conversion from " << input_type
1604b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                     << " to " << result_type;
1605b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      };
1606b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      break;
1607b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1608b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimDouble:
1609b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      switch (input_type) {
1610b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case Primitive::kPrimBoolean:
1611b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          // Boolean input is a result of code transformations.
1612b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case Primitive::kPrimByte:
1613b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case Primitive::kPrimShort:
1614b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case Primitive::kPrimInt:
1615b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case Primitive::kPrimChar:
1616b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          // Processing a Dex `int-to-double' instruction.
1617b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          locations->SetInAt(0, Location::RequiresRegister());
1618b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          locations->SetOut(Location::RequiresFpuRegister());
1619b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          break;
1620b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1621b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case Primitive::kPrimLong:
1622b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          // Processing a Dex `long-to-double' instruction.
16238de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert          locations->SetInAt(0, Location::RequiresRegister());
1624b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          locations->SetOut(Location::RequiresFpuRegister());
1625b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          locations->AddTemp(Location::RequiresRegister());
1626b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          locations->AddTemp(Location::RequiresRegister());
1627b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          locations->AddTemp(Location::RequiresFpuRegister());
1628b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          break;
1629b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1630b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case Primitive::kPrimFloat:
1631b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          // Processing a Dex `float-to-double' instruction.
1632b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          locations->SetInAt(0, Location::RequiresFpuRegister());
1633b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
1634b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          break;
1635b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1636b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        default:
1637b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          LOG(FATAL) << "Unexpected type conversion from " << input_type
1638b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                     << " to " << result_type;
1639b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      };
1640b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      break;
1641b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1642b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    default:
1643b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      LOG(FATAL) << "Unexpected type conversion from " << input_type
1644b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                 << " to " << result_type;
1645b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1646b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1647b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1648b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid InstructionCodeGeneratorARM::VisitTypeConversion(HTypeConversion* conversion) {
1649b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  LocationSummary* locations = conversion->GetLocations();
1650b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  Location out = locations->Out();
1651b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  Location in = locations->InAt(0);
1652b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  Primitive::Type result_type = conversion->GetResultType();
1653b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  Primitive::Type input_type = conversion->GetInputType();
1654b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  DCHECK_NE(result_type, input_type);
1655b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  switch (result_type) {
1656b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimByte:
1657b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      switch (input_type) {
1658b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case Primitive::kPrimBoolean:
1659b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          // Boolean input is a result of code transformations.
1660b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case Primitive::kPrimShort:
1661b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case Primitive::kPrimInt:
1662b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case Primitive::kPrimChar:
1663b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          // Processing a Dex `int-to-byte' instruction.
1664b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          __ sbfx(out.AsRegister<Register>(), in.AsRegister<Register>(), 0, 8);
1665b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          break;
1666b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1667b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        default:
1668b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          LOG(FATAL) << "Unexpected type conversion from " << input_type
1669b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                     << " to " << result_type;
1670b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      }
1671b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      break;
1672b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1673b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimShort:
1674b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      switch (input_type) {
1675b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case Primitive::kPrimBoolean:
1676b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          // Boolean input is a result of code transformations.
1677b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case Primitive::kPrimByte:
1678b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case Primitive::kPrimInt:
1679b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case Primitive::kPrimChar:
1680b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          // Processing a Dex `int-to-short' instruction.
1681b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          __ sbfx(out.AsRegister<Register>(), in.AsRegister<Register>(), 0, 16);
1682b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          break;
1683b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1684b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        default:
1685b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          LOG(FATAL) << "Unexpected type conversion from " << input_type
1686b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                     << " to " << result_type;
1687b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      }
1688b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      break;
1689b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1690b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimInt:
1691b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      switch (input_type) {
1692b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case Primitive::kPrimLong:
1693b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          // Processing a Dex `long-to-int' instruction.
1694b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          DCHECK(out.IsRegister());
1695b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          if (in.IsRegisterPair()) {
1696b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            __ Mov(out.AsRegister<Register>(), in.AsRegisterPairLow<Register>());
1697b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          } else if (in.IsDoubleStackSlot()) {
1698b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            __ LoadFromOffset(kLoadWord, out.AsRegister<Register>(), SP, in.GetStackIndex());
1699b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          } else {
1700b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            DCHECK(in.IsConstant());
1701b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            DCHECK(in.GetConstant()->IsLongConstant());
1702b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int64_t value = in.GetConstant()->AsLongConstant()->GetValue();
1703b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            __ LoadImmediate(out.AsRegister<Register>(), static_cast<int32_t>(value));
1704b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          }
1705b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          break;
1706b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1707b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case Primitive::kPrimFloat: {
1708b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          // Processing a Dex `float-to-int' instruction.
17098de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert          SRegister temp = locations->GetTemp(0).AsFpuRegisterPairLow<SRegister>();
1710b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          __ vmovs(temp, in.AsFpuRegister<SRegister>());
1711b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          __ vcvtis(temp, temp);
1712b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          __ vmovrs(out.AsRegister<Register>(), temp);
171359d709d503bab6e2b61931737e662dd293b40578ccornelius          break;
1714b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1715b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1716b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case Primitive::kPrimDouble: {
1717b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          // Processing a Dex `double-to-int' instruction.
1718b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          SRegister temp_s = locations->GetTemp(0).AsFpuRegisterPairLow<SRegister>();
1719b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          DRegister temp_d = FromLowSToD(temp_s);
1720b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          __ vmovd(temp_d, FromLowSToD(in.AsFpuRegisterPairLow<SRegister>()));
1721b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          __ vcvtid(temp_s, temp_d);
172250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho          __ vmovrs(out.AsRegister<Register>(), temp_s);
172350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho          break;
172450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        }
172550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
172650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        default:
172750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho          LOG(FATAL) << "Unexpected type conversion from " << input_type
172850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                     << " to " << result_type;
172950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho      }
173050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho      break;
173150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
173250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    case Primitive::kPrimLong:
173350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho      switch (input_type) {
173450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        case Primitive::kPrimBoolean:
173550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho          // Boolean input is a result of code transformations.
173650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        case Primitive::kPrimByte:
173750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        case Primitive::kPrimShort:
173850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        case Primitive::kPrimInt:
173950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        case Primitive::kPrimChar:
17408de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert          // Processing a Dex `int-to-long' instruction.
174150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho          DCHECK(out.IsRegisterPair());
174250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho          DCHECK(in.IsRegister());
174350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho          __ Mov(out.AsRegisterPairLow<Register>(), in.AsRegister<Register>());
174450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho          // Sign extension.
174550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho          __ Asr(out.AsRegisterPairHigh<Register>(),
174650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                 out.AsRegisterPairLow<Register>(),
174750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                 31);
174859d709d503bab6e2b61931737e662dd293b40578ccornelius          break;
174950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
175050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        case Primitive::kPrimFloat:
175150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho          // Processing a Dex `float-to-long' instruction.
175250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho          codegen_->InvokeRuntime(QUICK_ENTRY_POINT(pF2l),
175350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                                  conversion,
175450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                                  conversion->GetDexPc(),
175550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                                  nullptr);
175650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho          break;
1757b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1758b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case Primitive::kPrimDouble:
1759b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          // Processing a Dex `double-to-long' instruction.
1760b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          codegen_->InvokeRuntime(QUICK_ENTRY_POINT(pD2l),
1761b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                  conversion,
1762b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                  conversion->GetDexPc(),
1763b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                  nullptr);
17641b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert          break;
17651b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
1766b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        default:
1767b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          LOG(FATAL) << "Unexpected type conversion from " << input_type
1768b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                     << " to " << result_type;
1769b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      }
17701b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      break;
1771b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1772b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimChar:
1773b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      switch (input_type) {
1774b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case Primitive::kPrimBoolean:
1775b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          // Boolean input is a result of code transformations.
1776b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case Primitive::kPrimByte:
1777b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case Primitive::kPrimShort:
17781b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert        case Primitive::kPrimInt:
17791b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert          // Processing a Dex `int-to-char' instruction.
17801b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert          __ ubfx(out.AsRegister<Register>(), in.AsRegister<Register>(), 0, 16);
17811b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert          break;
17821b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
17831b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert        default:
17841b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert          LOG(FATAL) << "Unexpected type conversion from " << input_type
17851b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert                     << " to " << result_type;
17861b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      }
17871b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      break;
17881b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
17891b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    case Primitive::kPrimFloat:
17901b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      switch (input_type) {
17911b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert        case Primitive::kPrimBoolean:
1792b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          // Boolean input is a result of code transformations.
1793b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case Primitive::kPrimByte:
1794b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case Primitive::kPrimShort:
1795b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case Primitive::kPrimInt:
1796b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case Primitive::kPrimChar: {
1797b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          // Processing a Dex `int-to-float' instruction.
1798b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          __ vmovsr(out.AsFpuRegister<SRegister>(), in.AsRegister<Register>());
1799b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          __ vcvtsi(out.AsFpuRegister<SRegister>(), out.AsFpuRegister<SRegister>());
1800b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          break;
1801b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1802b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1803b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case Primitive::kPrimLong: {
1804b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          // Processing a Dex `long-to-float' instruction.
1805b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          Register low = in.AsRegisterPairLow<Register>();
1806b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          Register high = in.AsRegisterPairHigh<Register>();
1807b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          SRegister output = out.AsFpuRegister<SRegister>();
1808b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          Register constant_low = locations->GetTemp(0).AsRegister<Register>();
1809b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          Register constant_high = locations->GetTemp(1).AsRegister<Register>();
1810b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          SRegister temp1_s = locations->GetTemp(2).AsFpuRegisterPairLow<SRegister>();
1811b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          DRegister temp1_d = FromLowSToD(temp1_s);
1812b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          SRegister temp2_s = locations->GetTemp(3).AsFpuRegisterPairLow<SRegister>();
1813b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          DRegister temp2_d = FromLowSToD(temp2_s);
1814b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1815b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          // Operations use doubles for precision reasons (each 32-bit
1816b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          // half of a long fits in the 53-bit mantissa of a double,
1817b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          // but not in the 24-bit mantissa of a float).  This is
1818b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          // especially important for the low bits.  The result is
1819b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          // eventually converted to float.
1820b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1821b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          // temp1_d = int-to-double(high)
1822b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          __ vmovsr(temp1_s, high);
1823b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          __ vcvtdi(temp1_d, temp1_s);
1824b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          // Using vmovd to load the `k2Pow32EncodingForDouble` constant
1825b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          // as an immediate value into `temp2_d` does not work, as
1826b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          // this instruction only transfers 8 significant bits of its
1827b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          // immediate operand.  Instead, use two 32-bit core
1828b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          // registers to load `k2Pow32EncodingForDouble` into
1829b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          // `temp2_d`.
1830b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          __ LoadImmediate(constant_low, Low32Bits(k2Pow32EncodingForDouble));
1831b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          __ LoadImmediate(constant_high, High32Bits(k2Pow32EncodingForDouble));
1832b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          __ vmovdrr(temp2_d, constant_low, constant_high);
1833b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          // temp1_d = temp1_d * 2^32
1834b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          __ vmuld(temp1_d, temp1_d, temp2_d);
1835b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          // temp2_d = unsigned-to-double(low)
1836b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          __ vmovsr(temp2_s, low);
1837b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          __ vcvtdu(temp2_d, temp2_s);
1838b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          // temp1_d = temp1_d + temp2_d
1839b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          __ vaddd(temp1_d, temp1_d, temp2_d);
1840b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          // output = double-to-float(temp1_d);
18416d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru          __ vcvtsd(output, temp1_d);
1842b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          break;
1843b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1844b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1845b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case Primitive::kPrimDouble:
1846b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          // Processing a Dex `double-to-float' instruction.
1847b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          __ vcvtsd(out.AsFpuRegister<SRegister>(),
1848b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    FromLowSToD(in.AsFpuRegisterPairLow<SRegister>()));
1849b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          break;
1850b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1851b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        default:
1852b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          LOG(FATAL) << "Unexpected type conversion from " << input_type
1853b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                     << " to " << result_type;
18541b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      };
18551b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      break;
18561b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
18571b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    case Primitive::kPrimDouble:
1858b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      switch (input_type) {
18591b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert        case Primitive::kPrimBoolean:
1860b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          // Boolean input is a result of code transformations.
18611b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert        case Primitive::kPrimByte:
18621b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert        case Primitive::kPrimShort:
18631b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert        case Primitive::kPrimInt:
18641b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert        case Primitive::kPrimChar: {
18651b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert          // Processing a Dex `int-to-double' instruction.
18661b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert          __ vmovsr(out.AsFpuRegisterPairLow<SRegister>(), in.AsRegister<Register>());
18671b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert          __ vcvtdi(FromLowSToD(out.AsFpuRegisterPairLow<SRegister>()),
18681b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert                    out.AsFpuRegisterPairLow<SRegister>());
18691b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert          break;
18701b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert        }
18711b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
18721b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert        case Primitive::kPrimLong: {
18731b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert          // Processing a Dex `long-to-double' instruction.
1874b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          Register low = in.AsRegisterPairLow<Register>();
18751b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert          Register high = in.AsRegisterPairHigh<Register>();
1876b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          SRegister out_s = out.AsFpuRegisterPairLow<SRegister>();
1877b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          DRegister out_d = FromLowSToD(out_s);
1878b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          Register constant_low = locations->GetTemp(0).AsRegister<Register>();
1879b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          Register constant_high = locations->GetTemp(1).AsRegister<Register>();
1880b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          SRegister temp_s = locations->GetTemp(2).AsFpuRegisterPairLow<SRegister>();
18811b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert          DRegister temp_d = FromLowSToD(temp_s);
18821b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
18831b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert          // out_d = int-to-double(high)
18841b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert          __ vmovsr(out_s, high);
1885b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          __ vcvtdi(out_d, out_s);
18861b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert          // Using vmovd to load the `k2Pow32EncodingForDouble` constant
1887b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          // as an immediate value into `temp_d` does not work, as
18881b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert          // this instruction only transfers 8 significant bits of its
18891b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert          // immediate operand.  Instead, use two 32-bit core
18901b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert          // registers to load `k2Pow32EncodingForDouble` into `temp_d`.
18911b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert          __ LoadImmediate(constant_low, Low32Bits(k2Pow32EncodingForDouble));
18921b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert          __ LoadImmediate(constant_high, High32Bits(k2Pow32EncodingForDouble));
18931b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert          __ vmovdrr(temp_d, constant_low, constant_high);
18941b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert          // out_d = out_d * 2^32
18951b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert          __ vmuld(out_d, out_d, temp_d);
18961b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert          // temp_d = unsigned-to-double(low)
18971b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert          __ vmovsr(temp_s, low);
18981b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert          __ vcvtdu(temp_d, temp_s);
18991b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert          // out_d = out_d + temp_d
1900b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          __ vaddd(out_d, out_d, temp_d);
19011b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert          break;
19021b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert        }
19031b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
19041b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert        case Primitive::kPrimFloat:
19051b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert          // Processing a Dex `float-to-double' instruction.
19061b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert          __ vcvtds(FromLowSToD(out.AsFpuRegisterPairLow<SRegister>()),
19071b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert                    in.AsFpuRegister<SRegister>());
19081b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert          break;
19091b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
19101b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert        default:
19111b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert          LOG(FATAL) << "Unexpected type conversion from " << input_type
19121b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert                     << " to " << result_type;
1913b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      };
19141b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      break;
1915b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1916b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    default:
1917b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      LOG(FATAL) << "Unexpected type conversion from " << input_type
1918b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                 << " to " << result_type;
1919b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
19201b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert}
19211b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
19221b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubertvoid LocationsBuilderARM::VisitAdd(HAdd* add) {
19231b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert  LocationSummary* locations =
19241b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      new (GetGraph()->GetArena()) LocationSummary(add, LocationSummary::kNoCall);
19251b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert  switch (add->GetResultType()) {
19261b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    case Primitive::kPrimInt: {
19271b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      locations->SetInAt(0, Location::RequiresRegister());
1928b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      locations->SetInAt(1, Location::RegisterOrConstant(add->InputAt(1)));
19291b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
19301b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      break;
19311b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    }
19321b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
19331b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    case Primitive::kPrimLong: {
19341b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      locations->SetInAt(0, Location::RequiresRegister());
19351b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      locations->SetInAt(1, Location::RequiresRegister());
19361b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
19371b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      break;
19381b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    }
19391b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
19401b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    case Primitive::kPrimFloat:
1941b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimDouble: {
19421b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      locations->SetInAt(0, Location::RequiresFpuRegister());
19431b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      locations->SetInAt(1, Location::RequiresFpuRegister());
19441b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
19451b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      break;
19461b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    }
19471b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
19481b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    default:
19491b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      LOG(FATAL) << "Unexpected add type " << add->GetResultType();
19501b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert  }
19511b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert}
19521b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
19531b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubertvoid InstructionCodeGeneratorARM::VisitAdd(HAdd* add) {
1954b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  LocationSummary* locations = add->GetLocations();
19551b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert  Location out = locations->Out();
1956b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  Location first = locations->InAt(0);
1957b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  Location second = locations->InAt(1);
1958b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  switch (add->GetResultType()) {
1959b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimInt:
1960b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      if (second.IsRegister()) {
19611b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert        __ add(out.AsRegister<Register>(),
19621b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert               first.AsRegister<Register>(),
19631b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert               ShifterOperand(second.AsRegister<Register>()));
19641b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      } else {
19651b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert        __ AddConstant(out.AsRegister<Register>(),
1966b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                       first.AsRegister<Register>(),
19671b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert                       second.GetConstant()->AsIntConstant()->GetValue());
1968b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      }
19691b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      break;
19701b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
19711b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    case Primitive::kPrimLong: {
19721b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      DCHECK(second.IsRegisterPair());
19731b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      __ adds(out.AsRegisterPairLow<Register>(),
19741b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert              first.AsRegisterPairLow<Register>(),
19751b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert              ShifterOperand(second.AsRegisterPairLow<Register>()));
1976b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      __ adc(out.AsRegisterPairHigh<Register>(),
19771b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert             first.AsRegisterPairHigh<Register>(),
19781b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert             ShifterOperand(second.AsRegisterPairHigh<Register>()));
19791b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      break;
19801b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    }
19811b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
19821b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    case Primitive::kPrimFloat:
19831b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      __ vadds(out.AsFpuRegister<SRegister>(),
19841b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert               first.AsFpuRegister<SRegister>(),
19851b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert               second.AsFpuRegister<SRegister>());
19861b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      break;
19871b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
19881b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    case Primitive::kPrimDouble:
19891b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      __ vaddd(FromLowSToD(out.AsFpuRegisterPairLow<SRegister>()),
19901b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert               FromLowSToD(first.AsFpuRegisterPairLow<SRegister>()),
19911b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert               FromLowSToD(second.AsFpuRegisterPairLow<SRegister>()));
19921b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      break;
19931b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
19941b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    default:
19951b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      LOG(FATAL) << "Unexpected add type " << add->GetResultType();
19961b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert  }
19971b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert}
19981b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
19991b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubertvoid LocationsBuilderARM::VisitSub(HSub* sub) {
20001b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert  LocationSummary* locations =
20011b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      new (GetGraph()->GetArena()) LocationSummary(sub, LocationSummary::kNoCall);
20021b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert  switch (sub->GetResultType()) {
20031b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    case Primitive::kPrimInt: {
20041b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      locations->SetInAt(0, Location::RequiresRegister());
20051b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      locations->SetInAt(1, Location::RegisterOrConstant(sub->InputAt(1)));
20061b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
2007b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      break;
2008b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2009b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2010b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimLong: {
2011b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      locations->SetInAt(0, Location::RequiresRegister());
2012b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      locations->SetInAt(1, Location::RequiresRegister());
2013b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
2014b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      break;
2015b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
20161b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    case Primitive::kPrimFloat:
2017b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimDouble: {
2018b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      locations->SetInAt(0, Location::RequiresFpuRegister());
2019b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      locations->SetInAt(1, Location::RequiresFpuRegister());
20201b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
2021b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      break;
2022b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2023b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    default:
2024b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      LOG(FATAL) << "Unexpected sub type " << sub->GetResultType();
2025b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
20261b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert}
20271b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
2028b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid InstructionCodeGeneratorARM::VisitSub(HSub* sub) {
20291b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert  LocationSummary* locations = sub->GetLocations();
20301b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert  Location out = locations->Out();
20311b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert  Location first = locations->InAt(0);
20321b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert  Location second = locations->InAt(1);
20331b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert  switch (sub->GetResultType()) {
2034b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimInt: {
20351b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      if (second.IsRegister()) {
2036b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        __ sub(out.AsRegister<Register>(),
20371b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert               first.AsRegister<Register>(),
20381b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert               ShifterOperand(second.AsRegister<Register>()));
20391b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      } else {
20401b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert        __ AddConstant(out.AsRegister<Register>(),
20411b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert                       first.AsRegister<Register>(),
20421b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert                       -second.GetConstant()->AsIntConstant()->GetValue());
20431b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      }
20441b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      break;
20451b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    }
20461b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
20471b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    case Primitive::kPrimLong: {
20481b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      DCHECK(second.IsRegisterPair());
20491b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      __ subs(out.AsRegisterPairLow<Register>(),
20501b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert              first.AsRegisterPairLow<Register>(),
20511b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert              ShifterOperand(second.AsRegisterPairLow<Register>()));
20521b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      __ sbc(out.AsRegisterPairHigh<Register>(),
20531b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert             first.AsRegisterPairHigh<Register>(),
20541b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert             ShifterOperand(second.AsRegisterPairHigh<Register>()));
20551b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      break;
20561b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    }
20571b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
20581b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    case Primitive::kPrimFloat: {
20591b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      __ vsubs(out.AsFpuRegister<SRegister>(),
20601b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert               first.AsFpuRegister<SRegister>(),
20611b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert               second.AsFpuRegister<SRegister>());
20621b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      break;
20631b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    }
20641b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
20651b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    case Primitive::kPrimDouble: {
20661b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      __ vsubd(FromLowSToD(out.AsFpuRegisterPairLow<SRegister>()),
20671b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert               FromLowSToD(first.AsFpuRegisterPairLow<SRegister>()),
20681b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert               FromLowSToD(second.AsFpuRegisterPairLow<SRegister>()));
20691b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      break;
20701b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    }
20711b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
20721b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
20731b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    default:
20741b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      LOG(FATAL) << "Unexpected sub type " << sub->GetResultType();
20751b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert  }
20761b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert}
2077b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2078b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid LocationsBuilderARM::VisitMul(HMul* mul) {
20791b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert  LocationSummary* locations =
2080b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      new (GetGraph()->GetArena()) LocationSummary(mul, LocationSummary::kNoCall);
2081b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  switch (mul->GetResultType()) {
2082b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimInt:
2083b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimLong:  {
2084b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      locations->SetInAt(0, Location::RequiresRegister());
2085b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      locations->SetInAt(1, Location::RequiresRegister());
20861b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
2087b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      break;
2088b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2089b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
20901b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    case Primitive::kPrimFloat:
2091b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimDouble: {
20921b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      locations->SetInAt(0, Location::RequiresFpuRegister());
20931b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      locations->SetInAt(1, Location::RequiresFpuRegister());
20941b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
20951b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      break;
20961b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    }
20971b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
20981b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    default:
20991b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      LOG(FATAL) << "Unexpected mul type " << mul->GetResultType();
21001b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert  }
21011b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert}
21021b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
21031b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubertvoid InstructionCodeGeneratorARM::VisitMul(HMul* mul) {
21041b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert  LocationSummary* locations = mul->GetLocations();
21051b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert  Location out = locations->Out();
21061b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert  Location first = locations->InAt(0);
21071b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert  Location second = locations->InAt(1);
21081b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert  switch (mul->GetResultType()) {
21091b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    case Primitive::kPrimInt: {
21101b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      __ mul(out.AsRegister<Register>(),
21111b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert             first.AsRegister<Register>(),
21121b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert             second.AsRegister<Register>());
21131b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      break;
21141b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    }
21151b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    case Primitive::kPrimLong: {
21161b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      Register out_hi = out.AsRegisterPairHigh<Register>();
21171b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      Register out_lo = out.AsRegisterPairLow<Register>();
21181b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      Register in1_hi = first.AsRegisterPairHigh<Register>();
21191b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      Register in1_lo = first.AsRegisterPairLow<Register>();
21201b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      Register in2_hi = second.AsRegisterPairHigh<Register>();
21211b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      Register in2_lo = second.AsRegisterPairLow<Register>();
21221b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
21231b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      // Extra checks to protect caused by the existence of R1_R2.
21241b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      // The algorithm is wrong if out.hi is either in1.lo or in2.lo:
21251b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      // (e.g. in1=r0_r1, in2=r2_r3 and out=r1_r2);
21261b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      DCHECK_NE(out_hi, in1_lo);
21271b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      DCHECK_NE(out_hi, in2_lo);
21281b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
21291b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      // input: in1 - 64 bits, in2 - 64 bits
21301b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      // output: out
21311b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      // formula: out.hi : out.lo = (in1.lo * in2.hi + in1.hi * in2.lo)* 2^32 + in1.lo * in2.lo
21321b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      // parts: out.hi = in1.lo * in2.hi + in1.hi * in2.lo + (in1.lo * in2.lo)[63:32]
21331b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      // parts: out.lo = (in1.lo * in2.lo)[31:0]
21341b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
21351b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      // IP <- in1.lo * in2.hi
21361b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      __ mul(IP, in1_lo, in2_hi);
21371b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      // out.hi <- in1.lo * in2.hi + in1.hi * in2.lo
21381b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      __ mla(out_hi, in1_hi, in2_lo, IP);
21391b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      // out.lo <- (in1.lo * in2.lo)[31:0];
21401b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      __ umull(out_lo, IP, in1_lo, in2_lo);
21411b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      // out.hi <- in2.hi * in1.lo +  in2.lo * in1.hi + (in1.lo * in2.lo)[63:32]
21421b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      __ add(out_hi, out_hi, ShifterOperand(IP));
21431b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      break;
21441b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    }
21451b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
21461b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    case Primitive::kPrimFloat: {
21471b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      __ vmuls(out.AsFpuRegister<SRegister>(),
21481b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert               first.AsFpuRegister<SRegister>(),
21491b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert               second.AsFpuRegister<SRegister>());
21501b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      break;
21511b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    }
21521b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
21531b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    case Primitive::kPrimDouble: {
21541b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      __ vmuld(FromLowSToD(out.AsFpuRegisterPairLow<SRegister>()),
21551b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert               FromLowSToD(first.AsFpuRegisterPairLow<SRegister>()),
21561b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert               FromLowSToD(second.AsFpuRegisterPairLow<SRegister>()));
21571b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      break;
21581b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    }
21591b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
21601b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    default:
21611b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      LOG(FATAL) << "Unexpected mul type " << mul->GetResultType();
21621b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert  }
2163b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
21641b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
21651b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubertvoid LocationsBuilderARM::VisitDiv(HDiv* div) {
2166b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  LocationSummary::CallKind call_kind = LocationSummary::kNoCall;
2167b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if (div->GetResultType() == Primitive::kPrimLong) {
21681b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    // pLdiv runtime call.
2169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    call_kind = LocationSummary::kCall;
21701b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert  } else if (div->GetResultType() == Primitive::kPrimInt &&
21711b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert             !codegen_->GetInstructionSetFeatures().HasDivideInstruction()) {
21721b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    // pIdivmod runtime call.
21731b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    call_kind = LocationSummary::kCall;
21741b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert  }
21751b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
21761b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert  LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(div, call_kind);
21771b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
21781b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert  switch (div->GetResultType()) {
21791b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    case Primitive::kPrimInt: {
21801b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      if (codegen_->GetInstructionSetFeatures().HasDivideInstruction()) {
21811b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert        locations->SetInAt(0, Location::RequiresRegister());
21821b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert        locations->SetInAt(1, Location::RequiresRegister());
21831b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert        locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
21841b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      } else {
21851b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert        InvokeRuntimeCallingConvention calling_convention;
21861b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert        locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0)));
2187b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        locations->SetInAt(1, Location::RegisterLocation(calling_convention.GetRegisterAt(1)));
21881b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert        // Note: divrem will compute both the quotient and the remainder as the pair R0 and R1, but
21891b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert        //       we only need the former.
21901b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert        locations->SetOut(Location::RegisterLocation(R0));
2191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      }
2192b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      break;
2193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2194b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimLong: {
2195103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      InvokeRuntimeCallingConvention calling_convention;
2196b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      locations->SetInAt(0, Location::RegisterPairLocation(
2197b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          calling_convention.GetRegisterAt(0), calling_convention.GetRegisterAt(1)));
2198b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      locations->SetInAt(1, Location::RegisterPairLocation(
2199103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius          calling_convention.GetRegisterAt(2), calling_convention.GetRegisterAt(3)));
2200b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      locations->SetOut(Location::RegisterPairLocation(R0, R1));
2201b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      break;
2202b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2203103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    case Primitive::kPrimFloat:
2204b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimDouble: {
2205b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      locations->SetInAt(0, Location::RequiresFpuRegister());
2206b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      locations->SetInAt(1, Location::RequiresFpuRegister());
2207103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
2208b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      break;
2209b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2210b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2211103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    default:
2212103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      LOG(FATAL) << "Unexpected div type " << div->GetResultType();
2213103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  }
2214103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius}
2215103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
2216b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid InstructionCodeGeneratorARM::VisitDiv(HDiv* div) {
2217b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  LocationSummary* locations = div->GetLocations();
2218b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  Location out = locations->Out();
2219b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  Location first = locations->InAt(0);
2220b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  Location second = locations->InAt(1);
2221b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2222b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  switch (div->GetResultType()) {
2223b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimInt: {
2224b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      if (codegen_->GetInstructionSetFeatures().HasDivideInstruction()) {
2225b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        __ sdiv(out.AsRegister<Register>(),
2226b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                first.AsRegister<Register>(),
2227b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                second.AsRegister<Register>());
2228b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      } else {
2229b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        InvokeRuntimeCallingConvention calling_convention;
2230b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        DCHECK_EQ(calling_convention.GetRegisterAt(0), first.AsRegister<Register>());
2231b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        DCHECK_EQ(calling_convention.GetRegisterAt(1), second.AsRegister<Register>());
2232b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        DCHECK_EQ(R0, out.AsRegister<Register>());
2233b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2234b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        codegen_->InvokeRuntime(QUICK_ENTRY_POINT(pIdivmod), div, div->GetDexPc(), nullptr);
2235b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      }
2236b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      break;
2237b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2238b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2239b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimLong: {
224027f654740f2a26ad62a5c155af9199af9e69b889claireho      InvokeRuntimeCallingConvention calling_convention;
224127f654740f2a26ad62a5c155af9199af9e69b889claireho      DCHECK_EQ(calling_convention.GetRegisterAt(0), first.AsRegisterPairLow<Register>());
224227f654740f2a26ad62a5c155af9199af9e69b889claireho      DCHECK_EQ(calling_convention.GetRegisterAt(1), first.AsRegisterPairHigh<Register>());
2243b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      DCHECK_EQ(calling_convention.GetRegisterAt(2), second.AsRegisterPairLow<Register>());
2244b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      DCHECK_EQ(calling_convention.GetRegisterAt(3), second.AsRegisterPairHigh<Register>());
2245b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      DCHECK_EQ(R0, out.AsRegisterPairLow<Register>());
2246b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      DCHECK_EQ(R1, out.AsRegisterPairHigh<Register>());
2247b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2248b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      codegen_->InvokeRuntime(QUICK_ENTRY_POINT(pLdiv), div, div->GetDexPc(), nullptr);
2249b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      break;
2250b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2251b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2252b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimFloat: {
2253b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      __ vdivs(out.AsFpuRegister<SRegister>(),
2254b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru               first.AsFpuRegister<SRegister>(),
2255b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru               second.AsFpuRegister<SRegister>());
2256b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      break;
2257b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2258b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2259b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimDouble: {
2260b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      __ vdivd(FromLowSToD(out.AsFpuRegisterPairLow<SRegister>()),
2261b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru               FromLowSToD(first.AsFpuRegisterPairLow<SRegister>()),
2262b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru               FromLowSToD(second.AsFpuRegisterPairLow<SRegister>()));
2263b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      break;
2264b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2265b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2266b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    default:
2267b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      LOG(FATAL) << "Unexpected div type " << div->GetResultType();
2268b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
2269b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2270b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2271b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid LocationsBuilderARM::VisitRem(HRem* rem) {
2272c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  Primitive::Type type = rem->GetResultType();
2273b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2274b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // Most remainders are implemented in the runtime.
2275b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  LocationSummary::CallKind call_kind = LocationSummary::kCall;
2276b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if (rem->GetResultType() == Primitive::kPrimInt &&
2277b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      codegen_->GetInstructionSetFeatures().HasDivideInstruction()) {
2278b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Have hardware divide instruction for int, do it with three instructions.
2279b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    call_kind = LocationSummary::kNoCall;
2280b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
2281b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2282b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(rem, call_kind);
2283b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2284b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  switch (type) {
228554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    case Primitive::kPrimInt: {
228654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius      if (codegen_->GetInstructionSetFeatures().HasDivideInstruction()) {
228754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        locations->SetInAt(0, Location::RequiresRegister());
2288c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        locations->SetInAt(1, Location::RequiresRegister());
2289c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
2290c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        locations->AddTemp(Location::RequiresRegister());
2291b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      } else {
2292b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        InvokeRuntimeCallingConvention calling_convention;
2293b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0)));
2294b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        locations->SetInAt(1, Location::RegisterLocation(calling_convention.GetRegisterAt(1)));
2295b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // Note: divrem will compute both the quotient and the remainder as the pair R0 and R1, but
2296b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        //       we only need the latter.
2297b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        locations->SetOut(Location::RegisterLocation(R1));
2298b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      }
2299b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      break;
2300b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2301b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimLong: {
2302b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      InvokeRuntimeCallingConvention calling_convention;
2303b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      locations->SetInAt(0, Location::RegisterPairLocation(
2304b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          calling_convention.GetRegisterAt(0), calling_convention.GetRegisterAt(1)));
2305b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      locations->SetInAt(1, Location::RegisterPairLocation(
2306b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          calling_convention.GetRegisterAt(2), calling_convention.GetRegisterAt(3)));
2307b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      // The runtime helper puts the output in R2,R3.
2308b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      locations->SetOut(Location::RegisterPairLocation(R2, R3));
2309b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      break;
2310b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2311b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimFloat: {
2312b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      InvokeRuntimeCallingConvention calling_convention;
2313b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      locations->SetInAt(0, Location::FpuRegisterLocation(calling_convention.GetFpuRegisterAt(0)));
2314b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      locations->SetInAt(1, Location::FpuRegisterLocation(calling_convention.GetFpuRegisterAt(1)));
2315b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      locations->SetOut(Location::FpuRegisterLocation(S0));
2316b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      break;
2317b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2318b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2319b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimDouble: {
2320b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      InvokeRuntimeCallingConvention calling_convention;
2321b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      locations->SetInAt(0, Location::FpuRegisterPairLocation(
2322b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          calling_convention.GetFpuRegisterAt(0), calling_convention.GetFpuRegisterAt(1)));
2323b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      locations->SetInAt(1, Location::FpuRegisterPairLocation(
2324b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          calling_convention.GetFpuRegisterAt(2), calling_convention.GetFpuRegisterAt(3)));
2325b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      locations->SetOut(Location::Location::FpuRegisterPairLocation(S0, S1));
2326b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      break;
2327b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
23288de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert
2329b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    default:
2330b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      LOG(FATAL) << "Unexpected rem type " << type;
2331b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
2332b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2333b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2334b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid InstructionCodeGeneratorARM::VisitRem(HRem* rem) {
2335b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  LocationSummary* locations = rem->GetLocations();
2336b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  Location out = locations->Out();
2337b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  Location first = locations->InAt(0);
2338b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  Location second = locations->InAt(1);
2339b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2340b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  Primitive::Type type = rem->GetResultType();
2341b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  switch (type) {
2342b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case Primitive::kPrimInt: {
2343c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      if (codegen_->GetInstructionSetFeatures().HasDivideInstruction()) {
2344c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        Register reg1 = first.AsRegister<Register>();
2345c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        Register reg2 = second.AsRegister<Register>();
2346c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        Register temp = locations->GetTemp(0).AsRegister<Register>();
2347c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
2348c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // temp = reg1 / reg2  (integer division)
2349c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // temp = temp * reg2
2350c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // dest = reg1 - temp
2351c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        __ sdiv(temp, reg1, reg2);
2352c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        __ mul(temp, temp, reg2);
2353c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        __ sub(out.AsRegister<Register>(), reg1, ShifterOperand(temp));
2354c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      } else {
2355c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        InvokeRuntimeCallingConvention calling_convention;
23566d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru        DCHECK_EQ(calling_convention.GetRegisterAt(0), first.AsRegister<Register>());
2357c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        DCHECK_EQ(calling_convention.GetRegisterAt(1), second.AsRegister<Register>());
2358c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        DCHECK_EQ(R1, out.AsRegister<Register>());
23596d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru
2360c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        codegen_->InvokeRuntime(QUICK_ENTRY_POINT(pIdivmod), rem, rem->GetDexPc(), nullptr);
2361c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      }
2362c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      break;
23636d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru    }
2364c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
2365c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    case Primitive::kPrimLong: {
2366c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      codegen_->InvokeRuntime(QUICK_ENTRY_POINT(pLmod), rem, rem->GetDexPc(), nullptr);
2367c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      break;
23686d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru    }
2369c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
2370c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    case Primitive::kPrimFloat: {
23716d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru      codegen_->InvokeRuntime(QUICK_ENTRY_POINT(pFmodf), rem, rem->GetDexPc(), nullptr);
2372c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      break;
2373c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
2374c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
2375c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    case Primitive::kPrimDouble: {
2376c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      codegen_->InvokeRuntime(QUICK_ENTRY_POINT(pFmod), rem, rem->GetDexPc(), nullptr);
23776d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru      break;
2378c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
2379c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
2380c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    default:
2381c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      LOG(FATAL) << "Unexpected rem type " << type;
2382c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  }
2383c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
23846d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru
2385c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queruvoid LocationsBuilderARM::VisitDivZeroCheck(HDivZeroCheck* instruction) {
2386c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  LocationSummary* locations =
2387c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
2388c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  locations->SetInAt(0, Location::RegisterOrConstant(instruction->InputAt(0)));
2389c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  if (instruction->HasUses()) {
23906d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru    locations->SetOut(Location::SameAsFirstInput());
2391c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  }
2392c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
2393c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
2394c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queruvoid InstructionCodeGeneratorARM::VisitDivZeroCheck(HDivZeroCheck* instruction) {
2395c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  SlowPathCodeARM* slow_path = new (GetGraph()->GetArena()) DivZeroCheckSlowPathARM(instruction);
2396c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  codegen_->AddSlowPath(slow_path);
23976d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru
2398c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  LocationSummary* locations = instruction->GetLocations();
2399c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  Location value = locations->InAt(0);
2400c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
2401c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  switch (instruction->GetType()) {
2402c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    case Primitive::kPrimInt: {
24036d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru      if (value.IsRegister()) {
2404c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        __ cmp(value.AsRegister<Register>(), ShifterOperand(0));
2405c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        __ b(slow_path->GetEntryLabel(), EQ);
2406c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      } else {
2407c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        DCHECK(value.IsConstant()) << value;
2408c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if (value.GetConstant()->AsIntConstant()->GetValue() == 0) {
2409c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          __ b(slow_path->GetEntryLabel());
2410c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
24116d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru      }
2412c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      break;
2413c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
2414c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    case Primitive::kPrimLong: {
2415c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      if (value.IsRegisterPair()) {
2416c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        __ orrs(IP,
24176d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru                value.AsRegisterPairLow<Register>(),
2418c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                ShifterOperand(value.AsRegisterPairHigh<Register>()));
2419c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        __ b(slow_path->GetEntryLabel(), EQ);
2420c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      } else {
2421c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        DCHECK(value.IsConstant()) << value;
2422c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if (value.GetConstant()->AsLongConstant()->GetValue() == 0) {
24236d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru          __ b(slow_path->GetEntryLabel());
2424c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
2425c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      }
2426c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      break;
2427c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    default:
2428c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      LOG(FATAL) << "Unexpected type for HDivZeroCheck " << instruction->GetType();
24296d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru    }
2430c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  }
2431c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
2432c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
2433c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queruvoid LocationsBuilderARM::HandleShift(HBinaryOperation* op) {
2434c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  DCHECK(op->IsShl() || op->IsShr() || op->IsUShr());
24356d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru
2436c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  LocationSummary* locations =
2437c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      new (GetGraph()->GetArena()) LocationSummary(op, LocationSummary::kNoCall);
2438c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
2439c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  switch (op->GetResultType()) {
2440c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    case Primitive::kPrimInt: {
2441c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      locations->SetInAt(0, Location::RequiresRegister());
24426d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru      locations->SetInAt(1, Location::RegisterOrConstant(op->InputAt(1)));
2443c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
2444c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      break;
2445c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
2446c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    case Primitive::kPrimLong: {
2447c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      locations->SetInAt(0, Location::RequiresRegister());
24486d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru      locations->SetInAt(1, Location::RequiresRegister());
2449c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      locations->AddTemp(Location::RequiresRegister());
2450c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      locations->SetOut(Location::RequiresRegister());
2451c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      break;
2452c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
2453c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    default:
24546d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru      LOG(FATAL) << "Unexpected operation type " << op->GetResultType();
2455c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  }
2456c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
2457c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
2458c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queruvoid InstructionCodeGeneratorARM::HandleShift(HBinaryOperation* op) {
2459c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  DCHECK(op->IsShl() || op->IsShr() || op->IsUShr());
24606d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru
2461c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  LocationSummary* locations = op->GetLocations();
2462c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  Location out = locations->Out();
2463c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  Location first = locations->InAt(0);
2464c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  Location second = locations->InAt(1);
2465c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
2466c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  Primitive::Type type = op->GetResultType();
24676d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru  switch (type) {
2468c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    case Primitive::kPrimInt: {
2469c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      Register out_reg = out.AsRegister<Register>();
2470c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      Register first_reg = first.AsRegister<Register>();
2471c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      // Arm doesn't mask the shift count so we need to do it ourselves.
2472c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      if (second.IsRegister()) {
24736d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru        Register second_reg = second.AsRegister<Register>();
2474c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        __ and_(second_reg, second_reg, ShifterOperand(kMaxIntShiftValue));
2475c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if (op->IsShl()) {
2476c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          __ Lsl(out_reg, first_reg, second_reg);
2477c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        } else if (op->IsShr()) {
2478c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          __ Asr(out_reg, first_reg, second_reg);
24796d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru        } else {
2480c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          __ Lsr(out_reg, first_reg, second_reg);
2481c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
2482c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      } else {
2483c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        int32_t cst = second.GetConstant()->AsIntConstant()->GetValue();
2484c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        uint32_t shift_value = static_cast<uint32_t>(cst & kMaxIntShiftValue);
2485c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if (shift_value == 0) {  // arm does not support shifting with 0 immediate.
24866d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru          __ Mov(out_reg, first_reg);
2487c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        } else if (op->IsShl()) {
2488c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          __ Lsl(out_reg, first_reg, shift_value);
2489c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        } else if (op->IsShr()) {
2490c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          __ Asr(out_reg, first_reg, shift_value);
2491c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        } else {
24926d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru          __ Lsr(out_reg, first_reg, shift_value);
2493c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
2494c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      }
2495c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      break;
2496c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
2497c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    case Primitive::kPrimLong: {
2498c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      Register o_h = out.AsRegisterPairHigh<Register>();
2499c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      Register o_l = out.AsRegisterPairLow<Register>();
25006d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru
2501c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      Register temp = locations->GetTemp(0).AsRegister<Register>();
2502c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
2503c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      Register high = first.AsRegisterPairHigh<Register>();
25046d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru      Register low = first.AsRegisterPairLow<Register>();
2505c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
2506c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      Register second_reg = second.AsRegister<Register>();
2507c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
2508c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      if (op->IsShl()) {
2509c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // Shift the high part
2510c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        __ and_(second_reg, second_reg, ShifterOperand(63));
25116d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru        __ Lsl(o_h, high, second_reg);
2512c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // Shift the low part and `or` what overflew on the high part
2513c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        __ rsb(temp, second_reg, ShifterOperand(32));
2514c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        __ Lsr(temp, low, temp);
2515c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        __ orr(o_h, o_h, ShifterOperand(temp));
2516c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // If the shift is > 32 bits, override the high part
25176d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru        __ subs(temp, second_reg, ShifterOperand(32));
2518c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        __ it(PL);
2519c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        __ Lsl(o_h, low, temp, false, PL);
2520c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // Shift the low part
2521c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        __ Lsl(o_l, low, second_reg);
2522c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      } else if (op->IsShr()) {
2523c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // Shift the low part
2524c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        __ and_(second_reg, second_reg, ShifterOperand(63));
25256d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru        __ Lsr(o_l, low, second_reg);
2526c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // Shift the high part and `or` what underflew on the low part
2527c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        __ rsb(temp, second_reg, ShifterOperand(32));
2528c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        __ Lsl(temp, high, temp);
2529c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        __ orr(o_l, o_l, ShifterOperand(temp));
25306d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru        // If the shift is > 32 bits, override the low part
2531c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        __ subs(temp, second_reg, ShifterOperand(32));
2532c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        __ it(PL);
2533c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        __ Asr(o_l, high, temp, false, PL);
2534c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // Shift the high part
25356d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru        __ Asr(o_h, high, second_reg);
2536c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      } else {
2537c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // same as Shr except we use `Lsr`s and not `Asr`s
2538c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        __ and_(second_reg, second_reg, ShifterOperand(63));
2539c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        __ Lsr(o_l, low, second_reg);
2540c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        __ rsb(temp, second_reg, ShifterOperand(32));
2541c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        __ Lsl(temp, high, temp);
2542c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        __ orr(o_l, o_l, ShifterOperand(temp));
2543c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        __ subs(temp, second_reg, ShifterOperand(32));
25446d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru        __ it(PL);
2545c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        __ Lsr(o_l, high, temp, false, PL);
2546c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        __ Lsr(o_h, high, second_reg);
2547c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      }
2548c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      break;
2549c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
25506d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru    default:
2551c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      LOG(FATAL) << "Unexpected operation type " << type;
2552c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  }
2553c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
2554c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
2555c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queruvoid LocationsBuilderARM::VisitShl(HShl* shl) {
2556c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  HandleShift(shl);
25576d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru}
2558c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
2559c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queruvoid InstructionCodeGeneratorARM::VisitShl(HShl* shl) {
2560c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  HandleShift(shl);
2561c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
2562c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
25636d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queruvoid LocationsBuilderARM::VisitShr(HShr* shr) {
2564c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  HandleShift(shr);
2565c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
2566c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
2567c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queruvoid InstructionCodeGeneratorARM::VisitShr(HShr* shr) {
2568c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  HandleShift(shr);
25696d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru}
2570c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
2571c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queruvoid LocationsBuilderARM::VisitUShr(HUShr* ushr) {
2572c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  HandleShift(ushr);
2573c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
2574c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
2575c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queruvoid InstructionCodeGeneratorARM::VisitUShr(HUShr* ushr) {
25766d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru  HandleShift(ushr);
2577c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
2578c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
2579c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queruvoid LocationsBuilderARM::VisitNewInstance(HNewInstance* instruction) {
2580c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  LocationSummary* locations =
2581c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCall);
25826d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru  InvokeRuntimeCallingConvention calling_convention;
2583c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  locations->AddTemp(Location::RegisterLocation(calling_convention.GetRegisterAt(0)));
2584c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  locations->AddTemp(Location::RegisterLocation(calling_convention.GetRegisterAt(1)));
2585c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  locations->SetOut(Location::RegisterLocation(R0));
2586c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
2587c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
25886d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queruvoid InstructionCodeGeneratorARM::VisitNewInstance(HNewInstance* instruction) {
2589c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  InvokeRuntimeCallingConvention calling_convention;
2590c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  codegen_->LoadCurrentMethod(calling_convention.GetRegisterAt(1));
2591c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  __ LoadImmediate(calling_convention.GetRegisterAt(0), instruction->GetTypeIndex());
2592c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  codegen_->InvokeRuntime(GetThreadOffset<kArmWordSize>(instruction->GetEntrypoint()).Int32Value(),
2593c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                          instruction,
2594c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                          instruction->GetDexPc(),
25956d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru                          nullptr);
2596c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
2597c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
2598c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queruvoid LocationsBuilderARM::VisitNewArray(HNewArray* instruction) {
2599c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  LocationSummary* locations =
2600c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCall);
26016d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru  InvokeRuntimeCallingConvention calling_convention;
2602c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  locations->AddTemp(Location::RegisterLocation(calling_convention.GetRegisterAt(0)));
2603c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  locations->AddTemp(Location::RegisterLocation(calling_convention.GetRegisterAt(2)));
2604c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  locations->SetOut(Location::RegisterLocation(R0));
2605c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(1)));
2606c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
2607c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
26086d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queruvoid InstructionCodeGeneratorARM::VisitNewArray(HNewArray* instruction) {
2609c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  InvokeRuntimeCallingConvention calling_convention;
2610c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  codegen_->LoadCurrentMethod(calling_convention.GetRegisterAt(2));
2611c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  __ LoadImmediate(calling_convention.GetRegisterAt(0), instruction->GetTypeIndex());
26126d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru  codegen_->InvokeRuntime(GetThreadOffset<kArmWordSize>(instruction->GetEntrypoint()).Int32Value(),
2613c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                          instruction,
2614c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                          instruction->GetDexPc(),
2615c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                          nullptr);
2616c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
2617c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
2618c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queruvoid LocationsBuilderARM::VisitParameterValue(HParameterValue* instruction) {
2619c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  LocationSummary* locations =
2620c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
26216d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru  Location location = parameter_visitor_.GetNextLocation(instruction->GetType());
2622c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  if (location.IsStackSlot()) {
2623c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    location = Location::StackSlot(location.GetStackIndex() + codegen_->GetFrameSize());
2624c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  } else if (location.IsDoubleStackSlot()) {
2625c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    location = Location::DoubleStackSlot(location.GetStackIndex() + codegen_->GetFrameSize());
2626c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  }
26276d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru  locations->SetOut(location);
2628c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
2629c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
2630c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queruvoid InstructionCodeGeneratorARM::VisitParameterValue(HParameterValue* instruction) {
2631c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  // Nothing to do, the parameter is already at its location.
2632c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  UNUSED(instruction);
26336d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru}
2634c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
2635c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queruvoid LocationsBuilderARM::VisitNot(HNot* not_) {
2636c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  LocationSummary* locations =
2637c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      new (GetGraph()->GetArena()) LocationSummary(not_, LocationSummary::kNoCall);
2638c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  locations->SetInAt(0, Location::RequiresRegister());
2639c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
2640c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
2641c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
2642c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queruvoid InstructionCodeGeneratorARM::VisitNot(HNot* not_) {
2643c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  LocationSummary* locations = not_->GetLocations();
2644c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  Location out = locations->Out();
2645c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  Location in = locations->InAt(0);
2646c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  switch (not_->GetResultType()) {
2647c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    case Primitive::kPrimInt:
26486d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru      __ mvn(out.AsRegister<Register>(), ShifterOperand(in.AsRegister<Register>()));
2649c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      break;
2650c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
2651c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    case Primitive::kPrimLong:
26526d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru      __ mvn(out.AsRegisterPairLow<Register>(),
2653c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru             ShifterOperand(in.AsRegisterPairLow<Register>()));
2654c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      __ mvn(out.AsRegisterPairHigh<Register>(),
2655c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru             ShifterOperand(in.AsRegisterPairHigh<Register>()));
26566d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru      break;
2657c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
2658c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    default:
2659c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      LOG(FATAL) << "Unimplemented type for not operation " << not_->GetResultType();
2660c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  }
266150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho}
266250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
266350294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehovoid LocationsBuilderARM::VisitCompare(HCompare* compare) {
266450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho  LocationSummary* locations =
266550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho      new (GetGraph()->GetArena()) LocationSummary(compare, LocationSummary::kNoCall);
266650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho  switch (compare->InputAt(0)->GetType()) {
266750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    case Primitive::kPrimLong: {
266850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho      locations->SetInAt(0, Location::RequiresRegister());
266950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho      locations->SetInAt(1, Location::RequiresRegister());
267050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho      // Output overlaps because it is written before doing the low comparison.
267150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho      locations->SetOut(Location::RequiresRegister(), Location::kOutputOverlap);
267250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho      break;
267350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    }
267450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    case Primitive::kPrimFloat:
2675f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    case Primitive::kPrimDouble: {
2676f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius      locations->SetInAt(0, Location::RequiresFpuRegister());
2677f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius      locations->SetInAt(1, Location::RequiresFpuRegister());
2678f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius      locations->SetOut(Location::RequiresRegister());
2679f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius      break;
2680f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    }
2681f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    default:
2682f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius      LOG(FATAL) << "Unexpected type for compare operation " << compare->InputAt(0)->GetType();
2683f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius  }
2684f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius}
2685f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
2686f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusvoid InstructionCodeGeneratorARM::VisitCompare(HCompare* compare) {
26871b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert  LocationSummary* locations = compare->GetLocations();
26881b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert  Register out = locations->Out().AsRegister<Register>();
26891b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert  Location left = locations->InAt(0);
26901b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert  Location right = locations->InAt(1);
26911b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
26921b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert  Label less, greater, done;
26931b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert  Primitive::Type type = compare->InputAt(0)->GetType();
26941b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert  switch (type) {
26951b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    case Primitive::kPrimLong: {
26961b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      __ cmp(left.AsRegisterPairHigh<Register>(),
26971b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert             ShifterOperand(right.AsRegisterPairHigh<Register>()));  // Signed compare.
26981b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      __ b(&less, LT);
26991b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      __ b(&greater, GT);
27001b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert      // Do LoadImmediate before any `cmp`, as LoadImmediate might affect the status flags.
2701      __ LoadImmediate(out, 0);
2702      __ cmp(left.AsRegisterPairLow<Register>(),
2703             ShifterOperand(right.AsRegisterPairLow<Register>()));  // Unsigned compare.
2704      break;
2705    }
2706    case Primitive::kPrimFloat:
2707    case Primitive::kPrimDouble: {
2708      __ LoadImmediate(out, 0);
2709      if (type == Primitive::kPrimFloat) {
2710        __ vcmps(left.AsFpuRegister<SRegister>(), right.AsFpuRegister<SRegister>());
2711      } else {
2712        __ vcmpd(FromLowSToD(left.AsFpuRegisterPairLow<SRegister>()),
2713                 FromLowSToD(right.AsFpuRegisterPairLow<SRegister>()));
2714      }
2715      __ vmstat();  // transfer FP status register to ARM APSR.
2716      __ b(compare->IsGtBias() ? &greater : &less, VS);  // VS for unordered.
2717      break;
2718    }
2719    default:
2720      LOG(FATAL) << "Unexpected compare type " << type;
2721  }
2722  __ b(&done, EQ);
2723  __ b(&less, CC);  // CC is for both: unsigned compare for longs and 'less than' for floats.
2724
2725  __ Bind(&greater);
2726  __ LoadImmediate(out, 1);
2727  __ b(&done);
2728
2729  __ Bind(&less);
2730  __ LoadImmediate(out, -1);
2731
2732  __ Bind(&done);
2733}
2734
2735void LocationsBuilderARM::VisitPhi(HPhi* instruction) {
2736  LocationSummary* locations =
2737      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
2738  for (size_t i = 0, e = instruction->InputCount(); i < e; ++i) {
2739    locations->SetInAt(i, Location::Any());
2740  }
2741  locations->SetOut(Location::Any());
2742}
2743
2744void InstructionCodeGeneratorARM::VisitPhi(HPhi* instruction) {
2745  UNUSED(instruction);
2746  LOG(FATAL) << "Unreachable";
2747}
2748
2749void InstructionCodeGeneratorARM::GenerateMemoryBarrier(MemBarrierKind kind) {
2750  // TODO (ported from quick): revisit Arm barrier kinds
2751  DmbOptions flavour = DmbOptions::ISH;  // quiet c++ warnings
2752  switch (kind) {
2753    case MemBarrierKind::kAnyStore:
2754    case MemBarrierKind::kLoadAny:
2755    case MemBarrierKind::kAnyAny: {
2756      flavour = DmbOptions::ISH;
2757      break;
2758    }
2759    case MemBarrierKind::kStoreStore: {
2760      flavour = DmbOptions::ISHST;
2761      break;
2762    }
2763    default:
2764      LOG(FATAL) << "Unexpected memory barrier " << kind;
2765  }
2766  __ dmb(flavour);
2767}
2768
2769void InstructionCodeGeneratorARM::GenerateWideAtomicLoad(Register addr,
2770                                                         uint32_t offset,
2771                                                         Register out_lo,
2772                                                         Register out_hi) {
2773  if (offset != 0) {
2774    __ LoadImmediate(out_lo, offset);
2775    __ add(IP, addr, ShifterOperand(out_lo));
2776    addr = IP;
2777  }
2778  __ ldrexd(out_lo, out_hi, addr);
2779}
2780
2781void InstructionCodeGeneratorARM::GenerateWideAtomicStore(Register addr,
2782                                                          uint32_t offset,
2783                                                          Register value_lo,
2784                                                          Register value_hi,
2785                                                          Register temp1,
2786                                                          Register temp2,
2787                                                          HInstruction* instruction) {
2788  Label fail;
2789  if (offset != 0) {
2790    __ LoadImmediate(temp1, offset);
2791    __ add(IP, addr, ShifterOperand(temp1));
2792    addr = IP;
2793  }
2794  __ Bind(&fail);
2795  // We need a load followed by store. (The address used in a STREX instruction must
2796  // be the same as the address in the most recently executed LDREX instruction.)
2797  __ ldrexd(temp1, temp2, addr);
2798  codegen_->MaybeRecordImplicitNullCheck(instruction);
2799  __ strexd(temp1, value_lo, value_hi, addr);
2800  __ cmp(temp1, ShifterOperand(0));
2801  __ b(&fail, NE);
2802}
2803
2804void LocationsBuilderARM::HandleFieldSet(HInstruction* instruction, const FieldInfo& field_info) {
2805  DCHECK(instruction->IsInstanceFieldSet() || instruction->IsStaticFieldSet());
2806
2807  LocationSummary* locations =
2808      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
2809  locations->SetInAt(0, Location::RequiresRegister());
2810  locations->SetInAt(1, Location::RequiresRegister());
2811
2812
2813  Primitive::Type field_type = field_info.GetFieldType();
2814  bool is_wide = field_type == Primitive::kPrimLong || field_type == Primitive::kPrimDouble;
2815  bool generate_volatile = field_info.IsVolatile()
2816      && is_wide
2817      && !codegen_->GetInstructionSetFeatures().HasAtomicLdrdAndStrd();
2818  // Temporary registers for the write barrier.
2819  // TODO: consider renaming StoreNeedsWriteBarrier to StoreNeedsGCMark.
2820  if (CodeGenerator::StoreNeedsWriteBarrier(field_type, instruction->InputAt(1))) {
2821    locations->AddTemp(Location::RequiresRegister());
2822    locations->AddTemp(Location::RequiresRegister());
2823  } else if (generate_volatile) {
2824    // Arm encoding have some additional constraints for ldrexd/strexd:
2825    // - registers need to be consecutive
2826    // - the first register should be even but not R14.
2827    // We don't test for Arm yet, and the assertion makes sure that we revisit this if we ever
2828    // enable Arm encoding.
2829    DCHECK_EQ(InstructionSet::kThumb2, codegen_->GetInstructionSet());
2830
2831    locations->AddTemp(Location::RequiresRegister());
2832    locations->AddTemp(Location::RequiresRegister());
2833    if (field_type == Primitive::kPrimDouble) {
2834      // For doubles we need two more registers to copy the value.
2835      locations->AddTemp(Location::RegisterLocation(R2));
2836      locations->AddTemp(Location::RegisterLocation(R3));
2837    }
2838  }
2839}
2840
2841void InstructionCodeGeneratorARM::HandleFieldSet(HInstruction* instruction,
2842                                                 const FieldInfo& field_info) {
2843  DCHECK(instruction->IsInstanceFieldSet() || instruction->IsStaticFieldSet());
2844
2845  LocationSummary* locations = instruction->GetLocations();
2846  Register base = locations->InAt(0).AsRegister<Register>();
2847  Location value = locations->InAt(1);
2848
2849  bool is_volatile = field_info.IsVolatile();
2850  bool atomic_ldrd_strd = codegen_->GetInstructionSetFeatures().HasAtomicLdrdAndStrd();
2851  Primitive::Type field_type = field_info.GetFieldType();
2852  uint32_t offset = field_info.GetFieldOffset().Uint32Value();
2853
2854  if (is_volatile) {
2855    GenerateMemoryBarrier(MemBarrierKind::kAnyStore);
2856  }
2857
2858  switch (field_type) {
2859    case Primitive::kPrimBoolean:
2860    case Primitive::kPrimByte: {
2861      __ StoreToOffset(kStoreByte, value.AsRegister<Register>(), base, offset);
2862      break;
2863    }
2864
2865    case Primitive::kPrimShort:
2866    case Primitive::kPrimChar: {
2867      __ StoreToOffset(kStoreHalfword, value.AsRegister<Register>(), base, offset);
2868      break;
2869    }
2870
2871    case Primitive::kPrimInt:
2872    case Primitive::kPrimNot: {
2873      __ StoreToOffset(kStoreWord, value.AsRegister<Register>(), base, offset);
2874      break;
2875    }
2876
2877    case Primitive::kPrimLong: {
2878      if (is_volatile && !atomic_ldrd_strd) {
2879        GenerateWideAtomicStore(base, offset,
2880                                value.AsRegisterPairLow<Register>(),
2881                                value.AsRegisterPairHigh<Register>(),
2882                                locations->GetTemp(0).AsRegister<Register>(),
2883                                locations->GetTemp(1).AsRegister<Register>(),
2884                                instruction);
2885      } else {
2886        __ StoreToOffset(kStoreWordPair, value.AsRegisterPairLow<Register>(), base, offset);
2887        codegen_->MaybeRecordImplicitNullCheck(instruction);
2888      }
2889      break;
2890    }
2891
2892    case Primitive::kPrimFloat: {
2893      __ StoreSToOffset(value.AsFpuRegister<SRegister>(), base, offset);
2894      break;
2895    }
2896
2897    case Primitive::kPrimDouble: {
2898      DRegister value_reg = FromLowSToD(value.AsFpuRegisterPairLow<SRegister>());
2899      if (is_volatile && !atomic_ldrd_strd) {
2900        Register value_reg_lo = locations->GetTemp(0).AsRegister<Register>();
2901        Register value_reg_hi = locations->GetTemp(1).AsRegister<Register>();
2902
2903        __ vmovrrd(value_reg_lo, value_reg_hi, value_reg);
2904
2905        GenerateWideAtomicStore(base, offset,
2906                                value_reg_lo,
2907                                value_reg_hi,
2908                                locations->GetTemp(2).AsRegister<Register>(),
2909                                locations->GetTemp(3).AsRegister<Register>(),
2910                                instruction);
2911      } else {
2912        __ StoreDToOffset(value_reg, base, offset);
2913        codegen_->MaybeRecordImplicitNullCheck(instruction);
2914      }
2915      break;
2916    }
2917
2918    case Primitive::kPrimVoid:
2919      LOG(FATAL) << "Unreachable type " << field_type;
2920      UNREACHABLE();
2921  }
2922
2923  // Longs and doubles are handled in the switch.
2924  if (field_type != Primitive::kPrimLong && field_type != Primitive::kPrimDouble) {
2925    codegen_->MaybeRecordImplicitNullCheck(instruction);
2926  }
2927
2928  if (CodeGenerator::StoreNeedsWriteBarrier(field_type, instruction->InputAt(1))) {
2929    Register temp = locations->GetTemp(0).AsRegister<Register>();
2930    Register card = locations->GetTemp(1).AsRegister<Register>();
2931    codegen_->MarkGCCard(temp, card, base, value.AsRegister<Register>());
2932  }
2933
2934  if (is_volatile) {
2935    GenerateMemoryBarrier(MemBarrierKind::kAnyAny);
2936  }
2937}
2938
2939void LocationsBuilderARM::HandleFieldGet(HInstruction* instruction, const FieldInfo& field_info) {
2940  DCHECK(instruction->IsInstanceFieldGet() || instruction->IsStaticFieldGet());
2941  LocationSummary* locations =
2942      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
2943  locations->SetInAt(0, Location::RequiresRegister());
2944
2945  bool volatile_for_double = field_info.IsVolatile()
2946      && (field_info.GetFieldType() == Primitive::kPrimDouble)
2947      && !codegen_->GetInstructionSetFeatures().HasAtomicLdrdAndStrd();
2948  bool overlap = field_info.IsVolatile() && (field_info.GetFieldType() == Primitive::kPrimLong);
2949  locations->SetOut(Location::RequiresRegister(),
2950                    (overlap ? Location::kOutputOverlap : Location::kNoOutputOverlap));
2951  if (volatile_for_double) {
2952    // Arm encoding have some additional constraints for ldrexd/strexd:
2953    // - registers need to be consecutive
2954    // - the first register should be even but not R14.
2955    // We don't test for Arm yet, and the assertion makes sure that we revisit this if we ever
2956    // enable Arm encoding.
2957    DCHECK_EQ(InstructionSet::kThumb2, codegen_->GetInstructionSet());
2958    locations->AddTemp(Location::RequiresRegister());
2959    locations->AddTemp(Location::RequiresRegister());
2960  }
2961}
2962
2963void InstructionCodeGeneratorARM::HandleFieldGet(HInstruction* instruction,
2964                                                 const FieldInfo& field_info) {
2965  DCHECK(instruction->IsInstanceFieldGet() || instruction->IsStaticFieldGet());
2966
2967  LocationSummary* locations = instruction->GetLocations();
2968  Register base = locations->InAt(0).AsRegister<Register>();
2969  Location out = locations->Out();
2970  bool is_volatile = field_info.IsVolatile();
2971  bool atomic_ldrd_strd = codegen_->GetInstructionSetFeatures().HasAtomicLdrdAndStrd();
2972  Primitive::Type field_type = field_info.GetFieldType();
2973  uint32_t offset = field_info.GetFieldOffset().Uint32Value();
2974
2975  switch (field_type) {
2976    case Primitive::kPrimBoolean: {
2977      __ LoadFromOffset(kLoadUnsignedByte, out.AsRegister<Register>(), base, offset);
2978      break;
2979    }
2980
2981    case Primitive::kPrimByte: {
2982      __ LoadFromOffset(kLoadSignedByte, out.AsRegister<Register>(), base, offset);
2983      break;
2984    }
2985
2986    case Primitive::kPrimShort: {
2987      __ LoadFromOffset(kLoadSignedHalfword, out.AsRegister<Register>(), base, offset);
2988      break;
2989    }
2990
2991    case Primitive::kPrimChar: {
2992      __ LoadFromOffset(kLoadUnsignedHalfword, out.AsRegister<Register>(), base, offset);
2993      break;
2994    }
2995
2996    case Primitive::kPrimInt:
2997    case Primitive::kPrimNot: {
2998      __ LoadFromOffset(kLoadWord, out.AsRegister<Register>(), base, offset);
2999      break;
3000    }
3001
3002    case Primitive::kPrimLong: {
3003      if (is_volatile && !atomic_ldrd_strd) {
3004        GenerateWideAtomicLoad(base, offset,
3005                               out.AsRegisterPairLow<Register>(),
3006                               out.AsRegisterPairHigh<Register>());
3007      } else {
3008        __ LoadFromOffset(kLoadWordPair, out.AsRegisterPairLow<Register>(), base, offset);
3009      }
3010      break;
3011    }
3012
3013    case Primitive::kPrimFloat: {
3014      __ LoadSFromOffset(out.AsFpuRegister<SRegister>(), base, offset);
3015      break;
3016    }
3017
3018    case Primitive::kPrimDouble: {
3019      DRegister out_reg = FromLowSToD(out.AsFpuRegisterPairLow<SRegister>());
3020      if (is_volatile && !atomic_ldrd_strd) {
3021        Register lo = locations->GetTemp(0).AsRegister<Register>();
3022        Register hi = locations->GetTemp(1).AsRegister<Register>();
3023        GenerateWideAtomicLoad(base, offset, lo, hi);
3024        codegen_->MaybeRecordImplicitNullCheck(instruction);
3025        __ vmovdrr(out_reg, lo, hi);
3026      } else {
3027        __ LoadDFromOffset(out_reg, base, offset);
3028        codegen_->MaybeRecordImplicitNullCheck(instruction);
3029      }
3030      break;
3031    }
3032
3033    case Primitive::kPrimVoid:
3034      LOG(FATAL) << "Unreachable type " << field_type;
3035      UNREACHABLE();
3036  }
3037
3038  // Doubles are handled in the switch.
3039  if (field_type != Primitive::kPrimDouble) {
3040    codegen_->MaybeRecordImplicitNullCheck(instruction);
3041  }
3042
3043  if (is_volatile) {
3044    GenerateMemoryBarrier(MemBarrierKind::kLoadAny);
3045  }
3046}
3047
3048void LocationsBuilderARM::VisitInstanceFieldSet(HInstanceFieldSet* instruction) {
3049  HandleFieldSet(instruction, instruction->GetFieldInfo());
3050}
3051
3052void InstructionCodeGeneratorARM::VisitInstanceFieldSet(HInstanceFieldSet* instruction) {
3053  HandleFieldSet(instruction, instruction->GetFieldInfo());
3054}
3055
3056void LocationsBuilderARM::VisitInstanceFieldGet(HInstanceFieldGet* instruction) {
3057  HandleFieldGet(instruction, instruction->GetFieldInfo());
3058}
3059
3060void InstructionCodeGeneratorARM::VisitInstanceFieldGet(HInstanceFieldGet* instruction) {
3061  HandleFieldGet(instruction, instruction->GetFieldInfo());
3062}
3063
3064void LocationsBuilderARM::VisitStaticFieldGet(HStaticFieldGet* instruction) {
3065  HandleFieldGet(instruction, instruction->GetFieldInfo());
3066}
3067
3068void InstructionCodeGeneratorARM::VisitStaticFieldGet(HStaticFieldGet* instruction) {
3069  HandleFieldGet(instruction, instruction->GetFieldInfo());
3070}
3071
3072void LocationsBuilderARM::VisitStaticFieldSet(HStaticFieldSet* instruction) {
3073  HandleFieldSet(instruction, instruction->GetFieldInfo());
3074}
3075
3076void InstructionCodeGeneratorARM::VisitStaticFieldSet(HStaticFieldSet* instruction) {
3077  HandleFieldSet(instruction, instruction->GetFieldInfo());
3078}
3079
3080void LocationsBuilderARM::VisitNullCheck(HNullCheck* instruction) {
3081  LocationSummary* locations =
3082      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
3083  locations->SetInAt(0, Location::RequiresRegister());
3084  if (instruction->HasUses()) {
3085    locations->SetOut(Location::SameAsFirstInput());
3086  }
3087}
3088
3089void InstructionCodeGeneratorARM::GenerateImplicitNullCheck(HNullCheck* instruction) {
3090  if (codegen_->CanMoveNullCheckToUser(instruction)) {
3091    return;
3092  }
3093  Location obj = instruction->GetLocations()->InAt(0);
3094
3095  __ LoadFromOffset(kLoadWord, IP, obj.AsRegister<Register>(), 0);
3096  codegen_->RecordPcInfo(instruction, instruction->GetDexPc());
3097}
3098
3099void InstructionCodeGeneratorARM::GenerateExplicitNullCheck(HNullCheck* instruction) {
3100  SlowPathCodeARM* slow_path = new (GetGraph()->GetArena()) NullCheckSlowPathARM(instruction);
3101  codegen_->AddSlowPath(slow_path);
3102
3103  LocationSummary* locations = instruction->GetLocations();
3104  Location obj = locations->InAt(0);
3105
3106  __ cmp(obj.AsRegister<Register>(), ShifterOperand(0));
3107  __ b(slow_path->GetEntryLabel(), EQ);
3108}
3109
3110void InstructionCodeGeneratorARM::VisitNullCheck(HNullCheck* instruction) {
3111  if (codegen_->GetCompilerOptions().GetImplicitNullChecks()) {
3112    GenerateImplicitNullCheck(instruction);
3113  } else {
3114    GenerateExplicitNullCheck(instruction);
3115  }
3116}
3117
3118void LocationsBuilderARM::VisitArrayGet(HArrayGet* instruction) {
3119  LocationSummary* locations =
3120      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
3121  locations->SetInAt(0, Location::RequiresRegister());
3122  locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1)));
3123  locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
3124}
3125
3126void InstructionCodeGeneratorARM::VisitArrayGet(HArrayGet* instruction) {
3127  LocationSummary* locations = instruction->GetLocations();
3128  Register obj = locations->InAt(0).AsRegister<Register>();
3129  Location index = locations->InAt(1);
3130
3131  switch (instruction->GetType()) {
3132    case Primitive::kPrimBoolean: {
3133      uint32_t data_offset = mirror::Array::DataOffset(sizeof(uint8_t)).Uint32Value();
3134      Register out = locations->Out().AsRegister<Register>();
3135      if (index.IsConstant()) {
3136        size_t offset =
3137            (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_1) + data_offset;
3138        __ LoadFromOffset(kLoadUnsignedByte, out, obj, offset);
3139      } else {
3140        __ add(IP, obj, ShifterOperand(index.AsRegister<Register>()));
3141        __ LoadFromOffset(kLoadUnsignedByte, out, IP, data_offset);
3142      }
3143      break;
3144    }
3145
3146    case Primitive::kPrimByte: {
3147      uint32_t data_offset = mirror::Array::DataOffset(sizeof(int8_t)).Uint32Value();
3148      Register out = locations->Out().AsRegister<Register>();
3149      if (index.IsConstant()) {
3150        size_t offset =
3151            (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_1) + data_offset;
3152        __ LoadFromOffset(kLoadSignedByte, out, obj, offset);
3153      } else {
3154        __ add(IP, obj, ShifterOperand(index.AsRegister<Register>()));
3155        __ LoadFromOffset(kLoadSignedByte, out, IP, data_offset);
3156      }
3157      break;
3158    }
3159
3160    case Primitive::kPrimShort: {
3161      uint32_t data_offset = mirror::Array::DataOffset(sizeof(int16_t)).Uint32Value();
3162      Register out = locations->Out().AsRegister<Register>();
3163      if (index.IsConstant()) {
3164        size_t offset =
3165            (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_2) + data_offset;
3166        __ LoadFromOffset(kLoadSignedHalfword, out, obj, offset);
3167      } else {
3168        __ add(IP, obj, ShifterOperand(index.AsRegister<Register>(), LSL, TIMES_2));
3169        __ LoadFromOffset(kLoadSignedHalfword, out, IP, data_offset);
3170      }
3171      break;
3172    }
3173
3174    case Primitive::kPrimChar: {
3175      uint32_t data_offset = mirror::Array::DataOffset(sizeof(uint16_t)).Uint32Value();
3176      Register out = locations->Out().AsRegister<Register>();
3177      if (index.IsConstant()) {
3178        size_t offset =
3179            (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_2) + data_offset;
3180        __ LoadFromOffset(kLoadUnsignedHalfword, out, obj, offset);
3181      } else {
3182        __ add(IP, obj, ShifterOperand(index.AsRegister<Register>(), LSL, TIMES_2));
3183        __ LoadFromOffset(kLoadUnsignedHalfword, out, IP, data_offset);
3184      }
3185      break;
3186    }
3187
3188    case Primitive::kPrimInt:
3189    case Primitive::kPrimNot: {
3190      DCHECK_EQ(sizeof(mirror::HeapReference<mirror::Object>), sizeof(int32_t));
3191      uint32_t data_offset = mirror::Array::DataOffset(sizeof(int32_t)).Uint32Value();
3192      Register out = locations->Out().AsRegister<Register>();
3193      if (index.IsConstant()) {
3194        size_t offset =
3195            (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_4) + data_offset;
3196        __ LoadFromOffset(kLoadWord, out, obj, offset);
3197      } else {
3198        __ add(IP, obj, ShifterOperand(index.AsRegister<Register>(), LSL, TIMES_4));
3199        __ LoadFromOffset(kLoadWord, out, IP, data_offset);
3200      }
3201      break;
3202    }
3203
3204    case Primitive::kPrimLong: {
3205      uint32_t data_offset = mirror::Array::DataOffset(sizeof(int64_t)).Uint32Value();
3206      Location out = locations->Out();
3207      if (index.IsConstant()) {
3208        size_t offset =
3209            (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_8) + data_offset;
3210        __ LoadFromOffset(kLoadWordPair, out.AsRegisterPairLow<Register>(), obj, offset);
3211      } else {
3212        __ add(IP, obj, ShifterOperand(index.AsRegister<Register>(), LSL, TIMES_8));
3213        __ LoadFromOffset(kLoadWordPair, out.AsRegisterPairLow<Register>(), IP, data_offset);
3214      }
3215      break;
3216    }
3217
3218    case Primitive::kPrimFloat: {
3219      uint32_t data_offset = mirror::Array::DataOffset(sizeof(float)).Uint32Value();
3220      Location out = locations->Out();
3221      DCHECK(out.IsFpuRegister());
3222      if (index.IsConstant()) {
3223        size_t offset = (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_4) + data_offset;
3224        __ LoadSFromOffset(out.AsFpuRegister<SRegister>(), obj, offset);
3225      } else {
3226        __ add(IP, obj, ShifterOperand(index.AsRegister<Register>(), LSL, TIMES_4));
3227        __ LoadSFromOffset(out.AsFpuRegister<SRegister>(), IP, data_offset);
3228      }
3229      break;
3230    }
3231
3232    case Primitive::kPrimDouble: {
3233      uint32_t data_offset = mirror::Array::DataOffset(sizeof(double)).Uint32Value();
3234      Location out = locations->Out();
3235      DCHECK(out.IsFpuRegisterPair());
3236      if (index.IsConstant()) {
3237        size_t offset = (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_8) + data_offset;
3238        __ LoadDFromOffset(FromLowSToD(out.AsFpuRegisterPairLow<SRegister>()), obj, offset);
3239      } else {
3240        __ add(IP, obj, ShifterOperand(index.AsRegister<Register>(), LSL, TIMES_8));
3241        __ LoadDFromOffset(FromLowSToD(out.AsFpuRegisterPairLow<SRegister>()), IP, data_offset);
3242      }
3243      break;
3244    }
3245
3246    case Primitive::kPrimVoid:
3247      LOG(FATAL) << "Unreachable type " << instruction->GetType();
3248      UNREACHABLE();
3249  }
3250  codegen_->MaybeRecordImplicitNullCheck(instruction);
3251}
3252
3253void LocationsBuilderARM::VisitArraySet(HArraySet* instruction) {
3254  Primitive::Type value_type = instruction->GetComponentType();
3255
3256  bool needs_write_barrier =
3257      CodeGenerator::StoreNeedsWriteBarrier(value_type, instruction->GetValue());
3258  bool needs_runtime_call = instruction->NeedsTypeCheck();
3259
3260  LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(
3261      instruction, needs_runtime_call ? LocationSummary::kCall : LocationSummary::kNoCall);
3262  if (needs_runtime_call) {
3263    InvokeRuntimeCallingConvention calling_convention;
3264    locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0)));
3265    locations->SetInAt(1, Location::RegisterLocation(calling_convention.GetRegisterAt(1)));
3266    locations->SetInAt(2, Location::RegisterLocation(calling_convention.GetRegisterAt(2)));
3267  } else {
3268    locations->SetInAt(0, Location::RequiresRegister());
3269    locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1)));
3270    locations->SetInAt(2, Location::RequiresRegister());
3271
3272    if (needs_write_barrier) {
3273      // Temporary registers for the write barrier.
3274      locations->AddTemp(Location::RequiresRegister());
3275      locations->AddTemp(Location::RequiresRegister());
3276    }
3277  }
3278}
3279
3280void InstructionCodeGeneratorARM::VisitArraySet(HArraySet* instruction) {
3281  LocationSummary* locations = instruction->GetLocations();
3282  Register obj = locations->InAt(0).AsRegister<Register>();
3283  Location index = locations->InAt(1);
3284  Primitive::Type value_type = instruction->GetComponentType();
3285  bool needs_runtime_call = locations->WillCall();
3286  bool needs_write_barrier =
3287      CodeGenerator::StoreNeedsWriteBarrier(value_type, instruction->GetValue());
3288
3289  switch (value_type) {
3290    case Primitive::kPrimBoolean:
3291    case Primitive::kPrimByte: {
3292      uint32_t data_offset = mirror::Array::DataOffset(sizeof(uint8_t)).Uint32Value();
3293      Register value = locations->InAt(2).AsRegister<Register>();
3294      if (index.IsConstant()) {
3295        size_t offset =
3296            (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_1) + data_offset;
3297        __ StoreToOffset(kStoreByte, value, obj, offset);
3298      } else {
3299        __ add(IP, obj, ShifterOperand(index.AsRegister<Register>()));
3300        __ StoreToOffset(kStoreByte, value, IP, data_offset);
3301      }
3302      break;
3303    }
3304
3305    case Primitive::kPrimShort:
3306    case Primitive::kPrimChar: {
3307      uint32_t data_offset = mirror::Array::DataOffset(sizeof(uint16_t)).Uint32Value();
3308      Register value = locations->InAt(2).AsRegister<Register>();
3309      if (index.IsConstant()) {
3310        size_t offset =
3311            (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_2) + data_offset;
3312        __ StoreToOffset(kStoreHalfword, value, obj, offset);
3313      } else {
3314        __ add(IP, obj, ShifterOperand(index.AsRegister<Register>(), LSL, TIMES_2));
3315        __ StoreToOffset(kStoreHalfword, value, IP, data_offset);
3316      }
3317      break;
3318    }
3319
3320    case Primitive::kPrimInt:
3321    case Primitive::kPrimNot: {
3322      if (!needs_runtime_call) {
3323        uint32_t data_offset = mirror::Array::DataOffset(sizeof(int32_t)).Uint32Value();
3324        Register value = locations->InAt(2).AsRegister<Register>();
3325        if (index.IsConstant()) {
3326          size_t offset =
3327              (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_4) + data_offset;
3328          __ StoreToOffset(kStoreWord, value, obj, offset);
3329        } else {
3330          DCHECK(index.IsRegister()) << index;
3331          __ add(IP, obj, ShifterOperand(index.AsRegister<Register>(), LSL, TIMES_4));
3332          __ StoreToOffset(kStoreWord, value, IP, data_offset);
3333        }
3334        codegen_->MaybeRecordImplicitNullCheck(instruction);
3335        if (needs_write_barrier) {
3336          DCHECK_EQ(value_type, Primitive::kPrimNot);
3337          Register temp = locations->GetTemp(0).AsRegister<Register>();
3338          Register card = locations->GetTemp(1).AsRegister<Register>();
3339          codegen_->MarkGCCard(temp, card, obj, value);
3340        }
3341      } else {
3342        DCHECK_EQ(value_type, Primitive::kPrimNot);
3343        codegen_->InvokeRuntime(QUICK_ENTRY_POINT(pAputObject),
3344                                instruction,
3345                                instruction->GetDexPc(),
3346                                nullptr);
3347      }
3348      break;
3349    }
3350
3351    case Primitive::kPrimLong: {
3352      uint32_t data_offset = mirror::Array::DataOffset(sizeof(int64_t)).Uint32Value();
3353      Location value = locations->InAt(2);
3354      if (index.IsConstant()) {
3355        size_t offset =
3356            (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_8) + data_offset;
3357        __ StoreToOffset(kStoreWordPair, value.AsRegisterPairLow<Register>(), obj, offset);
3358      } else {
3359        __ add(IP, obj, ShifterOperand(index.AsRegister<Register>(), LSL, TIMES_8));
3360        __ StoreToOffset(kStoreWordPair, value.AsRegisterPairLow<Register>(), IP, data_offset);
3361      }
3362      break;
3363    }
3364
3365    case Primitive::kPrimFloat: {
3366      uint32_t data_offset = mirror::Array::DataOffset(sizeof(float)).Uint32Value();
3367      Location value = locations->InAt(2);
3368      DCHECK(value.IsFpuRegister());
3369      if (index.IsConstant()) {
3370        size_t offset = (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_4) + data_offset;
3371        __ StoreSToOffset(value.AsFpuRegister<SRegister>(), obj, offset);
3372      } else {
3373        __ add(IP, obj, ShifterOperand(index.AsRegister<Register>(), LSL, TIMES_4));
3374        __ StoreSToOffset(value.AsFpuRegister<SRegister>(), IP, data_offset);
3375      }
3376      break;
3377    }
3378
3379    case Primitive::kPrimDouble: {
3380      uint32_t data_offset = mirror::Array::DataOffset(sizeof(double)).Uint32Value();
3381      Location value = locations->InAt(2);
3382      DCHECK(value.IsFpuRegisterPair());
3383      if (index.IsConstant()) {
3384        size_t offset = (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_8) + data_offset;
3385        __ StoreDToOffset(FromLowSToD(value.AsFpuRegisterPairLow<SRegister>()), obj, offset);
3386      } else {
3387        __ add(IP, obj, ShifterOperand(index.AsRegister<Register>(), LSL, TIMES_8));
3388        __ StoreDToOffset(FromLowSToD(value.AsFpuRegisterPairLow<SRegister>()), IP, data_offset);
3389      }
3390
3391      break;
3392    }
3393
3394    case Primitive::kPrimVoid:
3395      LOG(FATAL) << "Unreachable type " << value_type;
3396      UNREACHABLE();
3397  }
3398
3399  // Ints and objects are handled in the switch.
3400  if (value_type != Primitive::kPrimInt && value_type != Primitive::kPrimNot) {
3401    codegen_->MaybeRecordImplicitNullCheck(instruction);
3402  }
3403}
3404
3405void LocationsBuilderARM::VisitArrayLength(HArrayLength* instruction) {
3406  LocationSummary* locations =
3407      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
3408  locations->SetInAt(0, Location::RequiresRegister());
3409  locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
3410}
3411
3412void InstructionCodeGeneratorARM::VisitArrayLength(HArrayLength* instruction) {
3413  LocationSummary* locations = instruction->GetLocations();
3414  uint32_t offset = mirror::Array::LengthOffset().Uint32Value();
3415  Register obj = locations->InAt(0).AsRegister<Register>();
3416  Register out = locations->Out().AsRegister<Register>();
3417  __ LoadFromOffset(kLoadWord, out, obj, offset);
3418  codegen_->MaybeRecordImplicitNullCheck(instruction);
3419}
3420
3421void LocationsBuilderARM::VisitBoundsCheck(HBoundsCheck* instruction) {
3422  LocationSummary* locations =
3423      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
3424  locations->SetInAt(0, Location::RequiresRegister());
3425  locations->SetInAt(1, Location::RequiresRegister());
3426  if (instruction->HasUses()) {
3427    locations->SetOut(Location::SameAsFirstInput());
3428  }
3429}
3430
3431void InstructionCodeGeneratorARM::VisitBoundsCheck(HBoundsCheck* instruction) {
3432  LocationSummary* locations = instruction->GetLocations();
3433  SlowPathCodeARM* slow_path = new (GetGraph()->GetArena()) BoundsCheckSlowPathARM(
3434      instruction, locations->InAt(0), locations->InAt(1));
3435  codegen_->AddSlowPath(slow_path);
3436
3437  Register index = locations->InAt(0).AsRegister<Register>();
3438  Register length = locations->InAt(1).AsRegister<Register>();
3439
3440  __ cmp(index, ShifterOperand(length));
3441  __ b(slow_path->GetEntryLabel(), CS);
3442}
3443
3444void CodeGeneratorARM::MarkGCCard(Register temp, Register card, Register object, Register value) {
3445  Label is_null;
3446  __ CompareAndBranchIfZero(value, &is_null);
3447  __ LoadFromOffset(kLoadWord, card, TR, Thread::CardTableOffset<kArmWordSize>().Int32Value());
3448  __ Lsr(temp, object, gc::accounting::CardTable::kCardShift);
3449  __ strb(card, Address(card, temp));
3450  __ Bind(&is_null);
3451}
3452
3453void LocationsBuilderARM::VisitTemporary(HTemporary* temp) {
3454  temp->SetLocations(nullptr);
3455}
3456
3457void InstructionCodeGeneratorARM::VisitTemporary(HTemporary* temp) {
3458  // Nothing to do, this is driven by the code generator.
3459  UNUSED(temp);
3460}
3461
3462void LocationsBuilderARM::VisitParallelMove(HParallelMove* instruction) {
3463  UNUSED(instruction);
3464  LOG(FATAL) << "Unreachable";
3465}
3466
3467void InstructionCodeGeneratorARM::VisitParallelMove(HParallelMove* instruction) {
3468  codegen_->GetMoveResolver()->EmitNativeCode(instruction);
3469}
3470
3471void LocationsBuilderARM::VisitSuspendCheck(HSuspendCheck* instruction) {
3472  new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCallOnSlowPath);
3473}
3474
3475void InstructionCodeGeneratorARM::VisitSuspendCheck(HSuspendCheck* instruction) {
3476  HBasicBlock* block = instruction->GetBlock();
3477  if (block->GetLoopInformation() != nullptr) {
3478    DCHECK(block->GetLoopInformation()->GetSuspendCheck() == instruction);
3479    // The back edge will generate the suspend check.
3480    return;
3481  }
3482  if (block->IsEntryBlock() && instruction->GetNext()->IsGoto()) {
3483    // The goto will generate the suspend check.
3484    return;
3485  }
3486  GenerateSuspendCheck(instruction, nullptr);
3487}
3488
3489void InstructionCodeGeneratorARM::GenerateSuspendCheck(HSuspendCheck* instruction,
3490                                                       HBasicBlock* successor) {
3491  SuspendCheckSlowPathARM* slow_path =
3492      new (GetGraph()->GetArena()) SuspendCheckSlowPathARM(instruction, successor);
3493  codegen_->AddSlowPath(slow_path);
3494
3495  __ LoadFromOffset(
3496      kLoadUnsignedHalfword, IP, TR, Thread::ThreadFlagsOffset<kArmWordSize>().Int32Value());
3497  __ cmp(IP, ShifterOperand(0));
3498  // TODO: Figure out the branch offsets and use cbz/cbnz.
3499  if (successor == nullptr) {
3500    __ b(slow_path->GetEntryLabel(), NE);
3501    __ Bind(slow_path->GetReturnLabel());
3502  } else {
3503    __ b(codegen_->GetLabelOf(successor), EQ);
3504    __ b(slow_path->GetEntryLabel());
3505  }
3506}
3507
3508ArmAssembler* ParallelMoveResolverARM::GetAssembler() const {
3509  return codegen_->GetAssembler();
3510}
3511
3512void ParallelMoveResolverARM::EmitMove(size_t index) {
3513  MoveOperands* move = moves_.Get(index);
3514  Location source = move->GetSource();
3515  Location destination = move->GetDestination();
3516
3517  if (source.IsRegister()) {
3518    if (destination.IsRegister()) {
3519      __ Mov(destination.AsRegister<Register>(), source.AsRegister<Register>());
3520    } else {
3521      DCHECK(destination.IsStackSlot());
3522      __ StoreToOffset(kStoreWord, source.AsRegister<Register>(),
3523                       SP, destination.GetStackIndex());
3524    }
3525  } else if (source.IsStackSlot()) {
3526    if (destination.IsRegister()) {
3527      __ LoadFromOffset(kLoadWord, destination.AsRegister<Register>(),
3528                        SP, source.GetStackIndex());
3529    } else if (destination.IsFpuRegister()) {
3530      __ LoadSFromOffset(destination.AsFpuRegister<SRegister>(), SP, source.GetStackIndex());
3531    } else {
3532      DCHECK(destination.IsStackSlot());
3533      __ LoadFromOffset(kLoadWord, IP, SP, source.GetStackIndex());
3534      __ StoreToOffset(kStoreWord, IP, SP, destination.GetStackIndex());
3535    }
3536  } else if (source.IsFpuRegister()) {
3537    if (destination.IsFpuRegister()) {
3538      __ vmovs(destination.AsFpuRegister<SRegister>(), source.AsFpuRegister<SRegister>());
3539    } else {
3540      DCHECK(destination.IsStackSlot());
3541      __ StoreSToOffset(source.AsFpuRegister<SRegister>(), SP, destination.GetStackIndex());
3542    }
3543  } else if (source.IsDoubleStackSlot()) {
3544    if (destination.IsDoubleStackSlot()) {
3545      __ LoadDFromOffset(DTMP, SP, source.GetStackIndex());
3546      __ StoreDToOffset(DTMP, SP, destination.GetStackIndex());
3547    } else if (destination.IsRegisterPair()) {
3548      DCHECK(ExpectedPairLayout(destination));
3549      __ LoadFromOffset(
3550          kLoadWordPair, destination.AsRegisterPairLow<Register>(), SP, source.GetStackIndex());
3551    } else {
3552      DCHECK(destination.IsFpuRegisterPair()) << destination;
3553      __ LoadDFromOffset(FromLowSToD(destination.AsFpuRegisterPairLow<SRegister>()),
3554                         SP,
3555                         source.GetStackIndex());
3556    }
3557  } else if (source.IsRegisterPair()) {
3558    if (destination.IsRegisterPair()) {
3559      __ Mov(destination.AsRegisterPairLow<Register>(), source.AsRegisterPairLow<Register>());
3560      __ Mov(destination.AsRegisterPairHigh<Register>(), source.AsRegisterPairHigh<Register>());
3561    } else {
3562      DCHECK(destination.IsDoubleStackSlot()) << destination;
3563      DCHECK(ExpectedPairLayout(source));
3564      __ StoreToOffset(
3565          kStoreWordPair, source.AsRegisterPairLow<Register>(), SP, destination.GetStackIndex());
3566    }
3567  } else if (source.IsFpuRegisterPair()) {
3568    if (destination.IsFpuRegisterPair()) {
3569      __ vmovd(FromLowSToD(destination.AsFpuRegisterPairLow<SRegister>()),
3570               FromLowSToD(source.AsFpuRegisterPairLow<SRegister>()));
3571    } else {
3572      DCHECK(destination.IsDoubleStackSlot()) << destination;
3573      __ StoreDToOffset(FromLowSToD(source.AsFpuRegisterPairLow<SRegister>()),
3574                        SP,
3575                        destination.GetStackIndex());
3576    }
3577  } else {
3578    DCHECK(source.IsConstant()) << source;
3579    HConstant* constant = source.GetConstant();
3580    if (constant->IsIntConstant() || constant->IsNullConstant()) {
3581      int32_t value = CodeGenerator::GetInt32ValueOf(constant);
3582      if (destination.IsRegister()) {
3583        __ LoadImmediate(destination.AsRegister<Register>(), value);
3584      } else {
3585        DCHECK(destination.IsStackSlot());
3586        __ LoadImmediate(IP, value);
3587        __ StoreToOffset(kStoreWord, IP, SP, destination.GetStackIndex());
3588      }
3589    } else if (constant->IsLongConstant()) {
3590      int64_t value = constant->AsLongConstant()->GetValue();
3591      if (destination.IsRegisterPair()) {
3592        __ LoadImmediate(destination.AsRegisterPairLow<Register>(), Low32Bits(value));
3593        __ LoadImmediate(destination.AsRegisterPairHigh<Register>(), High32Bits(value));
3594      } else {
3595        DCHECK(destination.IsDoubleStackSlot()) << destination;
3596        __ LoadImmediate(IP, Low32Bits(value));
3597        __ StoreToOffset(kStoreWord, IP, SP, destination.GetStackIndex());
3598        __ LoadImmediate(IP, High32Bits(value));
3599        __ StoreToOffset(kStoreWord, IP, SP, destination.GetHighStackIndex(kArmWordSize));
3600      }
3601    } else if (constant->IsDoubleConstant()) {
3602      double value = constant->AsDoubleConstant()->GetValue();
3603      if (destination.IsFpuRegisterPair()) {
3604        __ LoadDImmediate(FromLowSToD(destination.AsFpuRegisterPairLow<SRegister>()), value);
3605      } else {
3606        DCHECK(destination.IsDoubleStackSlot()) << destination;
3607        uint64_t int_value = bit_cast<uint64_t, double>(value);
3608        __ LoadImmediate(IP, Low32Bits(int_value));
3609        __ StoreToOffset(kStoreWord, IP, SP, destination.GetStackIndex());
3610        __ LoadImmediate(IP, High32Bits(int_value));
3611        __ StoreToOffset(kStoreWord, IP, SP, destination.GetHighStackIndex(kArmWordSize));
3612      }
3613    } else {
3614      DCHECK(constant->IsFloatConstant()) << constant->DebugName();
3615      float value = constant->AsFloatConstant()->GetValue();
3616      if (destination.IsFpuRegister()) {
3617        __ LoadSImmediate(destination.AsFpuRegister<SRegister>(), value);
3618      } else {
3619        DCHECK(destination.IsStackSlot());
3620        __ LoadImmediate(IP, bit_cast<int32_t, float>(value));
3621        __ StoreToOffset(kStoreWord, IP, SP, destination.GetStackIndex());
3622      }
3623    }
3624  }
3625}
3626
3627void ParallelMoveResolverARM::Exchange(Register reg, int mem) {
3628  __ Mov(IP, reg);
3629  __ LoadFromOffset(kLoadWord, reg, SP, mem);
3630  __ StoreToOffset(kStoreWord, IP, SP, mem);
3631}
3632
3633void ParallelMoveResolverARM::Exchange(int mem1, int mem2) {
3634  ScratchRegisterScope ensure_scratch(this, IP, R0, codegen_->GetNumberOfCoreRegisters());
3635  int stack_offset = ensure_scratch.IsSpilled() ? kArmWordSize : 0;
3636  __ LoadFromOffset(kLoadWord, static_cast<Register>(ensure_scratch.GetRegister()),
3637                    SP, mem1 + stack_offset);
3638  __ LoadFromOffset(kLoadWord, IP, SP, mem2 + stack_offset);
3639  __ StoreToOffset(kStoreWord, static_cast<Register>(ensure_scratch.GetRegister()),
3640                   SP, mem2 + stack_offset);
3641  __ StoreToOffset(kStoreWord, IP, SP, mem1 + stack_offset);
3642}
3643
3644void ParallelMoveResolverARM::EmitSwap(size_t index) {
3645  MoveOperands* move = moves_.Get(index);
3646  Location source = move->GetSource();
3647  Location destination = move->GetDestination();
3648
3649  if (source.IsRegister() && destination.IsRegister()) {
3650    DCHECK_NE(source.AsRegister<Register>(), IP);
3651    DCHECK_NE(destination.AsRegister<Register>(), IP);
3652    __ Mov(IP, source.AsRegister<Register>());
3653    __ Mov(source.AsRegister<Register>(), destination.AsRegister<Register>());
3654    __ Mov(destination.AsRegister<Register>(), IP);
3655  } else if (source.IsRegister() && destination.IsStackSlot()) {
3656    Exchange(source.AsRegister<Register>(), destination.GetStackIndex());
3657  } else if (source.IsStackSlot() && destination.IsRegister()) {
3658    Exchange(destination.AsRegister<Register>(), source.GetStackIndex());
3659  } else if (source.IsStackSlot() && destination.IsStackSlot()) {
3660    Exchange(source.GetStackIndex(), destination.GetStackIndex());
3661  } else if (source.IsFpuRegister() && destination.IsFpuRegister()) {
3662    __ vmovrs(IP, source.AsFpuRegister<SRegister>());
3663    __ vmovs(source.AsFpuRegister<SRegister>(), destination.AsFpuRegister<SRegister>());
3664    __ vmovsr(destination.AsFpuRegister<SRegister>(), IP);
3665  } else if (source.IsRegisterPair() && destination.IsRegisterPair()) {
3666    __ vmovdrr(DTMP, source.AsRegisterPairLow<Register>(), source.AsRegisterPairHigh<Register>());
3667    __ Mov(source.AsRegisterPairLow<Register>(), destination.AsRegisterPairLow<Register>());
3668    __ Mov(source.AsRegisterPairHigh<Register>(), destination.AsRegisterPairHigh<Register>());
3669    __ vmovrrd(destination.AsRegisterPairLow<Register>(),
3670               destination.AsRegisterPairHigh<Register>(),
3671               DTMP);
3672  } else if (source.IsRegisterPair() || destination.IsRegisterPair()) {
3673    Register low_reg = source.IsRegisterPair()
3674        ? source.AsRegisterPairLow<Register>()
3675        : destination.AsRegisterPairLow<Register>();
3676    int mem = source.IsRegisterPair()
3677        ? destination.GetStackIndex()
3678        : source.GetStackIndex();
3679    DCHECK(ExpectedPairLayout(source.IsRegisterPair() ? source : destination));
3680    __ vmovdrr(DTMP, low_reg, static_cast<Register>(low_reg + 1));
3681    __ LoadFromOffset(kLoadWordPair, low_reg, SP, mem);
3682    __ StoreDToOffset(DTMP, SP, mem);
3683  } else if (source.IsFpuRegisterPair() && destination.IsFpuRegisterPair()) {
3684    DRegister first = FromLowSToD(source.AsFpuRegisterPairLow<SRegister>());
3685    DRegister second = FromLowSToD(destination.AsFpuRegisterPairLow<SRegister>());
3686    __ vmovd(DTMP, first);
3687    __ vmovd(first, second);
3688    __ vmovd(second, DTMP);
3689  } else if (source.IsFpuRegisterPair() || destination.IsFpuRegisterPair()) {
3690    DRegister reg = source.IsFpuRegisterPair()
3691        ? FromLowSToD(source.AsFpuRegisterPairLow<SRegister>())
3692        : FromLowSToD(destination.AsFpuRegisterPairLow<SRegister>());
3693    int mem = source.IsFpuRegisterPair()
3694        ? destination.GetStackIndex()
3695        : source.GetStackIndex();
3696    __ vmovd(DTMP, reg);
3697    __ LoadDFromOffset(reg, SP, mem);
3698    __ StoreDToOffset(DTMP, SP, mem);
3699  } else if (source.IsFpuRegister() || destination.IsFpuRegister()) {
3700    SRegister reg = source.IsFpuRegister() ? source.AsFpuRegister<SRegister>()
3701                                           : destination.AsFpuRegister<SRegister>();
3702    int mem = source.IsFpuRegister()
3703        ? destination.GetStackIndex()
3704        : source.GetStackIndex();
3705
3706    __ vmovrs(IP, reg);
3707    __ LoadSFromOffset(reg, SP, mem);
3708    __ StoreToOffset(kStoreWord, IP, SP, mem);
3709  } else if (source.IsDoubleStackSlot() && destination.IsDoubleStackSlot()) {
3710    Exchange(source.GetStackIndex(), destination.GetStackIndex());
3711    Exchange(source.GetHighStackIndex(kArmWordSize), destination.GetHighStackIndex(kArmWordSize));
3712  } else {
3713    LOG(FATAL) << "Unimplemented" << source << " <-> " << destination;
3714  }
3715}
3716
3717void ParallelMoveResolverARM::SpillScratch(int reg) {
3718  __ Push(static_cast<Register>(reg));
3719}
3720
3721void ParallelMoveResolverARM::RestoreScratch(int reg) {
3722  __ Pop(static_cast<Register>(reg));
3723}
3724
3725void LocationsBuilderARM::VisitLoadClass(HLoadClass* cls) {
3726  LocationSummary::CallKind call_kind = cls->CanCallRuntime()
3727      ? LocationSummary::kCallOnSlowPath
3728      : LocationSummary::kNoCall;
3729  LocationSummary* locations =
3730      new (GetGraph()->GetArena()) LocationSummary(cls, call_kind);
3731  locations->SetOut(Location::RequiresRegister());
3732}
3733
3734void InstructionCodeGeneratorARM::VisitLoadClass(HLoadClass* cls) {
3735  Register out = cls->GetLocations()->Out().AsRegister<Register>();
3736  if (cls->IsReferrersClass()) {
3737    DCHECK(!cls->CanCallRuntime());
3738    DCHECK(!cls->MustGenerateClinitCheck());
3739    codegen_->LoadCurrentMethod(out);
3740    __ LoadFromOffset(kLoadWord, out, out, mirror::ArtMethod::DeclaringClassOffset().Int32Value());
3741  } else {
3742    DCHECK(cls->CanCallRuntime());
3743    codegen_->LoadCurrentMethod(out);
3744    __ LoadFromOffset(
3745        kLoadWord, out, out, mirror::ArtMethod::DexCacheResolvedTypesOffset().Int32Value());
3746    __ LoadFromOffset(kLoadWord, out, out, CodeGenerator::GetCacheOffset(cls->GetTypeIndex()));
3747
3748    SlowPathCodeARM* slow_path = new (GetGraph()->GetArena()) LoadClassSlowPathARM(
3749        cls, cls, cls->GetDexPc(), cls->MustGenerateClinitCheck());
3750    codegen_->AddSlowPath(slow_path);
3751    __ cmp(out, ShifterOperand(0));
3752    __ b(slow_path->GetEntryLabel(), EQ);
3753    if (cls->MustGenerateClinitCheck()) {
3754      GenerateClassInitializationCheck(slow_path, out);
3755    } else {
3756      __ Bind(slow_path->GetExitLabel());
3757    }
3758  }
3759}
3760
3761void LocationsBuilderARM::VisitClinitCheck(HClinitCheck* check) {
3762  LocationSummary* locations =
3763      new (GetGraph()->GetArena()) LocationSummary(check, LocationSummary::kCallOnSlowPath);
3764  locations->SetInAt(0, Location::RequiresRegister());
3765  if (check->HasUses()) {
3766    locations->SetOut(Location::SameAsFirstInput());
3767  }
3768}
3769
3770void InstructionCodeGeneratorARM::VisitClinitCheck(HClinitCheck* check) {
3771  // We assume the class is not null.
3772  SlowPathCodeARM* slow_path = new (GetGraph()->GetArena()) LoadClassSlowPathARM(
3773      check->GetLoadClass(), check, check->GetDexPc(), true);
3774  codegen_->AddSlowPath(slow_path);
3775  GenerateClassInitializationCheck(slow_path,
3776                                   check->GetLocations()->InAt(0).AsRegister<Register>());
3777}
3778
3779void InstructionCodeGeneratorARM::GenerateClassInitializationCheck(
3780    SlowPathCodeARM* slow_path, Register class_reg) {
3781  __ LoadFromOffset(kLoadWord, IP, class_reg, mirror::Class::StatusOffset().Int32Value());
3782  __ cmp(IP, ShifterOperand(mirror::Class::kStatusInitialized));
3783  __ b(slow_path->GetEntryLabel(), LT);
3784  // Even if the initialized flag is set, we may be in a situation where caches are not synced
3785  // properly. Therefore, we do a memory fence.
3786  __ dmb(ISH);
3787  __ Bind(slow_path->GetExitLabel());
3788}
3789
3790void LocationsBuilderARM::VisitLoadString(HLoadString* load) {
3791  LocationSummary* locations =
3792      new (GetGraph()->GetArena()) LocationSummary(load, LocationSummary::kCallOnSlowPath);
3793  locations->SetOut(Location::RequiresRegister());
3794}
3795
3796void InstructionCodeGeneratorARM::VisitLoadString(HLoadString* load) {
3797  SlowPathCodeARM* slow_path = new (GetGraph()->GetArena()) LoadStringSlowPathARM(load);
3798  codegen_->AddSlowPath(slow_path);
3799
3800  Register out = load->GetLocations()->Out().AsRegister<Register>();
3801  codegen_->LoadCurrentMethod(out);
3802  __ LoadFromOffset(kLoadWord, out, out, mirror::ArtMethod::DeclaringClassOffset().Int32Value());
3803  __ LoadFromOffset(kLoadWord, out, out, mirror::Class::DexCacheStringsOffset().Int32Value());
3804  __ LoadFromOffset(kLoadWord, out, out, CodeGenerator::GetCacheOffset(load->GetStringIndex()));
3805  __ cmp(out, ShifterOperand(0));
3806  __ b(slow_path->GetEntryLabel(), EQ);
3807  __ Bind(slow_path->GetExitLabel());
3808}
3809
3810void LocationsBuilderARM::VisitLoadException(HLoadException* load) {
3811  LocationSummary* locations =
3812      new (GetGraph()->GetArena()) LocationSummary(load, LocationSummary::kNoCall);
3813  locations->SetOut(Location::RequiresRegister());
3814}
3815
3816void InstructionCodeGeneratorARM::VisitLoadException(HLoadException* load) {
3817  Register out = load->GetLocations()->Out().AsRegister<Register>();
3818  int32_t offset = Thread::ExceptionOffset<kArmWordSize>().Int32Value();
3819  __ LoadFromOffset(kLoadWord, out, TR, offset);
3820  __ LoadImmediate(IP, 0);
3821  __ StoreToOffset(kStoreWord, IP, TR, offset);
3822}
3823
3824void LocationsBuilderARM::VisitThrow(HThrow* instruction) {
3825  LocationSummary* locations =
3826      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCall);
3827  InvokeRuntimeCallingConvention calling_convention;
3828  locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0)));
3829}
3830
3831void InstructionCodeGeneratorARM::VisitThrow(HThrow* instruction) {
3832  codegen_->InvokeRuntime(
3833      QUICK_ENTRY_POINT(pDeliverException), instruction, instruction->GetDexPc(), nullptr);
3834}
3835
3836void LocationsBuilderARM::VisitInstanceOf(HInstanceOf* instruction) {
3837  LocationSummary::CallKind call_kind = instruction->IsClassFinal()
3838      ? LocationSummary::kNoCall
3839      : LocationSummary::kCallOnSlowPath;
3840  LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, call_kind);
3841  locations->SetInAt(0, Location::RequiresRegister());
3842  locations->SetInAt(1, Location::RequiresRegister());
3843  // The out register is used as a temporary, so it overlaps with the inputs.
3844  locations->SetOut(Location::RequiresRegister(), Location::kOutputOverlap);
3845}
3846
3847void InstructionCodeGeneratorARM::VisitInstanceOf(HInstanceOf* instruction) {
3848  LocationSummary* locations = instruction->GetLocations();
3849  Register obj = locations->InAt(0).AsRegister<Register>();
3850  Register cls = locations->InAt(1).AsRegister<Register>();
3851  Register out = locations->Out().AsRegister<Register>();
3852  uint32_t class_offset = mirror::Object::ClassOffset().Int32Value();
3853  Label done, zero;
3854  SlowPathCodeARM* slow_path = nullptr;
3855
3856  // Return 0 if `obj` is null.
3857  // TODO: avoid this check if we know obj is not null.
3858  __ cmp(obj, ShifterOperand(0));
3859  __ b(&zero, EQ);
3860  // Compare the class of `obj` with `cls`.
3861  __ LoadFromOffset(kLoadWord, out, obj, class_offset);
3862  __ cmp(out, ShifterOperand(cls));
3863  if (instruction->IsClassFinal()) {
3864    // Classes must be equal for the instanceof to succeed.
3865    __ b(&zero, NE);
3866    __ LoadImmediate(out, 1);
3867    __ b(&done);
3868  } else {
3869    // If the classes are not equal, we go into a slow path.
3870    DCHECK(locations->OnlyCallsOnSlowPath());
3871    slow_path = new (GetGraph()->GetArena()) TypeCheckSlowPathARM(
3872        instruction, locations->InAt(1), locations->Out(), instruction->GetDexPc());
3873    codegen_->AddSlowPath(slow_path);
3874    __ b(slow_path->GetEntryLabel(), NE);
3875    __ LoadImmediate(out, 1);
3876    __ b(&done);
3877  }
3878  __ Bind(&zero);
3879  __ LoadImmediate(out, 0);
3880  if (slow_path != nullptr) {
3881    __ Bind(slow_path->GetExitLabel());
3882  }
3883  __ Bind(&done);
3884}
3885
3886void LocationsBuilderARM::VisitCheckCast(HCheckCast* instruction) {
3887  LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(
3888      instruction, LocationSummary::kCallOnSlowPath);
3889  locations->SetInAt(0, Location::RequiresRegister());
3890  locations->SetInAt(1, Location::RequiresRegister());
3891  locations->AddTemp(Location::RequiresRegister());
3892}
3893
3894void InstructionCodeGeneratorARM::VisitCheckCast(HCheckCast* instruction) {
3895  LocationSummary* locations = instruction->GetLocations();
3896  Register obj = locations->InAt(0).AsRegister<Register>();
3897  Register cls = locations->InAt(1).AsRegister<Register>();
3898  Register temp = locations->GetTemp(0).AsRegister<Register>();
3899  uint32_t class_offset = mirror::Object::ClassOffset().Int32Value();
3900
3901  SlowPathCodeARM* slow_path = new (GetGraph()->GetArena()) TypeCheckSlowPathARM(
3902      instruction, locations->InAt(1), locations->GetTemp(0), instruction->GetDexPc());
3903  codegen_->AddSlowPath(slow_path);
3904
3905  // TODO: avoid this check if we know obj is not null.
3906  __ cmp(obj, ShifterOperand(0));
3907  __ b(slow_path->GetExitLabel(), EQ);
3908  // Compare the class of `obj` with `cls`.
3909  __ LoadFromOffset(kLoadWord, temp, obj, class_offset);
3910  __ cmp(temp, ShifterOperand(cls));
3911  __ b(slow_path->GetEntryLabel(), NE);
3912  __ Bind(slow_path->GetExitLabel());
3913}
3914
3915void LocationsBuilderARM::VisitMonitorOperation(HMonitorOperation* instruction) {
3916  LocationSummary* locations =
3917      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCall);
3918  InvokeRuntimeCallingConvention calling_convention;
3919  locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0)));
3920}
3921
3922void InstructionCodeGeneratorARM::VisitMonitorOperation(HMonitorOperation* instruction) {
3923  codegen_->InvokeRuntime(instruction->IsEnter()
3924        ? QUICK_ENTRY_POINT(pLockObject) : QUICK_ENTRY_POINT(pUnlockObject),
3925      instruction,
3926      instruction->GetDexPc(),
3927      nullptr);
3928}
3929
3930void LocationsBuilderARM::VisitAnd(HAnd* instruction) { HandleBitwiseOperation(instruction); }
3931void LocationsBuilderARM::VisitOr(HOr* instruction) { HandleBitwiseOperation(instruction); }
3932void LocationsBuilderARM::VisitXor(HXor* instruction) { HandleBitwiseOperation(instruction); }
3933
3934void LocationsBuilderARM::HandleBitwiseOperation(HBinaryOperation* instruction) {
3935  LocationSummary* locations =
3936      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
3937  DCHECK(instruction->GetResultType() == Primitive::kPrimInt
3938         || instruction->GetResultType() == Primitive::kPrimLong);
3939  locations->SetInAt(0, Location::RequiresRegister());
3940  locations->SetInAt(1, Location::RequiresRegister());
3941  locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
3942}
3943
3944void InstructionCodeGeneratorARM::VisitAnd(HAnd* instruction) {
3945  HandleBitwiseOperation(instruction);
3946}
3947
3948void InstructionCodeGeneratorARM::VisitOr(HOr* instruction) {
3949  HandleBitwiseOperation(instruction);
3950}
3951
3952void InstructionCodeGeneratorARM::VisitXor(HXor* instruction) {
3953  HandleBitwiseOperation(instruction);
3954}
3955
3956void InstructionCodeGeneratorARM::HandleBitwiseOperation(HBinaryOperation* instruction) {
3957  LocationSummary* locations = instruction->GetLocations();
3958
3959  if (instruction->GetResultType() == Primitive::kPrimInt) {
3960    Register first = locations->InAt(0).AsRegister<Register>();
3961    Register second = locations->InAt(1).AsRegister<Register>();
3962    Register out = locations->Out().AsRegister<Register>();
3963    if (instruction->IsAnd()) {
3964      __ and_(out, first, ShifterOperand(second));
3965    } else if (instruction->IsOr()) {
3966      __ orr(out, first, ShifterOperand(second));
3967    } else {
3968      DCHECK(instruction->IsXor());
3969      __ eor(out, first, ShifterOperand(second));
3970    }
3971  } else {
3972    DCHECK_EQ(instruction->GetResultType(), Primitive::kPrimLong);
3973    Location first = locations->InAt(0);
3974    Location second = locations->InAt(1);
3975    Location out = locations->Out();
3976    if (instruction->IsAnd()) {
3977      __ and_(out.AsRegisterPairLow<Register>(),
3978              first.AsRegisterPairLow<Register>(),
3979              ShifterOperand(second.AsRegisterPairLow<Register>()));
3980      __ and_(out.AsRegisterPairHigh<Register>(),
3981              first.AsRegisterPairHigh<Register>(),
3982              ShifterOperand(second.AsRegisterPairHigh<Register>()));
3983    } else if (instruction->IsOr()) {
3984      __ orr(out.AsRegisterPairLow<Register>(),
3985             first.AsRegisterPairLow<Register>(),
3986             ShifterOperand(second.AsRegisterPairLow<Register>()));
3987      __ orr(out.AsRegisterPairHigh<Register>(),
3988             first.AsRegisterPairHigh<Register>(),
3989             ShifterOperand(second.AsRegisterPairHigh<Register>()));
3990    } else {
3991      DCHECK(instruction->IsXor());
3992      __ eor(out.AsRegisterPairLow<Register>(),
3993             first.AsRegisterPairLow<Register>(),
3994             ShifterOperand(second.AsRegisterPairLow<Register>()));
3995      __ eor(out.AsRegisterPairHigh<Register>(),
3996             first.AsRegisterPairHigh<Register>(),
3997             ShifterOperand(second.AsRegisterPairHigh<Register>()));
3998    }
3999  }
4000}
4001
4002void CodeGeneratorARM::GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, Register temp) {
4003  DCHECK_EQ(temp, kArtMethodRegister);
4004
4005  // TODO: Implement all kinds of calls:
4006  // 1) boot -> boot
4007  // 2) app -> boot
4008  // 3) app -> app
4009  //
4010  // Currently we implement the app -> app logic, which looks up in the resolve cache.
4011
4012  // temp = method;
4013  LoadCurrentMethod(temp);
4014  if (!invoke->IsRecursive()) {
4015    // temp = temp->dex_cache_resolved_methods_;
4016    __ LoadFromOffset(
4017        kLoadWord, temp, temp, mirror::ArtMethod::DexCacheResolvedMethodsOffset().Int32Value());
4018    // temp = temp[index_in_cache]
4019    __ LoadFromOffset(
4020        kLoadWord, temp, temp, CodeGenerator::GetCacheOffset(invoke->GetDexMethodIndex()));
4021    // LR = temp[offset_of_quick_compiled_code]
4022    __ LoadFromOffset(kLoadWord, LR, temp,
4023                      mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset(
4024                          kArmWordSize).Int32Value());
4025    // LR()
4026    __ blx(LR);
4027  } else {
4028    __ bl(GetFrameEntryLabel());
4029  }
4030
4031  DCHECK(!IsLeafMethod());
4032}
4033
4034void LocationsBuilderARM::VisitBoundType(HBoundType* instruction) {
4035  // Nothing to do, this should be removed during prepare for register allocator.
4036  UNUSED(instruction);
4037  LOG(FATAL) << "Unreachable";
4038}
4039
4040void InstructionCodeGeneratorARM::VisitBoundType(HBoundType* instruction) {
4041  // Nothing to do, this should be removed during prepare for register allocator.
4042  UNUSED(instruction);
4043  LOG(FATAL) << "Unreachable";
4044}
4045
4046}  // namespace arm
4047}  // namespace art
4048