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