intrinsics_arm.cc revision 07276db28d654594e0e86e9e467cad393f752e6e
12bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe/* 22bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe * Copyright (C) 2015 The Android Open Source Project 32bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe * 42bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe * Licensed under the Apache License, Version 2.0 (the "License"); 52bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe * you may not use this file except in compliance with the License. 62bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe * You may obtain a copy of the License at 72bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe * 82bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe * http://www.apache.org/licenses/LICENSE-2.0 92bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe * 102bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe * Unless required by applicable law or agreed to in writing, software 112bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe * distributed under the License is distributed on an "AS IS" BASIS, 122bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 132bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe * See the License for the specific language governing permissions and 142bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe * limitations under the License. 152bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe */ 162bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 172bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe#include "intrinsics_arm.h" 182bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 192bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe#include "arch/arm/instruction_set_features_arm.h" 202bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe#include "code_generator_arm.h" 212bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe#include "entrypoints/quick/quick_entrypoints.h" 222bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe#include "intrinsics.h" 232bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe#include "mirror/array-inl.h" 242bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe#include "mirror/art_method.h" 252bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe#include "mirror/string.h" 262bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe#include "thread.h" 272bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe#include "utils/arm/assembler_arm.h" 282bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 292bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampenamespace art { 302bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 312bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampenamespace arm { 322bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 332bcf9bf784a0021630d8fe63d7230d46d6891780Andreas GampeArmAssembler* IntrinsicCodeGeneratorARM::GetAssembler() { 342bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe return codegen_->GetAssembler(); 352bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 362bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 372bcf9bf784a0021630d8fe63d7230d46d6891780Andreas GampeArenaAllocator* IntrinsicCodeGeneratorARM::GetAllocator() { 382bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe return codegen_->GetGraph()->GetArena(); 392bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 402bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 412bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe#define __ codegen->GetAssembler()-> 422bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 432bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampestatic void MoveFromReturnRegister(Location trg, Primitive::Type type, CodeGeneratorARM* codegen) { 442bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe if (!trg.IsValid()) { 452bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe DCHECK(type == Primitive::kPrimVoid); 462bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe return; 472bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe } 482bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 492bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe DCHECK_NE(type, Primitive::kPrimVoid); 502bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 51848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao if (Primitive::IsIntegralType(type) || type == Primitive::kPrimNot) { 522bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe if (type == Primitive::kPrimLong) { 532bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe Register trg_reg_lo = trg.AsRegisterPairLow<Register>(); 542bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe Register trg_reg_hi = trg.AsRegisterPairHigh<Register>(); 552bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe Register res_reg_lo = R0; 562bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe Register res_reg_hi = R1; 572bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe if (trg_reg_lo != res_reg_hi) { 582bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe if (trg_reg_lo != res_reg_lo) { 592bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ mov(trg_reg_lo, ShifterOperand(res_reg_lo)); 602bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ mov(trg_reg_hi, ShifterOperand(res_reg_hi)); 612bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe } else { 622bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe DCHECK_EQ(trg_reg_lo + 1, trg_reg_hi); 632bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe } 642bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe } else { 652bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ mov(trg_reg_hi, ShifterOperand(res_reg_hi)); 662bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ mov(trg_reg_lo, ShifterOperand(res_reg_lo)); 672bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe } 682bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe } else { 692bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe Register trg_reg = trg.AsRegister<Register>(); 702bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe Register res_reg = R0; 712bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe if (trg_reg != res_reg) { 722bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ mov(trg_reg, ShifterOperand(res_reg)); 732bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe } 742bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe } 752bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe } else { 762bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe UNIMPLEMENTED(FATAL) << "Floating-point return."; 772bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe } 782bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 792bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 80ec525fc30848189051b888da53ba051bc0878b78Roland Levillainstatic void MoveArguments(HInvoke* invoke, CodeGeneratorARM* codegen) { 812d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain InvokeDexCallingConventionVisitorARM calling_convention_visitor; 82ec525fc30848189051b888da53ba051bc0878b78Roland Levillain IntrinsicVisitor::MoveArguments(invoke, codegen, &calling_convention_visitor); 832bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 842bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 852bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe// Slow-path for fallback (calling the managed code to handle the intrinsic) in an intrinsified 862bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe// call. This will copy the arguments into the positions for a regular call. 872bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe// 882bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe// Note: The actual parameters are required to be in the locations given by the invoke's location 892bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe// summary. If an intrinsic modifies those locations before a slowpath call, they must be 902bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe// restored! 912bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampeclass IntrinsicSlowPathARM : public SlowPathCodeARM { 922bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe public: 932bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe explicit IntrinsicSlowPathARM(HInvoke* invoke) : invoke_(invoke) { } 942bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 952bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe void EmitNativeCode(CodeGenerator* codegen_in) OVERRIDE { 962bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe CodeGeneratorARM* codegen = down_cast<CodeGeneratorARM*>(codegen_in); 972bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ Bind(GetEntryLabel()); 982bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 99a8ac9130b872c080299afacf5dcaab513d13ea87Nicolas Geoffray SaveLiveRegisters(codegen, invoke_->GetLocations()); 1002bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 101ec525fc30848189051b888da53ba051bc0878b78Roland Levillain MoveArguments(invoke_, codegen); 1022bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 1032bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe if (invoke_->IsInvokeStaticOrDirect()) { 1042bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe codegen->GenerateStaticOrDirectCall(invoke_->AsInvokeStaticOrDirect(), kArtMethodRegister); 105a8ac9130b872c080299afacf5dcaab513d13ea87Nicolas Geoffray RecordPcInfo(codegen, invoke_, invoke_->GetDexPc()); 1062bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe } else { 1072bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe UNIMPLEMENTED(FATAL) << "Non-direct intrinsic slow-path not yet implemented"; 1082bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe UNREACHABLE(); 1092bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe } 1102bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 1112bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe // Copy the result back to the expected output. 1122bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe Location out = invoke_->GetLocations()->Out(); 1132bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe if (out.IsValid()) { 1142bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe DCHECK(out.IsRegister()); // TODO: Replace this when we support output in memory. 1152bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe DCHECK(!invoke_->GetLocations()->GetLiveRegisters()->ContainsCoreRegister(out.reg())); 1162bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe MoveFromReturnRegister(out, invoke_->GetType(), codegen); 1172bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe } 1182bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 119a8ac9130b872c080299afacf5dcaab513d13ea87Nicolas Geoffray RestoreLiveRegisters(codegen, invoke_->GetLocations()); 1202bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ b(GetExitLabel()); 1212bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe } 1222bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 1232bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe private: 1242bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe // The instruction where this slow path is happening. 1252bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe HInvoke* const invoke_; 1262bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 1272bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe DISALLOW_COPY_AND_ASSIGN(IntrinsicSlowPathARM); 1282bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe}; 1292bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 1302bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe#undef __ 1312bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 1322bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampebool IntrinsicLocationsBuilderARM::TryDispatch(HInvoke* invoke) { 1332bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe Dispatch(invoke); 1342bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe LocationSummary* res = invoke->GetLocations(); 1352bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe return res != nullptr && res->Intrinsified(); 1362bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 1372bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 1382bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe#define __ assembler-> 1392bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 1402bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampestatic void CreateFPToIntLocations(ArenaAllocator* arena, HInvoke* invoke) { 1412bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe LocationSummary* locations = new (arena) LocationSummary(invoke, 1422bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe LocationSummary::kNoCall, 1432bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe kIntrinsified); 1442bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe locations->SetInAt(0, Location::RequiresFpuRegister()); 1452bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe locations->SetOut(Location::RequiresRegister()); 1462bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 1472bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 1482bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampestatic void CreateIntToFPLocations(ArenaAllocator* arena, HInvoke* invoke) { 1492bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe LocationSummary* locations = new (arena) LocationSummary(invoke, 1502bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe LocationSummary::kNoCall, 1512bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe kIntrinsified); 1522bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe locations->SetInAt(0, Location::RequiresRegister()); 1532bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe locations->SetOut(Location::RequiresFpuRegister()); 1542bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 1552bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 1562bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampestatic void MoveFPToInt(LocationSummary* locations, bool is64bit, ArmAssembler* assembler) { 1572bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe Location input = locations->InAt(0); 1582bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe Location output = locations->Out(); 1592bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe if (is64bit) { 1602bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ vmovrrd(output.AsRegisterPairLow<Register>(), 1612bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe output.AsRegisterPairHigh<Register>(), 1622bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe FromLowSToD(input.AsFpuRegisterPairLow<SRegister>())); 1632bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe } else { 1642bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ vmovrs(output.AsRegister<Register>(), input.AsFpuRegister<SRegister>()); 1652bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe } 1662bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 1672bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 1682bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampestatic void MoveIntToFP(LocationSummary* locations, bool is64bit, ArmAssembler* assembler) { 1692bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe Location input = locations->InAt(0); 1702bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe Location output = locations->Out(); 1712bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe if (is64bit) { 1722bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ vmovdrr(FromLowSToD(output.AsFpuRegisterPairLow<SRegister>()), 1732bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe input.AsRegisterPairLow<Register>(), 1742bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe input.AsRegisterPairHigh<Register>()); 1752bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe } else { 1762bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ vmovsr(output.AsFpuRegister<SRegister>(), input.AsRegister<Register>()); 1772bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe } 1782bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 1792bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 1802bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicLocationsBuilderARM::VisitDoubleDoubleToRawLongBits(HInvoke* invoke) { 1812bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe CreateFPToIntLocations(arena_, invoke); 1822bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 1832bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicLocationsBuilderARM::VisitDoubleLongBitsToDouble(HInvoke* invoke) { 1842bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe CreateIntToFPLocations(arena_, invoke); 1852bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 1862bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 1872bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicCodeGeneratorARM::VisitDoubleDoubleToRawLongBits(HInvoke* invoke) { 1882bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe MoveFPToInt(invoke->GetLocations(), true, GetAssembler()); 1892bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 1902bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicCodeGeneratorARM::VisitDoubleLongBitsToDouble(HInvoke* invoke) { 1912bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe MoveIntToFP(invoke->GetLocations(), true, GetAssembler()); 1922bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 1932bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 1942bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicLocationsBuilderARM::VisitFloatFloatToRawIntBits(HInvoke* invoke) { 1952bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe CreateFPToIntLocations(arena_, invoke); 1962bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 1972bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicLocationsBuilderARM::VisitFloatIntBitsToFloat(HInvoke* invoke) { 1982bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe CreateIntToFPLocations(arena_, invoke); 1992bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 2002bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 2012bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicCodeGeneratorARM::VisitFloatFloatToRawIntBits(HInvoke* invoke) { 2022bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe MoveFPToInt(invoke->GetLocations(), false, GetAssembler()); 2032bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 2042bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicCodeGeneratorARM::VisitFloatIntBitsToFloat(HInvoke* invoke) { 2052bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe MoveIntToFP(invoke->GetLocations(), false, GetAssembler()); 2062bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 2072bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 2082bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampestatic void CreateIntToIntLocations(ArenaAllocator* arena, HInvoke* invoke) { 2092bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe LocationSummary* locations = new (arena) LocationSummary(invoke, 2102bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe LocationSummary::kNoCall, 2112bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe kIntrinsified); 2122bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe locations->SetInAt(0, Location::RequiresRegister()); 2132bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); 2142bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 2152bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 2162bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampestatic void CreateFPToFPLocations(ArenaAllocator* arena, HInvoke* invoke) { 2172bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe LocationSummary* locations = new (arena) LocationSummary(invoke, 2182bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe LocationSummary::kNoCall, 2192bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe kIntrinsified); 2202bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe locations->SetInAt(0, Location::RequiresFpuRegister()); 2212bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap); 2222bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 2232bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 2242bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampestatic void MathAbsFP(LocationSummary* locations, bool is64bit, ArmAssembler* assembler) { 2252bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe Location in = locations->InAt(0); 2262bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe Location out = locations->Out(); 2272bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 2282bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe if (is64bit) { 2292bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ vabsd(FromLowSToD(out.AsFpuRegisterPairLow<SRegister>()), 2302bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe FromLowSToD(in.AsFpuRegisterPairLow<SRegister>())); 2312bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe } else { 2322bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ vabss(out.AsFpuRegister<SRegister>(), in.AsFpuRegister<SRegister>()); 2332bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe } 2342bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 2352bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 2362bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicLocationsBuilderARM::VisitMathAbsDouble(HInvoke* invoke) { 2372bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe CreateFPToFPLocations(arena_, invoke); 2382bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 2392bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 2402bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicCodeGeneratorARM::VisitMathAbsDouble(HInvoke* invoke) { 2412bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe MathAbsFP(invoke->GetLocations(), true, GetAssembler()); 2422bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 2432bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 2442bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicLocationsBuilderARM::VisitMathAbsFloat(HInvoke* invoke) { 2452bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe CreateFPToFPLocations(arena_, invoke); 2462bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 2472bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 2482bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicCodeGeneratorARM::VisitMathAbsFloat(HInvoke* invoke) { 2492bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe MathAbsFP(invoke->GetLocations(), false, GetAssembler()); 2502bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 2512bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 2522bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampestatic void CreateIntToIntPlusTemp(ArenaAllocator* arena, HInvoke* invoke) { 2532bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe LocationSummary* locations = new (arena) LocationSummary(invoke, 2542bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe LocationSummary::kNoCall, 2552bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe kIntrinsified); 2562bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe locations->SetInAt(0, Location::RequiresRegister()); 2572bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); 2582bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 2592bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe locations->AddTemp(Location::RequiresRegister()); 2602bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 2612bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 2622bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampestatic void GenAbsInteger(LocationSummary* locations, 2632bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe bool is64bit, 2642bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe ArmAssembler* assembler) { 2652bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe Location in = locations->InAt(0); 2662bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe Location output = locations->Out(); 2672bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 2682bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe Register mask = locations->GetTemp(0).AsRegister<Register>(); 2692bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 2702bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe if (is64bit) { 2712bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe Register in_reg_lo = in.AsRegisterPairLow<Register>(); 2722bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe Register in_reg_hi = in.AsRegisterPairHigh<Register>(); 2732bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe Register out_reg_lo = output.AsRegisterPairLow<Register>(); 2742bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe Register out_reg_hi = output.AsRegisterPairHigh<Register>(); 2752bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 2762bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe DCHECK_NE(out_reg_lo, in_reg_hi) << "Diagonal overlap unexpected."; 2772bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 2782bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ Asr(mask, in_reg_hi, 31); 2792bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ adds(out_reg_lo, in_reg_lo, ShifterOperand(mask)); 2802bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ adc(out_reg_hi, in_reg_hi, ShifterOperand(mask)); 2812bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ eor(out_reg_lo, mask, ShifterOperand(out_reg_lo)); 2822bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ eor(out_reg_hi, mask, ShifterOperand(out_reg_hi)); 2832bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe } else { 2842bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe Register in_reg = in.AsRegister<Register>(); 2852bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe Register out_reg = output.AsRegister<Register>(); 2862bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 2872bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ Asr(mask, in_reg, 31); 2882bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ add(out_reg, in_reg, ShifterOperand(mask)); 2892bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ eor(out_reg, mask, ShifterOperand(out_reg)); 2902bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe } 2912bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 2922bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 2932bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicLocationsBuilderARM::VisitMathAbsInt(HInvoke* invoke) { 2942bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe CreateIntToIntPlusTemp(arena_, invoke); 2952bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 2962bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 2972bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicCodeGeneratorARM::VisitMathAbsInt(HInvoke* invoke) { 2982bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe GenAbsInteger(invoke->GetLocations(), false, GetAssembler()); 2992bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 3002bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 3012bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 3022bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicLocationsBuilderARM::VisitMathAbsLong(HInvoke* invoke) { 3032bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe CreateIntToIntPlusTemp(arena_, invoke); 3042bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 3052bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 3062bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicCodeGeneratorARM::VisitMathAbsLong(HInvoke* invoke) { 3072bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe GenAbsInteger(invoke->GetLocations(), true, GetAssembler()); 3082bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 3092bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 3102bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampestatic void GenMinMax(LocationSummary* locations, 3112bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe bool is_min, 3122bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe ArmAssembler* assembler) { 3132bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe Register op1 = locations->InAt(0).AsRegister<Register>(); 3142bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe Register op2 = locations->InAt(1).AsRegister<Register>(); 3152bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe Register out = locations->Out().AsRegister<Register>(); 3162bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 3172bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ cmp(op1, ShifterOperand(op2)); 3182bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 3192bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ it((is_min) ? Condition::LT : Condition::GT, kItElse); 3202bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ mov(out, ShifterOperand(op1), is_min ? Condition::LT : Condition::GT); 3212bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ mov(out, ShifterOperand(op2), is_min ? Condition::GE : Condition::LE); 3222bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 3232bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 3242bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampestatic void CreateIntIntToIntLocations(ArenaAllocator* arena, HInvoke* invoke) { 3252bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe LocationSummary* locations = new (arena) LocationSummary(invoke, 3262bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe LocationSummary::kNoCall, 3272bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe kIntrinsified); 3282bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe locations->SetInAt(0, Location::RequiresRegister()); 3292bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe locations->SetInAt(1, Location::RequiresRegister()); 3302bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); 3312bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 3322bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 3332bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicLocationsBuilderARM::VisitMathMinIntInt(HInvoke* invoke) { 3342bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe CreateIntIntToIntLocations(arena_, invoke); 3352bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 3362bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 3372bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicCodeGeneratorARM::VisitMathMinIntInt(HInvoke* invoke) { 3382bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe GenMinMax(invoke->GetLocations(), true, GetAssembler()); 3392bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 3402bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 3412bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicLocationsBuilderARM::VisitMathMaxIntInt(HInvoke* invoke) { 3422bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe CreateIntIntToIntLocations(arena_, invoke); 3432bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 3442bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 3452bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicCodeGeneratorARM::VisitMathMaxIntInt(HInvoke* invoke) { 3462bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe GenMinMax(invoke->GetLocations(), false, GetAssembler()); 3472bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 3482bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 3492bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicLocationsBuilderARM::VisitMathSqrt(HInvoke* invoke) { 3502bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe CreateFPToFPLocations(arena_, invoke); 3512bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 3522bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 3532bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicCodeGeneratorARM::VisitMathSqrt(HInvoke* invoke) { 3542bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe LocationSummary* locations = invoke->GetLocations(); 3552bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe ArmAssembler* assembler = GetAssembler(); 3562bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ vsqrtd(FromLowSToD(locations->Out().AsFpuRegisterPairLow<SRegister>()), 3572bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe FromLowSToD(locations->InAt(0).AsFpuRegisterPairLow<SRegister>())); 3582bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 3592bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 3602bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicLocationsBuilderARM::VisitMemoryPeekByte(HInvoke* invoke) { 3612bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe CreateIntToIntLocations(arena_, invoke); 3622bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 3632bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 3642bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicCodeGeneratorARM::VisitMemoryPeekByte(HInvoke* invoke) { 3652bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe ArmAssembler* assembler = GetAssembler(); 3662bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe // Ignore upper 4B of long address. 3672bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ ldrsb(invoke->GetLocations()->Out().AsRegister<Register>(), 3682bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe Address(invoke->GetLocations()->InAt(0).AsRegisterPairLow<Register>())); 3692bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 3702bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 3712bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicLocationsBuilderARM::VisitMemoryPeekIntNative(HInvoke* invoke) { 3722bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe CreateIntToIntLocations(arena_, invoke); 3732bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 3742bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 3752bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicCodeGeneratorARM::VisitMemoryPeekIntNative(HInvoke* invoke) { 3762bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe ArmAssembler* assembler = GetAssembler(); 3772bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe // Ignore upper 4B of long address. 3782bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ ldr(invoke->GetLocations()->Out().AsRegister<Register>(), 3792bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe Address(invoke->GetLocations()->InAt(0).AsRegisterPairLow<Register>())); 3802bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 3812bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 3822bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicLocationsBuilderARM::VisitMemoryPeekLongNative(HInvoke* invoke) { 3832bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe CreateIntToIntLocations(arena_, invoke); 3842bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 3852bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 3862bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicCodeGeneratorARM::VisitMemoryPeekLongNative(HInvoke* invoke) { 3872bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe ArmAssembler* assembler = GetAssembler(); 3882bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe // Ignore upper 4B of long address. 3892bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe Register addr = invoke->GetLocations()->InAt(0).AsRegisterPairLow<Register>(); 3902bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe // Worst case: Control register bit SCTLR.A = 0. Then unaligned accesses throw a processor 3912bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe // exception. So we can't use ldrd as addr may be unaligned. 3922bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe Register lo = invoke->GetLocations()->Out().AsRegisterPairLow<Register>(); 3932bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe Register hi = invoke->GetLocations()->Out().AsRegisterPairHigh<Register>(); 3942bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe if (addr == lo) { 3952bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ ldr(hi, Address(addr, 4)); 3962bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ ldr(lo, Address(addr, 0)); 3972bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe } else { 3982bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ ldr(lo, Address(addr, 0)); 3992bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ ldr(hi, Address(addr, 4)); 4002bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe } 4012bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 4022bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 4032bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicLocationsBuilderARM::VisitMemoryPeekShortNative(HInvoke* invoke) { 4042bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe CreateIntToIntLocations(arena_, invoke); 4052bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 4062bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 4072bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicCodeGeneratorARM::VisitMemoryPeekShortNative(HInvoke* invoke) { 4082bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe ArmAssembler* assembler = GetAssembler(); 4092bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe // Ignore upper 4B of long address. 4102bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ ldrsh(invoke->GetLocations()->Out().AsRegister<Register>(), 4112bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe Address(invoke->GetLocations()->InAt(0).AsRegisterPairLow<Register>())); 4122bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 4132bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 4142bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampestatic void CreateIntIntToVoidLocations(ArenaAllocator* arena, HInvoke* invoke) { 4152bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe LocationSummary* locations = new (arena) LocationSummary(invoke, 4162bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe LocationSummary::kNoCall, 4172bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe kIntrinsified); 4182bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe locations->SetInAt(0, Location::RequiresRegister()); 4192bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe locations->SetInAt(1, Location::RequiresRegister()); 4202bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 4212bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 4222bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicLocationsBuilderARM::VisitMemoryPokeByte(HInvoke* invoke) { 4232bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe CreateIntIntToVoidLocations(arena_, invoke); 4242bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 4252bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 4262bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicCodeGeneratorARM::VisitMemoryPokeByte(HInvoke* invoke) { 4272bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe ArmAssembler* assembler = GetAssembler(); 4282bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ strb(invoke->GetLocations()->InAt(1).AsRegister<Register>(), 4292bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe Address(invoke->GetLocations()->InAt(0).AsRegisterPairLow<Register>())); 4302bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 4312bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 4322bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicLocationsBuilderARM::VisitMemoryPokeIntNative(HInvoke* invoke) { 4332bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe CreateIntIntToVoidLocations(arena_, invoke); 4342bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 4352bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 4362bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicCodeGeneratorARM::VisitMemoryPokeIntNative(HInvoke* invoke) { 4372bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe ArmAssembler* assembler = GetAssembler(); 4382bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ str(invoke->GetLocations()->InAt(1).AsRegister<Register>(), 4392bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe Address(invoke->GetLocations()->InAt(0).AsRegisterPairLow<Register>())); 4402bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 4412bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 4422bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicLocationsBuilderARM::VisitMemoryPokeLongNative(HInvoke* invoke) { 4432bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe CreateIntIntToVoidLocations(arena_, invoke); 4442bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 4452bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 4462bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicCodeGeneratorARM::VisitMemoryPokeLongNative(HInvoke* invoke) { 4472bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe ArmAssembler* assembler = GetAssembler(); 4482bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe // Ignore upper 4B of long address. 4492bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe Register addr = invoke->GetLocations()->InAt(0).AsRegisterPairLow<Register>(); 4502bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe // Worst case: Control register bit SCTLR.A = 0. Then unaligned accesses throw a processor 4512bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe // exception. So we can't use ldrd as addr may be unaligned. 4522bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ str(invoke->GetLocations()->InAt(1).AsRegisterPairLow<Register>(), Address(addr, 0)); 4532bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ str(invoke->GetLocations()->InAt(1).AsRegisterPairHigh<Register>(), Address(addr, 4)); 4542bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 4552bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 4562bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicLocationsBuilderARM::VisitMemoryPokeShortNative(HInvoke* invoke) { 4572bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe CreateIntIntToVoidLocations(arena_, invoke); 4582bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 4592bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 4602bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicCodeGeneratorARM::VisitMemoryPokeShortNative(HInvoke* invoke) { 4612bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe ArmAssembler* assembler = GetAssembler(); 4622bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ strh(invoke->GetLocations()->InAt(1).AsRegister<Register>(), 4632bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe Address(invoke->GetLocations()->InAt(0).AsRegisterPairLow<Register>())); 4642bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 4652bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 4662bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicLocationsBuilderARM::VisitThreadCurrentThread(HInvoke* invoke) { 4672bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe LocationSummary* locations = new (arena_) LocationSummary(invoke, 4682bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe LocationSummary::kNoCall, 4692bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe kIntrinsified); 4702bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe locations->SetOut(Location::RequiresRegister()); 4712bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 4722bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 4732bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicCodeGeneratorARM::VisitThreadCurrentThread(HInvoke* invoke) { 4742bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe ArmAssembler* assembler = GetAssembler(); 4752bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ LoadFromOffset(kLoadWord, 4762bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe invoke->GetLocations()->Out().AsRegister<Register>(), 4772bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe TR, 4782bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe Thread::PeerOffset<kArmPointerSize>().Int32Value()); 4792bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 4802bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 4812bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampestatic void GenUnsafeGet(HInvoke* invoke, 4822bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe Primitive::Type type, 4832bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe bool is_volatile, 4842bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe CodeGeneratorARM* codegen) { 4852bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe LocationSummary* locations = invoke->GetLocations(); 4862bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe DCHECK((type == Primitive::kPrimInt) || 4872bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe (type == Primitive::kPrimLong) || 4882bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe (type == Primitive::kPrimNot)); 4892bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe ArmAssembler* assembler = codegen->GetAssembler(); 4902bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe Register base = locations->InAt(1).AsRegister<Register>(); // Object pointer. 4912bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe Register offset = locations->InAt(2).AsRegisterPairLow<Register>(); // Long offset, lo part only. 4922bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 4932bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe if (type == Primitive::kPrimLong) { 4942bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe Register trg_lo = locations->Out().AsRegisterPairLow<Register>(); 4952bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ add(IP, base, ShifterOperand(offset)); 4962bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe if (is_volatile && !codegen->GetInstructionSetFeatures().HasAtomicLdrdAndStrd()) { 4972bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe Register trg_hi = locations->Out().AsRegisterPairHigh<Register>(); 4982bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ ldrexd(trg_lo, trg_hi, IP); 4992bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe } else { 5002bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ ldrd(trg_lo, Address(IP)); 5012bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe } 5022bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe } else { 5032bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe Register trg = locations->Out().AsRegister<Register>(); 5042bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ ldr(trg, Address(base, offset)); 5052bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe } 5062bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 5072bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe if (is_volatile) { 5082bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ dmb(ISH); 5092bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe } 5102bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 5112bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 5122bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampestatic void CreateIntIntIntToIntLocations(ArenaAllocator* arena, HInvoke* invoke) { 5132bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe LocationSummary* locations = new (arena) LocationSummary(invoke, 5142bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe LocationSummary::kNoCall, 5152bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe kIntrinsified); 5162bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe locations->SetInAt(0, Location::NoLocation()); // Unused receiver. 5172bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe locations->SetInAt(1, Location::RequiresRegister()); 5182bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe locations->SetInAt(2, Location::RequiresRegister()); 5192bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); 5202bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 5212bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 5222bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicLocationsBuilderARM::VisitUnsafeGet(HInvoke* invoke) { 5232bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe CreateIntIntIntToIntLocations(arena_, invoke); 5242bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 5252bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicLocationsBuilderARM::VisitUnsafeGetVolatile(HInvoke* invoke) { 5262bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe CreateIntIntIntToIntLocations(arena_, invoke); 5272bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 5282bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicLocationsBuilderARM::VisitUnsafeGetLong(HInvoke* invoke) { 5292bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe CreateIntIntIntToIntLocations(arena_, invoke); 5302bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 5312bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicLocationsBuilderARM::VisitUnsafeGetLongVolatile(HInvoke* invoke) { 5322bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe CreateIntIntIntToIntLocations(arena_, invoke); 5332bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 5342bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicLocationsBuilderARM::VisitUnsafeGetObject(HInvoke* invoke) { 5352bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe CreateIntIntIntToIntLocations(arena_, invoke); 5362bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 5372bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicLocationsBuilderARM::VisitUnsafeGetObjectVolatile(HInvoke* invoke) { 5382bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe CreateIntIntIntToIntLocations(arena_, invoke); 5392bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 5402bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 5412bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicCodeGeneratorARM::VisitUnsafeGet(HInvoke* invoke) { 5422bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe GenUnsafeGet(invoke, Primitive::kPrimInt, false, codegen_); 5432bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 5442bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicCodeGeneratorARM::VisitUnsafeGetVolatile(HInvoke* invoke) { 5452bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe GenUnsafeGet(invoke, Primitive::kPrimInt, true, codegen_); 5462bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 5472bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicCodeGeneratorARM::VisitUnsafeGetLong(HInvoke* invoke) { 5482bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe GenUnsafeGet(invoke, Primitive::kPrimLong, false, codegen_); 5492bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 5502bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicCodeGeneratorARM::VisitUnsafeGetLongVolatile(HInvoke* invoke) { 5512bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe GenUnsafeGet(invoke, Primitive::kPrimLong, true, codegen_); 5522bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 5532bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicCodeGeneratorARM::VisitUnsafeGetObject(HInvoke* invoke) { 5542bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe GenUnsafeGet(invoke, Primitive::kPrimNot, false, codegen_); 5552bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 5562bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicCodeGeneratorARM::VisitUnsafeGetObjectVolatile(HInvoke* invoke) { 5572bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe GenUnsafeGet(invoke, Primitive::kPrimNot, true, codegen_); 5582bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 5592bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 5602bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampestatic void CreateIntIntIntIntToVoid(ArenaAllocator* arena, 5612bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe const ArmInstructionSetFeatures& features, 5622bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe Primitive::Type type, 5632bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe bool is_volatile, 5642bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe HInvoke* invoke) { 5652bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe LocationSummary* locations = new (arena) LocationSummary(invoke, 5662bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe LocationSummary::kNoCall, 5672bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe kIntrinsified); 5682bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe locations->SetInAt(0, Location::NoLocation()); // Unused receiver. 5692bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe locations->SetInAt(1, Location::RequiresRegister()); 5702bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe locations->SetInAt(2, Location::RequiresRegister()); 5712bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe locations->SetInAt(3, Location::RequiresRegister()); 5722bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 5732bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe if (type == Primitive::kPrimLong) { 5742bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe // Potentially need temps for ldrexd-strexd loop. 5752bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe if (is_volatile && !features.HasAtomicLdrdAndStrd()) { 5762bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe locations->AddTemp(Location::RequiresRegister()); // Temp_lo. 5772bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe locations->AddTemp(Location::RequiresRegister()); // Temp_hi. 5782bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe } 5792bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe } else if (type == Primitive::kPrimNot) { 5802bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe // Temps for card-marking. 5812bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe locations->AddTemp(Location::RequiresRegister()); // Temp. 5822bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe locations->AddTemp(Location::RequiresRegister()); // Card. 5832bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe } 5842bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 5852bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 5862bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicLocationsBuilderARM::VisitUnsafePut(HInvoke* invoke) { 5872bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe CreateIntIntIntIntToVoid(arena_, features_, Primitive::kPrimInt, false, invoke); 5882bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 5892bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicLocationsBuilderARM::VisitUnsafePutOrdered(HInvoke* invoke) { 5902bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe CreateIntIntIntIntToVoid(arena_, features_, Primitive::kPrimInt, false, invoke); 5912bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 5922bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicLocationsBuilderARM::VisitUnsafePutVolatile(HInvoke* invoke) { 5932bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe CreateIntIntIntIntToVoid(arena_, features_, Primitive::kPrimInt, true, invoke); 5942bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 5952bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicLocationsBuilderARM::VisitUnsafePutObject(HInvoke* invoke) { 5962bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe CreateIntIntIntIntToVoid(arena_, features_, Primitive::kPrimNot, false, invoke); 5972bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 5982bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicLocationsBuilderARM::VisitUnsafePutObjectOrdered(HInvoke* invoke) { 5992bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe CreateIntIntIntIntToVoid(arena_, features_, Primitive::kPrimNot, false, invoke); 6002bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 6012bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicLocationsBuilderARM::VisitUnsafePutObjectVolatile(HInvoke* invoke) { 6022bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe CreateIntIntIntIntToVoid(arena_, features_, Primitive::kPrimNot, true, invoke); 6032bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 6042bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicLocationsBuilderARM::VisitUnsafePutLong(HInvoke* invoke) { 6052bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe CreateIntIntIntIntToVoid(arena_, features_, Primitive::kPrimLong, false, invoke); 6062bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 6072bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicLocationsBuilderARM::VisitUnsafePutLongOrdered(HInvoke* invoke) { 6082bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe CreateIntIntIntIntToVoid(arena_, features_, Primitive::kPrimLong, false, invoke); 6092bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 6102bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicLocationsBuilderARM::VisitUnsafePutLongVolatile(HInvoke* invoke) { 6112bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe CreateIntIntIntIntToVoid(arena_, features_, Primitive::kPrimLong, true, invoke); 6122bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 6132bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 6142bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampestatic void GenUnsafePut(LocationSummary* locations, 6152bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe Primitive::Type type, 6162bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe bool is_volatile, 6172bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe bool is_ordered, 6182bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe CodeGeneratorARM* codegen) { 6192bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe ArmAssembler* assembler = codegen->GetAssembler(); 6202bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 6212bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe Register base = locations->InAt(1).AsRegister<Register>(); // Object pointer. 6222bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe Register offset = locations->InAt(2).AsRegisterPairLow<Register>(); // Long offset, lo part only. 6232bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe Register value; 6242bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 6252bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe if (is_volatile || is_ordered) { 6262bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ dmb(ISH); 6272bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe } 6282bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 6292bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe if (type == Primitive::kPrimLong) { 6302bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe Register value_lo = locations->InAt(3).AsRegisterPairLow<Register>(); 6312bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe value = value_lo; 6322bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe if (is_volatile && !codegen->GetInstructionSetFeatures().HasAtomicLdrdAndStrd()) { 6332bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe Register temp_lo = locations->GetTemp(0).AsRegister<Register>(); 6342bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe Register temp_hi = locations->GetTemp(1).AsRegister<Register>(); 6352bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe Register value_hi = locations->InAt(3).AsRegisterPairHigh<Register>(); 6362bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 6372bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ add(IP, base, ShifterOperand(offset)); 6382bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe Label loop_head; 6392bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ Bind(&loop_head); 6402bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ ldrexd(temp_lo, temp_hi, IP); 6412bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ strexd(temp_lo, value_lo, value_hi, IP); 6422bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ cmp(temp_lo, ShifterOperand(0)); 6432bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ b(&loop_head, NE); 6442bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe } else { 6452bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ add(IP, base, ShifterOperand(offset)); 6462bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ strd(value_lo, Address(IP)); 6472bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe } 6482bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe } else { 6492bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe value = locations->InAt(3).AsRegister<Register>(); 6502bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ str(value, Address(base, offset)); 6512bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe } 6522bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 6532bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe if (is_volatile) { 6542bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ dmb(ISH); 6552bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe } 6562bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 6572bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe if (type == Primitive::kPrimNot) { 6582bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe Register temp = locations->GetTemp(0).AsRegister<Register>(); 6592bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe Register card = locations->GetTemp(1).AsRegister<Register>(); 66007276db28d654594e0e86e9e467cad393f752e6eNicolas Geoffray bool value_can_be_null = true; // TODO: Worth finding out this information? 66107276db28d654594e0e86e9e467cad393f752e6eNicolas Geoffray codegen->MarkGCCard(temp, card, base, value, value_can_be_null); 6622bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe } 6632bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 6642bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 6652bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicCodeGeneratorARM::VisitUnsafePut(HInvoke* invoke) { 6662bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe GenUnsafePut(invoke->GetLocations(), Primitive::kPrimInt, false, false, codegen_); 6672bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 6682bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicCodeGeneratorARM::VisitUnsafePutOrdered(HInvoke* invoke) { 6692bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe GenUnsafePut(invoke->GetLocations(), Primitive::kPrimInt, false, true, codegen_); 6702bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 6712bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicCodeGeneratorARM::VisitUnsafePutVolatile(HInvoke* invoke) { 6722bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe GenUnsafePut(invoke->GetLocations(), Primitive::kPrimInt, true, false, codegen_); 6732bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 6742bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicCodeGeneratorARM::VisitUnsafePutObject(HInvoke* invoke) { 6752bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe GenUnsafePut(invoke->GetLocations(), Primitive::kPrimNot, false, false, codegen_); 6762bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 6772bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicCodeGeneratorARM::VisitUnsafePutObjectOrdered(HInvoke* invoke) { 6782bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe GenUnsafePut(invoke->GetLocations(), Primitive::kPrimNot, false, true, codegen_); 6792bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 6802bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicCodeGeneratorARM::VisitUnsafePutObjectVolatile(HInvoke* invoke) { 6812bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe GenUnsafePut(invoke->GetLocations(), Primitive::kPrimNot, true, false, codegen_); 6822bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 6832bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicCodeGeneratorARM::VisitUnsafePutLong(HInvoke* invoke) { 6842bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe GenUnsafePut(invoke->GetLocations(), Primitive::kPrimLong, false, false, codegen_); 6852bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 6862bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicCodeGeneratorARM::VisitUnsafePutLongOrdered(HInvoke* invoke) { 6872bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe GenUnsafePut(invoke->GetLocations(), Primitive::kPrimLong, false, true, codegen_); 6882bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 6892bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicCodeGeneratorARM::VisitUnsafePutLongVolatile(HInvoke* invoke) { 6902bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe GenUnsafePut(invoke->GetLocations(), Primitive::kPrimLong, true, false, codegen_); 6912bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 6922bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 6932bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampestatic void CreateIntIntIntIntIntToIntPlusTemps(ArenaAllocator* arena, 6942bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe HInvoke* invoke) { 6952bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe LocationSummary* locations = new (arena) LocationSummary(invoke, 6962bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe LocationSummary::kNoCall, 6972bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe kIntrinsified); 6982bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe locations->SetInAt(0, Location::NoLocation()); // Unused receiver. 6992bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe locations->SetInAt(1, Location::RequiresRegister()); 7002bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe locations->SetInAt(2, Location::RequiresRegister()); 7012bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe locations->SetInAt(3, Location::RequiresRegister()); 7022bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe locations->SetInAt(4, Location::RequiresRegister()); 7032bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 7042bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); 7052bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 7062bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe locations->AddTemp(Location::RequiresRegister()); // Pointer. 7072bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe locations->AddTemp(Location::RequiresRegister()); // Temp 1. 7082bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe locations->AddTemp(Location::RequiresRegister()); // Temp 2. 7092bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 7102bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 7112bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampestatic void GenCas(LocationSummary* locations, Primitive::Type type, CodeGeneratorARM* codegen) { 7122bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe DCHECK_NE(type, Primitive::kPrimLong); 7132bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 7142bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe ArmAssembler* assembler = codegen->GetAssembler(); 7152bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 7162bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe Register out = locations->Out().AsRegister<Register>(); // Boolean result. 7172bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 7182bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe Register base = locations->InAt(1).AsRegister<Register>(); // Object pointer. 7192bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe Register offset = locations->InAt(2).AsRegisterPairLow<Register>(); // Offset (discard high 4B). 7202bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe Register expected_lo = locations->InAt(3).AsRegister<Register>(); // Expected. 7212bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe Register value_lo = locations->InAt(4).AsRegister<Register>(); // Value. 7222bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 7232bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe Register tmp_ptr = locations->GetTemp(0).AsRegister<Register>(); // Pointer to actual memory. 7242bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe Register tmp_lo = locations->GetTemp(1).AsRegister<Register>(); // Value in memory. 7252bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 7262bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe if (type == Primitive::kPrimNot) { 7272bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe // Mark card for object assuming new value is stored. Worst case we will mark an unchanged 7282bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe // object and scan the receiver at the next GC for nothing. 72907276db28d654594e0e86e9e467cad393f752e6eNicolas Geoffray bool value_can_be_null = true; // TODO: Worth finding out this information? 73007276db28d654594e0e86e9e467cad393f752e6eNicolas Geoffray codegen->MarkGCCard(tmp_ptr, tmp_lo, base, value_lo, value_can_be_null); 7312bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe } 7322bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 7332bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe // Prevent reordering with prior memory operations. 7342bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ dmb(ISH); 7352bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 7362bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ add(tmp_ptr, base, ShifterOperand(offset)); 7372bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 7382bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe // do { 7392bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe // tmp = [r_ptr] - expected; 7402bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe // } while (tmp == 0 && failure([r_ptr] <- r_new_value)); 7412bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe // result = tmp != 0; 7422bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 7432bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe Label loop_head; 7442bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ Bind(&loop_head); 7452bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 7462bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ ldrex(tmp_lo, tmp_ptr); 7472bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 7482bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ subs(tmp_lo, tmp_lo, ShifterOperand(expected_lo)); 7492bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 7502bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ it(EQ, ItState::kItT); 7512bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ strex(tmp_lo, value_lo, tmp_ptr, EQ); 7522bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ cmp(tmp_lo, ShifterOperand(1), EQ); 7532bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 7542bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ b(&loop_head, EQ); 7552bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 7562bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ dmb(ISH); 7572bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 7582bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ rsbs(out, tmp_lo, ShifterOperand(1)); 7592bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ it(CC); 7602bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ mov(out, ShifterOperand(0), CC); 7612bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 7622bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 763ca71458862be8505330b7fd5649a062f31d143dcAndreas Gampevoid IntrinsicLocationsBuilderARM::VisitUnsafeCASInt(HInvoke* invoke) { 7642bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe CreateIntIntIntIntIntToIntPlusTemps(arena_, invoke); 7652bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 766ca71458862be8505330b7fd5649a062f31d143dcAndreas Gampevoid IntrinsicLocationsBuilderARM::VisitUnsafeCASObject(HInvoke* invoke) { 7672bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe CreateIntIntIntIntIntToIntPlusTemps(arena_, invoke); 7682bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 7692bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicCodeGeneratorARM::VisitUnsafeCASInt(HInvoke* invoke) { 7702bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe GenCas(invoke->GetLocations(), Primitive::kPrimInt, codegen_); 7712bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 7722bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicCodeGeneratorARM::VisitUnsafeCASObject(HInvoke* invoke) { 7732bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe GenCas(invoke->GetLocations(), Primitive::kPrimNot, codegen_); 7742bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 7752bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 7762bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicLocationsBuilderARM::VisitStringCharAt(HInvoke* invoke) { 7772bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe LocationSummary* locations = new (arena_) LocationSummary(invoke, 7782bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe LocationSummary::kCallOnSlowPath, 7792bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe kIntrinsified); 7802bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe locations->SetInAt(0, Location::RequiresRegister()); 7812bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe locations->SetInAt(1, Location::RequiresRegister()); 7822bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe locations->SetOut(Location::RequiresRegister(), Location::kOutputOverlap); 7832bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 7842bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe locations->AddTemp(Location::RequiresRegister()); 7852bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe locations->AddTemp(Location::RequiresRegister()); 7862bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 7872bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 7882bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicCodeGeneratorARM::VisitStringCharAt(HInvoke* invoke) { 7892bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe ArmAssembler* assembler = GetAssembler(); 7902bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe LocationSummary* locations = invoke->GetLocations(); 7912bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 7922bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe // Location of reference to data array 7932bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe const MemberOffset value_offset = mirror::String::ValueOffset(); 7942bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe // Location of count 7952bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe const MemberOffset count_offset = mirror::String::CountOffset(); 7962bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 7972bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe Register obj = locations->InAt(0).AsRegister<Register>(); // String object pointer. 7982bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe Register idx = locations->InAt(1).AsRegister<Register>(); // Index of character. 7992bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe Register out = locations->Out().AsRegister<Register>(); // Result character. 8002bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 8012bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe Register temp = locations->GetTemp(0).AsRegister<Register>(); 8022bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe Register array_temp = locations->GetTemp(1).AsRegister<Register>(); 8032bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 8042bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe // TODO: Maybe we can support range check elimination. Overall, though, I think it's not worth 8052bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe // the cost. 8062bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe // TODO: For simplicity, the index parameter is requested in a register, so different from Quick 8072bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe // we will not optimize the code for constants (which would save a register). 8082bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 8092bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe SlowPathCodeARM* slow_path = new (GetAllocator()) IntrinsicSlowPathARM(invoke); 8102bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe codegen_->AddSlowPath(slow_path); 8112bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 8122bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ ldr(temp, Address(obj, count_offset.Int32Value())); // temp = str.length. 8132bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe codegen_->MaybeRecordImplicitNullCheck(invoke); 8142bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ cmp(idx, ShifterOperand(temp)); 8152bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ b(slow_path->GetEntryLabel(), CS); 8162bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 817848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao __ add(array_temp, obj, ShifterOperand(value_offset.Int32Value())); // array_temp := str.value. 8182bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 8192bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe // Load the value. 820848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao __ ldrh(out, Address(array_temp, idx, LSL, 1)); // out := array_temp[idx]. 8212bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 8222bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe __ Bind(slow_path->GetExitLabel()); 8232bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 8242bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 825d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffrayvoid IntrinsicLocationsBuilderARM::VisitStringCompareTo(HInvoke* invoke) { 826d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray // The inputs plus one temp. 827d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray LocationSummary* locations = new (arena_) LocationSummary(invoke, 828d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray LocationSummary::kCall, 829d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray kIntrinsified); 830d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray InvokeRuntimeCallingConvention calling_convention; 831d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0))); 832d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray locations->SetInAt(1, Location::RegisterLocation(calling_convention.GetRegisterAt(1))); 833d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray locations->SetOut(Location::RegisterLocation(R0)); 834d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray} 835d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray 836d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffrayvoid IntrinsicCodeGeneratorARM::VisitStringCompareTo(HInvoke* invoke) { 837d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray ArmAssembler* assembler = GetAssembler(); 838d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray LocationSummary* locations = invoke->GetLocations(); 839d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray 840512e04d1ea7fb33e3992715fe55be8a834d4a79cNicolas Geoffray // Note that the null check must have been done earlier. 841641547a5f18ca2ea54469cceadcfef64f132e5e0Calin Juravle DCHECK(!invoke->CanDoImplicitNullCheckOn(invoke->InputAt(0))); 842d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray 843d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray Register argument = locations->InAt(1).AsRegister<Register>(); 844d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray __ cmp(argument, ShifterOperand(0)); 845d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray SlowPathCodeARM* slow_path = new (GetAllocator()) IntrinsicSlowPathARM(invoke); 846d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray codegen_->AddSlowPath(slow_path); 847d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray __ b(slow_path->GetEntryLabel(), EQ); 848d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray 849d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray __ LoadFromOffset( 850d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray kLoadWord, LR, TR, QUICK_ENTRYPOINT_OFFSET(kArmWordSize, pStringCompareTo).Int32Value()); 851d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray __ blx(LR); 852d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray __ Bind(slow_path->GetExitLabel()); 853d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray} 854d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray 855ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampestatic void GenerateVisitStringIndexOf(HInvoke* invoke, 856ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe ArmAssembler* assembler, 857ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe CodeGeneratorARM* codegen, 858ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe ArenaAllocator* allocator, 859ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe bool start_at_zero) { 860ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe LocationSummary* locations = invoke->GetLocations(); 861ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe Register tmp_reg = locations->GetTemp(0).AsRegister<Register>(); 862ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe 863ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe // Note that the null check must have been done earlier. 864ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe DCHECK(!invoke->CanDoImplicitNullCheckOn(invoke->InputAt(0))); 865ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe 866ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe // Check for code points > 0xFFFF. Either a slow-path check when we don't know statically, 867ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe // or directly dispatch if we have a constant. 868ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe SlowPathCodeARM* slow_path = nullptr; 869ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe if (invoke->InputAt(1)->IsIntConstant()) { 870ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe if (static_cast<uint32_t>(invoke->InputAt(1)->AsIntConstant()->GetValue()) > 871ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe std::numeric_limits<uint16_t>::max()) { 872ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe // Always needs the slow-path. We could directly dispatch to it, but this case should be 873ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe // rare, so for simplicity just put the full slow-path down and branch unconditionally. 874ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe slow_path = new (allocator) IntrinsicSlowPathARM(invoke); 875ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe codegen->AddSlowPath(slow_path); 876ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe __ b(slow_path->GetEntryLabel()); 877ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe __ Bind(slow_path->GetExitLabel()); 878ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe return; 879ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe } 880ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe } else { 881ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe Register char_reg = locations->InAt(1).AsRegister<Register>(); 882ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe __ LoadImmediate(tmp_reg, std::numeric_limits<uint16_t>::max()); 883ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe __ cmp(char_reg, ShifterOperand(tmp_reg)); 884ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe slow_path = new (allocator) IntrinsicSlowPathARM(invoke); 885ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe codegen->AddSlowPath(slow_path); 886ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe __ b(slow_path->GetEntryLabel(), HI); 887ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe } 888ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe 889ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe if (start_at_zero) { 890ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe DCHECK_EQ(tmp_reg, R2); 891ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe // Start-index = 0. 892ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe __ LoadImmediate(tmp_reg, 0); 893ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe } 894ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe 895ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe __ LoadFromOffset(kLoadWord, LR, TR, 896ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe QUICK_ENTRYPOINT_OFFSET(kArmWordSize, pIndexOf).Int32Value()); 897ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe __ blx(LR); 898ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe 899ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe if (slow_path != nullptr) { 900ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe __ Bind(slow_path->GetExitLabel()); 901ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe } 902ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe} 903ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe 904ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampevoid IntrinsicLocationsBuilderARM::VisitStringIndexOf(HInvoke* invoke) { 905ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe LocationSummary* locations = new (arena_) LocationSummary(invoke, 906ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe LocationSummary::kCall, 907ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe kIntrinsified); 908ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe // We have a hand-crafted assembly stub that follows the runtime calling convention. So it's 909ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe // best to align the inputs accordingly. 910ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe InvokeRuntimeCallingConvention calling_convention; 911ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0))); 912ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe locations->SetInAt(1, Location::RegisterLocation(calling_convention.GetRegisterAt(1))); 913ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe locations->SetOut(Location::RegisterLocation(R0)); 914ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe 915ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe // Need a temp for slow-path codepoint compare, and need to send start-index=0. 916ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe locations->AddTemp(Location::RegisterLocation(calling_convention.GetRegisterAt(2))); 917ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe} 918ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe 919ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampevoid IntrinsicCodeGeneratorARM::VisitStringIndexOf(HInvoke* invoke) { 920ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe GenerateVisitStringIndexOf(invoke, GetAssembler(), codegen_, GetAllocator(), true); 921ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe} 922ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe 923ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampevoid IntrinsicLocationsBuilderARM::VisitStringIndexOfAfter(HInvoke* invoke) { 924ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe LocationSummary* locations = new (arena_) LocationSummary(invoke, 925ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe LocationSummary::kCall, 926ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe kIntrinsified); 927ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe // We have a hand-crafted assembly stub that follows the runtime calling convention. So it's 928ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe // best to align the inputs accordingly. 929ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe InvokeRuntimeCallingConvention calling_convention; 930ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0))); 931ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe locations->SetInAt(1, Location::RegisterLocation(calling_convention.GetRegisterAt(1))); 932ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe locations->SetInAt(2, Location::RegisterLocation(calling_convention.GetRegisterAt(2))); 933ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe locations->SetOut(Location::RegisterLocation(R0)); 934ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe 935ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe // Need a temp for slow-path codepoint compare. 936ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe locations->AddTemp(Location::RequiresRegister()); 937ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe} 938ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe 939ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampevoid IntrinsicCodeGeneratorARM::VisitStringIndexOfAfter(HInvoke* invoke) { 940ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe GenerateVisitStringIndexOf(invoke, GetAssembler(), codegen_, GetAllocator(), false); 941ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe} 942ba6fdbcb764d5a8972f5ff2d7147e4d78226b347Andreas Gampe 943848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Haovoid IntrinsicLocationsBuilderARM::VisitStringNewStringFromBytes(HInvoke* invoke) { 944848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao LocationSummary* locations = new (arena_) LocationSummary(invoke, 945848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao LocationSummary::kCall, 946848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao kIntrinsified); 947848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao InvokeRuntimeCallingConvention calling_convention; 948848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0))); 949848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao locations->SetInAt(1, Location::RegisterLocation(calling_convention.GetRegisterAt(1))); 950848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao locations->SetInAt(2, Location::RegisterLocation(calling_convention.GetRegisterAt(2))); 951848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao locations->SetInAt(3, Location::RegisterLocation(calling_convention.GetRegisterAt(3))); 952848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao locations->SetOut(Location::RegisterLocation(R0)); 953848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao} 954848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao 955848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Haovoid IntrinsicCodeGeneratorARM::VisitStringNewStringFromBytes(HInvoke* invoke) { 956848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao ArmAssembler* assembler = GetAssembler(); 957848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao LocationSummary* locations = invoke->GetLocations(); 958848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao 959848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao Register byte_array = locations->InAt(0).AsRegister<Register>(); 960848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao __ cmp(byte_array, ShifterOperand(0)); 961848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao SlowPathCodeARM* slow_path = new (GetAllocator()) IntrinsicSlowPathARM(invoke); 962848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao codegen_->AddSlowPath(slow_path); 963848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao __ b(slow_path->GetEntryLabel(), EQ); 964848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao 965848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao __ LoadFromOffset( 966848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao kLoadWord, LR, TR, QUICK_ENTRYPOINT_OFFSET(kArmWordSize, pAllocStringFromBytes).Int32Value()); 967848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao codegen_->RecordPcInfo(invoke, invoke->GetDexPc()); 968848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao __ blx(LR); 969848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao __ Bind(slow_path->GetExitLabel()); 970848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao} 971848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao 972848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Haovoid IntrinsicLocationsBuilderARM::VisitStringNewStringFromChars(HInvoke* invoke) { 973848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao LocationSummary* locations = new (arena_) LocationSummary(invoke, 974848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao LocationSummary::kCall, 975848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao kIntrinsified); 976848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao InvokeRuntimeCallingConvention calling_convention; 977848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0))); 978848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao locations->SetInAt(1, Location::RegisterLocation(calling_convention.GetRegisterAt(1))); 979848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao locations->SetInAt(2, Location::RegisterLocation(calling_convention.GetRegisterAt(2))); 980848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao locations->SetOut(Location::RegisterLocation(R0)); 981848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao} 982848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao 983848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Haovoid IntrinsicCodeGeneratorARM::VisitStringNewStringFromChars(HInvoke* invoke) { 984848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao ArmAssembler* assembler = GetAssembler(); 985848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao 986848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao __ LoadFromOffset( 987848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao kLoadWord, LR, TR, QUICK_ENTRYPOINT_OFFSET(kArmWordSize, pAllocStringFromChars).Int32Value()); 988848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao codegen_->RecordPcInfo(invoke, invoke->GetDexPc()); 989848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao __ blx(LR); 990848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao} 991848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao 992848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Haovoid IntrinsicLocationsBuilderARM::VisitStringNewStringFromString(HInvoke* invoke) { 993848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao LocationSummary* locations = new (arena_) LocationSummary(invoke, 994848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao LocationSummary::kCall, 995848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao kIntrinsified); 996848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao InvokeRuntimeCallingConvention calling_convention; 997848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0))); 998848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao locations->SetOut(Location::RegisterLocation(R0)); 999848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao} 1000848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao 1001848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Haovoid IntrinsicCodeGeneratorARM::VisitStringNewStringFromString(HInvoke* invoke) { 1002848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao ArmAssembler* assembler = GetAssembler(); 1003848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao LocationSummary* locations = invoke->GetLocations(); 1004848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao 1005848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao Register string_to_copy = locations->InAt(0).AsRegister<Register>(); 1006848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao __ cmp(string_to_copy, ShifterOperand(0)); 1007848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao SlowPathCodeARM* slow_path = new (GetAllocator()) IntrinsicSlowPathARM(invoke); 1008848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao codegen_->AddSlowPath(slow_path); 1009848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao __ b(slow_path->GetEntryLabel(), EQ); 1010848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao 1011848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao __ LoadFromOffset(kLoadWord, 1012848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao LR, TR, QUICK_ENTRYPOINT_OFFSET(kArmWordSize, pAllocStringFromString).Int32Value()); 1013848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao codegen_->RecordPcInfo(invoke, invoke->GetDexPc()); 1014848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao __ blx(LR); 1015848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao __ Bind(slow_path->GetExitLabel()); 1016848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao} 1017848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao 10182bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe// Unimplemented intrinsics. 10192bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 10202bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe#define UNIMPLEMENTED_INTRINSIC(Name) \ 10212bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicLocationsBuilderARM::Visit ## Name(HInvoke* invoke ATTRIBUTE_UNUSED) { \ 10222bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} \ 10232bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampevoid IntrinsicCodeGeneratorARM::Visit ## Name(HInvoke* invoke ATTRIBUTE_UNUSED) { \ 10242bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 10252bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 10262bcf9bf784a0021630d8fe63d7230d46d6891780Andreas GampeUNIMPLEMENTED_INTRINSIC(IntegerReverse) 10272bcf9bf784a0021630d8fe63d7230d46d6891780Andreas GampeUNIMPLEMENTED_INTRINSIC(IntegerReverseBytes) 10282bcf9bf784a0021630d8fe63d7230d46d6891780Andreas GampeUNIMPLEMENTED_INTRINSIC(LongReverse) 10292bcf9bf784a0021630d8fe63d7230d46d6891780Andreas GampeUNIMPLEMENTED_INTRINSIC(LongReverseBytes) 10302bcf9bf784a0021630d8fe63d7230d46d6891780Andreas GampeUNIMPLEMENTED_INTRINSIC(ShortReverseBytes) 10312bcf9bf784a0021630d8fe63d7230d46d6891780Andreas GampeUNIMPLEMENTED_INTRINSIC(MathMinDoubleDouble) 10322bcf9bf784a0021630d8fe63d7230d46d6891780Andreas GampeUNIMPLEMENTED_INTRINSIC(MathMinFloatFloat) 10332bcf9bf784a0021630d8fe63d7230d46d6891780Andreas GampeUNIMPLEMENTED_INTRINSIC(MathMaxDoubleDouble) 10342bcf9bf784a0021630d8fe63d7230d46d6891780Andreas GampeUNIMPLEMENTED_INTRINSIC(MathMaxFloatFloat) 10352bcf9bf784a0021630d8fe63d7230d46d6891780Andreas GampeUNIMPLEMENTED_INTRINSIC(MathMinLongLong) 10362bcf9bf784a0021630d8fe63d7230d46d6891780Andreas GampeUNIMPLEMENTED_INTRINSIC(MathMaxLongLong) 10372bcf9bf784a0021630d8fe63d7230d46d6891780Andreas GampeUNIMPLEMENTED_INTRINSIC(MathCeil) // Could be done by changing rounding mode, maybe? 10382bcf9bf784a0021630d8fe63d7230d46d6891780Andreas GampeUNIMPLEMENTED_INTRINSIC(MathFloor) // Could be done by changing rounding mode, maybe? 10392bcf9bf784a0021630d8fe63d7230d46d6891780Andreas GampeUNIMPLEMENTED_INTRINSIC(MathRint) 10402bcf9bf784a0021630d8fe63d7230d46d6891780Andreas GampeUNIMPLEMENTED_INTRINSIC(MathRoundDouble) // Could be done by changing rounding mode, maybe? 10412bcf9bf784a0021630d8fe63d7230d46d6891780Andreas GampeUNIMPLEMENTED_INTRINSIC(MathRoundFloat) // Could be done by changing rounding mode, maybe? 10422bcf9bf784a0021630d8fe63d7230d46d6891780Andreas GampeUNIMPLEMENTED_INTRINSIC(UnsafeCASLong) // High register pressure. 10432bcf9bf784a0021630d8fe63d7230d46d6891780Andreas GampeUNIMPLEMENTED_INTRINSIC(SystemArrayCopyChar) 10442bcf9bf784a0021630d8fe63d7230d46d6891780Andreas GampeUNIMPLEMENTED_INTRINSIC(ReferenceGetReferent) 1045848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff HaoUNIMPLEMENTED_INTRINSIC(StringGetCharsNoCheck) 10462bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 10472bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} // namespace arm 10482bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} // namespace art 1049