1701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen/* 2701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen * Copyright (C) 2015 The Android Open Source Project 3701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen * 4701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen * Licensed under the Apache License, Version 2.0 (the "License"); 5701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen * you may not use this file except in compliance with the License. 6701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen * You may obtain a copy of the License at 7701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen * 8701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen * http://www.apache.org/licenses/LICENSE-2.0 9701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen * 10701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen * Unless required by applicable law or agreed to in writing, software 11701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen * distributed under the License is distributed on an "AS IS" BASIS, 12701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen * See the License for the specific language governing permissions and 14701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen * limitations under the License. 15701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen */ 16701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen 17701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen#include "intrinsics_mips.h" 18701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen 19701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen#include "arch/mips/instruction_set_features_mips.h" 20701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen#include "art_method.h" 21701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen#include "code_generator_mips.h" 22701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen#include "entrypoints/quick/quick_entrypoints.h" 23701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen#include "intrinsics.h" 24701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen#include "mirror/array-inl.h" 25701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen#include "mirror/string.h" 26701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen#include "thread.h" 27701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen#include "utils/mips/assembler_mips.h" 28701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen#include "utils/mips/constants_mips.h" 29701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen 30701566aaae098d5aab9d912e2003a18d44fb850dChris Larsennamespace art { 31701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen 32701566aaae098d5aab9d912e2003a18d44fb850dChris Larsennamespace mips { 33701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen 34701566aaae098d5aab9d912e2003a18d44fb850dChris LarsenIntrinsicLocationsBuilderMIPS::IntrinsicLocationsBuilderMIPS(CodeGeneratorMIPS* codegen) 35701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen : arena_(codegen->GetGraph()->GetArena()) { 36701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen} 37701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen 38701566aaae098d5aab9d912e2003a18d44fb850dChris LarsenMipsAssembler* IntrinsicCodeGeneratorMIPS::GetAssembler() { 39701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen return reinterpret_cast<MipsAssembler*>(codegen_->GetAssembler()); 40701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen} 41701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen 42701566aaae098d5aab9d912e2003a18d44fb850dChris LarsenArenaAllocator* IntrinsicCodeGeneratorMIPS::GetAllocator() { 43701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen return codegen_->GetGraph()->GetArena(); 44701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen} 45701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen 46bb9863af3a98622e650de78fb235ab484b50eb1fAlexey Frunzeinline bool IntrinsicCodeGeneratorMIPS::IsR2OrNewer() const { 47e16ce5a52da4fcbb8c6b5d1ec696863fcf113409Chris Larsen return codegen_->GetInstructionSetFeatures().IsMipsIsaRevGreaterThanEqual2(); 48e16ce5a52da4fcbb8c6b5d1ec696863fcf113409Chris Larsen} 49e16ce5a52da4fcbb8c6b5d1ec696863fcf113409Chris Larsen 50bb9863af3a98622e650de78fb235ab484b50eb1fAlexey Frunzeinline bool IntrinsicCodeGeneratorMIPS::IsR6() const { 51e16ce5a52da4fcbb8c6b5d1ec696863fcf113409Chris Larsen return codegen_->GetInstructionSetFeatures().IsR6(); 52e16ce5a52da4fcbb8c6b5d1ec696863fcf113409Chris Larsen} 53e16ce5a52da4fcbb8c6b5d1ec696863fcf113409Chris Larsen 54bb9863af3a98622e650de78fb235ab484b50eb1fAlexey Frunzeinline bool IntrinsicCodeGeneratorMIPS::Is32BitFPU() const { 55bb9863af3a98622e650de78fb235ab484b50eb1fAlexey Frunze return codegen_->GetInstructionSetFeatures().Is32BitFloatingPoint(); 56bb9863af3a98622e650de78fb235ab484b50eb1fAlexey Frunze} 57bb9863af3a98622e650de78fb235ab484b50eb1fAlexey Frunze 58701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen#define __ codegen->GetAssembler()-> 59701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen 60701566aaae098d5aab9d912e2003a18d44fb850dChris Larsenstatic void MoveFromReturnRegister(Location trg, 61701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen Primitive::Type type, 62701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen CodeGeneratorMIPS* codegen) { 63701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen if (!trg.IsValid()) { 64701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen DCHECK_EQ(type, Primitive::kPrimVoid); 65701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen return; 66701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen } 67701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen 68701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen DCHECK_NE(type, Primitive::kPrimVoid); 69701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen 70701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen if (Primitive::IsIntegralType(type) || type == Primitive::kPrimNot) { 71701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen Register trg_reg = trg.AsRegister<Register>(); 72701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen if (trg_reg != V0) { 73701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen __ Move(V0, trg_reg); 74701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen } 75701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen } else { 76701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen FRegister trg_reg = trg.AsFpuRegister<FRegister>(); 77701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen if (trg_reg != F0) { 78701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen if (type == Primitive::kPrimFloat) { 79701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen __ MovS(F0, trg_reg); 80701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen } else { 81701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen __ MovD(F0, trg_reg); 82701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen } 83701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen } 84701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen } 85701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen} 86701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen 87701566aaae098d5aab9d912e2003a18d44fb850dChris Larsenstatic void MoveArguments(HInvoke* invoke, CodeGeneratorMIPS* codegen) { 88701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen InvokeDexCallingConventionVisitorMIPS calling_convention_visitor; 89701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen IntrinsicVisitor::MoveArguments(invoke, codegen, &calling_convention_visitor); 90701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen} 91701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen 92701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen// Slow-path for fallback (calling the managed code to handle the 93701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen// intrinsic) in an intrinsified call. This will copy the arguments 94701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen// into the positions for a regular call. 95701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen// 96701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen// Note: The actual parameters are required to be in the locations 97701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen// given by the invoke's location summary. If an intrinsic 98701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen// modifies those locations before a slowpath call, they must be 99701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen// restored! 100701566aaae098d5aab9d912e2003a18d44fb850dChris Larsenclass IntrinsicSlowPathMIPS : public SlowPathCodeMIPS { 101701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen public: 1029cd6d378bd573cdc14d049d32bdd22a97fa4d84aDavid Srbecky explicit IntrinsicSlowPathMIPS(HInvoke* invoke) : SlowPathCodeMIPS(invoke), invoke_(invoke) { } 103701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen 104701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen void EmitNativeCode(CodeGenerator* codegen_in) OVERRIDE { 105701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen CodeGeneratorMIPS* codegen = down_cast<CodeGeneratorMIPS*>(codegen_in); 106701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen 107701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen __ Bind(GetEntryLabel()); 108701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen 109701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen SaveLiveRegisters(codegen, invoke_->GetLocations()); 110701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen 111701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen MoveArguments(invoke_, codegen); 112701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen 113701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen if (invoke_->IsInvokeStaticOrDirect()) { 114701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen codegen->GenerateStaticOrDirectCall(invoke_->AsInvokeStaticOrDirect(), 115701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen Location::RegisterLocation(A0)); 116701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen } else { 1173acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen codegen->GenerateVirtualCall(invoke_->AsInvokeVirtual(), Location::RegisterLocation(A0)); 118701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen } 1193acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen codegen->RecordPcInfo(invoke_, invoke_->GetDexPc(), this); 120701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen 121701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen // Copy the result back to the expected output. 122701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen Location out = invoke_->GetLocations()->Out(); 123701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen if (out.IsValid()) { 124701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen DCHECK(out.IsRegister()); // TODO: Replace this when we support output in memory. 125701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen DCHECK(!invoke_->GetLocations()->GetLiveRegisters()->ContainsCoreRegister(out.reg())); 126701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen MoveFromReturnRegister(out, invoke_->GetType(), codegen); 127701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen } 128701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen 129701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen RestoreLiveRegisters(codegen, invoke_->GetLocations()); 130701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen __ B(GetExitLabel()); 131701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen } 132701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen 133701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen const char* GetDescription() const OVERRIDE { return "IntrinsicSlowPathMIPS"; } 134701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen 135701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen private: 136701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen // The instruction where this slow path is happening. 137701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen HInvoke* const invoke_; 138701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen 139701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen DISALLOW_COPY_AND_ASSIGN(IntrinsicSlowPathMIPS); 140701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen}; 141701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen 142701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen#undef __ 143701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen 144701566aaae098d5aab9d912e2003a18d44fb850dChris Larsenbool IntrinsicLocationsBuilderMIPS::TryDispatch(HInvoke* invoke) { 145701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen Dispatch(invoke); 146701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen LocationSummary* res = invoke->GetLocations(); 147701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen return res != nullptr && res->Intrinsified(); 148701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen} 149701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen 150701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen#define __ assembler-> 151701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen 1523f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsenstatic void CreateFPToIntLocations(ArenaAllocator* arena, HInvoke* invoke) { 1533f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen LocationSummary* locations = new (arena) LocationSummary(invoke, 1543f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen LocationSummary::kNoCall, 1553f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen kIntrinsified); 1563f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen locations->SetInAt(0, Location::RequiresFpuRegister()); 1573f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen locations->SetOut(Location::RequiresRegister()); 1583f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen} 1593f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen 1603f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsenstatic void MoveFPToInt(LocationSummary* locations, bool is64bit, MipsAssembler* assembler) { 1613f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen FRegister in = locations->InAt(0).AsFpuRegister<FRegister>(); 1623f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen 1633f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen if (is64bit) { 1643f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen Register out_lo = locations->Out().AsRegisterPairLow<Register>(); 1653f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen Register out_hi = locations->Out().AsRegisterPairHigh<Register>(); 1663f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen 1673f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen __ Mfc1(out_lo, in); 168bb9863af3a98622e650de78fb235ab484b50eb1fAlexey Frunze __ MoveFromFpuHigh(out_hi, in); 1693f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen } else { 1703f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen Register out = locations->Out().AsRegister<Register>(); 1713f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen 1723f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen __ Mfc1(out, in); 1733f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen } 1743f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen} 1753f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen 1763f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen// long java.lang.Double.doubleToRawLongBits(double) 1773f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsenvoid IntrinsicLocationsBuilderMIPS::VisitDoubleDoubleToRawLongBits(HInvoke* invoke) { 1783f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen CreateFPToIntLocations(arena_, invoke); 1793f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen} 1803f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen 1813f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsenvoid IntrinsicCodeGeneratorMIPS::VisitDoubleDoubleToRawLongBits(HInvoke* invoke) { 182bf84a3d2aa29c0975b4ac0f6f983d56724b2cc57Roland Levillain MoveFPToInt(invoke->GetLocations(), /* is64bit */ true, GetAssembler()); 1833f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen} 1843f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen 1853f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen// int java.lang.Float.floatToRawIntBits(float) 1863f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsenvoid IntrinsicLocationsBuilderMIPS::VisitFloatFloatToRawIntBits(HInvoke* invoke) { 1873f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen CreateFPToIntLocations(arena_, invoke); 1883f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen} 1893f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen 1903f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsenvoid IntrinsicCodeGeneratorMIPS::VisitFloatFloatToRawIntBits(HInvoke* invoke) { 191bf84a3d2aa29c0975b4ac0f6f983d56724b2cc57Roland Levillain MoveFPToInt(invoke->GetLocations(), /* is64bit */ false, GetAssembler()); 1923f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen} 1933f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen 1943f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsenstatic void CreateIntToFPLocations(ArenaAllocator* arena, HInvoke* invoke) { 1953f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen LocationSummary* locations = new (arena) LocationSummary(invoke, 1963f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen LocationSummary::kNoCall, 1973f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen kIntrinsified); 1983f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen locations->SetInAt(0, Location::RequiresRegister()); 1993f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen locations->SetOut(Location::RequiresFpuRegister()); 2003f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen} 2013f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen 2023f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsenstatic void MoveIntToFP(LocationSummary* locations, bool is64bit, MipsAssembler* assembler) { 2033f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen FRegister out = locations->Out().AsFpuRegister<FRegister>(); 2043f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen 2053f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen if (is64bit) { 2063f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen Register in_lo = locations->InAt(0).AsRegisterPairLow<Register>(); 2073f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen Register in_hi = locations->InAt(0).AsRegisterPairHigh<Register>(); 2083f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen 2093f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen __ Mtc1(in_lo, out); 210bb9863af3a98622e650de78fb235ab484b50eb1fAlexey Frunze __ MoveToFpuHigh(in_hi, out); 2113f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen } else { 2123f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen Register in = locations->InAt(0).AsRegister<Register>(); 2133f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen 2143f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen __ Mtc1(in, out); 2153f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen } 2163f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen} 2173f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen 2183f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen// double java.lang.Double.longBitsToDouble(long) 2193f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsenvoid IntrinsicLocationsBuilderMIPS::VisitDoubleLongBitsToDouble(HInvoke* invoke) { 2203f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen CreateIntToFPLocations(arena_, invoke); 2213f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen} 2223f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen 2233f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsenvoid IntrinsicCodeGeneratorMIPS::VisitDoubleLongBitsToDouble(HInvoke* invoke) { 224bf84a3d2aa29c0975b4ac0f6f983d56724b2cc57Roland Levillain MoveIntToFP(invoke->GetLocations(), /* is64bit */ true, GetAssembler()); 2253f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen} 2263f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen 2273f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen// float java.lang.Float.intBitsToFloat(int) 2283f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsenvoid IntrinsicLocationsBuilderMIPS::VisitFloatIntBitsToFloat(HInvoke* invoke) { 2293f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen CreateIntToFPLocations(arena_, invoke); 2303f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen} 2313f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen 2323f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsenvoid IntrinsicCodeGeneratorMIPS::VisitFloatIntBitsToFloat(HInvoke* invoke) { 233bf84a3d2aa29c0975b4ac0f6f983d56724b2cc57Roland Levillain MoveIntToFP(invoke->GetLocations(), /* is64bit */ false, GetAssembler()); 2343f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen} 2353f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen 2368682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsenstatic void CreateIntToIntLocations(ArenaAllocator* arena, 2378682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsen HInvoke* invoke, 2388682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsen Location::OutputOverlap overlaps = Location::kNoOutputOverlap) { 2393f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen LocationSummary* locations = new (arena) LocationSummary(invoke, 2403f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen LocationSummary::kNoCall, 2413f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen kIntrinsified); 2423f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen locations->SetInAt(0, Location::RequiresRegister()); 2438682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsen locations->SetOut(Location::RequiresRegister(), overlaps); 2443f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen} 2453f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen 24670014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsenstatic void GenReverse(LocationSummary* locations, 24770014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen Primitive::Type type, 24870014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen bool isR2OrNewer, 24970014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen bool isR6, 25070014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen bool reverseBits, 25170014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen MipsAssembler* assembler) { 2523f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen DCHECK(type == Primitive::kPrimShort || 2533f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen type == Primitive::kPrimInt || 2543f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen type == Primitive::kPrimLong); 25570014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen DCHECK(type != Primitive::kPrimShort || !reverseBits); 2563f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen 2573f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen if (type == Primitive::kPrimShort) { 2583f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen Register in = locations->InAt(0).AsRegister<Register>(); 2593f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen Register out = locations->Out().AsRegister<Register>(); 2603f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen 2613f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen if (isR2OrNewer) { 2623f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen __ Wsbh(out, in); 2633f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen __ Seh(out, out); 2643f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen } else { 2653f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen __ Sll(TMP, in, 24); 2663f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen __ Sra(TMP, TMP, 16); 2673f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen __ Sll(out, in, 16); 2683f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen __ Srl(out, out, 24); 2693f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen __ Or(out, out, TMP); 2703f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen } 2713f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen } else if (type == Primitive::kPrimInt) { 2723f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen Register in = locations->InAt(0).AsRegister<Register>(); 2733f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen Register out = locations->Out().AsRegister<Register>(); 2743f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen 2753f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen if (isR2OrNewer) { 2763f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen __ Rotr(out, in, 16); 2773f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen __ Wsbh(out, out); 2783f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen } else { 2793f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen // MIPS32r1 2803f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen // __ Rotr(out, in, 16); 2813f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen __ Sll(TMP, in, 16); 2823f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen __ Srl(out, in, 16); 2833f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen __ Or(out, out, TMP); 2843f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen // __ Wsbh(out, out); 2853f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen __ LoadConst32(AT, 0x00FF00FF); 2863f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen __ And(TMP, out, AT); 2873f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen __ Sll(TMP, TMP, 8); 2883f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen __ Srl(out, out, 8); 2893f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen __ And(out, out, AT); 2903f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen __ Or(out, out, TMP); 2913f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen } 29270014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen if (reverseBits) { 29370014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen if (isR6) { 29470014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen __ Bitswap(out, out); 29570014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen } else { 29670014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen __ LoadConst32(AT, 0x0F0F0F0F); 29770014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen __ And(TMP, out, AT); 29870014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen __ Sll(TMP, TMP, 4); 29970014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen __ Srl(out, out, 4); 30070014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen __ And(out, out, AT); 30170014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen __ Or(out, TMP, out); 30270014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen __ LoadConst32(AT, 0x33333333); 30370014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen __ And(TMP, out, AT); 30470014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen __ Sll(TMP, TMP, 2); 30570014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen __ Srl(out, out, 2); 30670014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen __ And(out, out, AT); 30770014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen __ Or(out, TMP, out); 30870014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen __ LoadConst32(AT, 0x55555555); 30970014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen __ And(TMP, out, AT); 31070014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen __ Sll(TMP, TMP, 1); 31170014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen __ Srl(out, out, 1); 31270014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen __ And(out, out, AT); 31370014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen __ Or(out, TMP, out); 31470014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen } 31570014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen } 3163f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen } else if (type == Primitive::kPrimLong) { 3173f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen Register in_lo = locations->InAt(0).AsRegisterPairLow<Register>(); 3183f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen Register in_hi = locations->InAt(0).AsRegisterPairHigh<Register>(); 3193f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen Register out_lo = locations->Out().AsRegisterPairLow<Register>(); 3203f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen Register out_hi = locations->Out().AsRegisterPairHigh<Register>(); 3213f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen 3223f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen if (isR2OrNewer) { 3233f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen __ Rotr(AT, in_hi, 16); 3243f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen __ Rotr(TMP, in_lo, 16); 3253f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen __ Wsbh(out_lo, AT); 3263f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen __ Wsbh(out_hi, TMP); 3273f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen } else { 3283f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen // When calling CreateIntToIntLocations() we promised that the 3293f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen // use of the out_lo/out_hi wouldn't overlap with the use of 3303f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen // in_lo/in_hi. Be very careful not to write to out_lo/out_hi 3313f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen // until we're completely done reading from in_lo/in_hi. 3323f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen // __ Rotr(TMP, in_lo, 16); 3333f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen __ Sll(TMP, in_lo, 16); 3343f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen __ Srl(AT, in_lo, 16); 3353f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen __ Or(TMP, TMP, AT); // Hold in TMP until it's safe 3363f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen // to write to out_hi. 3373f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen // __ Rotr(out_lo, in_hi, 16); 3383f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen __ Sll(AT, in_hi, 16); 3393f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen __ Srl(out_lo, in_hi, 16); // Here we are finally done reading 3403f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen // from in_lo/in_hi so it's okay to 3413f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen // write to out_lo/out_hi. 3423f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen __ Or(out_lo, out_lo, AT); 3433f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen // __ Wsbh(out_hi, out_hi); 3443f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen __ LoadConst32(AT, 0x00FF00FF); 3453f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen __ And(out_hi, TMP, AT); 3463f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen __ Sll(out_hi, out_hi, 8); 3473f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen __ Srl(TMP, TMP, 8); 3483f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen __ And(TMP, TMP, AT); 3493f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen __ Or(out_hi, out_hi, TMP); 3503f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen // __ Wsbh(out_lo, out_lo); 3513f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen __ And(TMP, out_lo, AT); // AT already holds the correct mask value 3523f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen __ Sll(TMP, TMP, 8); 3533f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen __ Srl(out_lo, out_lo, 8); 3543f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen __ And(out_lo, out_lo, AT); 3553f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen __ Or(out_lo, out_lo, TMP); 3563f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen } 35770014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen if (reverseBits) { 35870014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen if (isR6) { 35970014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen __ Bitswap(out_hi, out_hi); 36070014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen __ Bitswap(out_lo, out_lo); 36170014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen } else { 36270014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen __ LoadConst32(AT, 0x0F0F0F0F); 36370014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen __ And(TMP, out_hi, AT); 36470014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen __ Sll(TMP, TMP, 4); 36570014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen __ Srl(out_hi, out_hi, 4); 36670014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen __ And(out_hi, out_hi, AT); 36770014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen __ Or(out_hi, TMP, out_hi); 36870014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen __ And(TMP, out_lo, AT); 36970014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen __ Sll(TMP, TMP, 4); 37070014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen __ Srl(out_lo, out_lo, 4); 37170014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen __ And(out_lo, out_lo, AT); 37270014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen __ Or(out_lo, TMP, out_lo); 37370014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen __ LoadConst32(AT, 0x33333333); 37470014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen __ And(TMP, out_hi, AT); 37570014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen __ Sll(TMP, TMP, 2); 37670014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen __ Srl(out_hi, out_hi, 2); 37770014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen __ And(out_hi, out_hi, AT); 37870014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen __ Or(out_hi, TMP, out_hi); 37970014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen __ And(TMP, out_lo, AT); 38070014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen __ Sll(TMP, TMP, 2); 38170014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen __ Srl(out_lo, out_lo, 2); 38270014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen __ And(out_lo, out_lo, AT); 38370014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen __ Or(out_lo, TMP, out_lo); 38470014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen __ LoadConst32(AT, 0x55555555); 38570014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen __ And(TMP, out_hi, AT); 38670014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen __ Sll(TMP, TMP, 1); 38770014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen __ Srl(out_hi, out_hi, 1); 38870014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen __ And(out_hi, out_hi, AT); 38970014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen __ Or(out_hi, TMP, out_hi); 39070014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen __ And(TMP, out_lo, AT); 39170014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen __ Sll(TMP, TMP, 1); 39270014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen __ Srl(out_lo, out_lo, 1); 39370014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen __ And(out_lo, out_lo, AT); 39470014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen __ Or(out_lo, TMP, out_lo); 39570014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen } 39670014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen } 3973f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen } 3983f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen} 3993f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen 4003f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen// int java.lang.Integer.reverseBytes(int) 4013f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsenvoid IntrinsicLocationsBuilderMIPS::VisitIntegerReverseBytes(HInvoke* invoke) { 4023f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen CreateIntToIntLocations(arena_, invoke); 4033f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen} 4043f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen 4053f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsenvoid IntrinsicCodeGeneratorMIPS::VisitIntegerReverseBytes(HInvoke* invoke) { 40670014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen GenReverse(invoke->GetLocations(), 40770014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen Primitive::kPrimInt, 408e16ce5a52da4fcbb8c6b5d1ec696863fcf113409Chris Larsen IsR2OrNewer(), 409e16ce5a52da4fcbb8c6b5d1ec696863fcf113409Chris Larsen IsR6(), 410b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen /* reverseBits */ false, 41170014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen GetAssembler()); 4123f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen} 4133f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen 4143f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen// long java.lang.Long.reverseBytes(long) 4153f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsenvoid IntrinsicLocationsBuilderMIPS::VisitLongReverseBytes(HInvoke* invoke) { 4163f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen CreateIntToIntLocations(arena_, invoke); 4173f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen} 4183f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen 4193f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsenvoid IntrinsicCodeGeneratorMIPS::VisitLongReverseBytes(HInvoke* invoke) { 42070014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen GenReverse(invoke->GetLocations(), 42170014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen Primitive::kPrimLong, 422e16ce5a52da4fcbb8c6b5d1ec696863fcf113409Chris Larsen IsR2OrNewer(), 423e16ce5a52da4fcbb8c6b5d1ec696863fcf113409Chris Larsen IsR6(), 424b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen /* reverseBits */ false, 42570014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen GetAssembler()); 4263f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen} 4273f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen 4283f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen// short java.lang.Short.reverseBytes(short) 4293f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsenvoid IntrinsicLocationsBuilderMIPS::VisitShortReverseBytes(HInvoke* invoke) { 4303f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen CreateIntToIntLocations(arena_, invoke); 4313f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen} 4323f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen 4333f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsenvoid IntrinsicCodeGeneratorMIPS::VisitShortReverseBytes(HInvoke* invoke) { 43470014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen GenReverse(invoke->GetLocations(), 43570014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen Primitive::kPrimShort, 436e16ce5a52da4fcbb8c6b5d1ec696863fcf113409Chris Larsen IsR2OrNewer(), 437e16ce5a52da4fcbb8c6b5d1ec696863fcf113409Chris Larsen IsR6(), 438b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen /* reverseBits */ false, 43970014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen GetAssembler()); 44070014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen} 44170014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen 442e384547851a9d9e5d89ae5bb4c16bfd7d93cc12eChris Larsenstatic void GenNumberOfLeadingZeroes(LocationSummary* locations, 443e384547851a9d9e5d89ae5bb4c16bfd7d93cc12eChris Larsen bool is64bit, 444e384547851a9d9e5d89ae5bb4c16bfd7d93cc12eChris Larsen bool isR6, 445e384547851a9d9e5d89ae5bb4c16bfd7d93cc12eChris Larsen MipsAssembler* assembler) { 446e384547851a9d9e5d89ae5bb4c16bfd7d93cc12eChris Larsen Register out = locations->Out().AsRegister<Register>(); 447e384547851a9d9e5d89ae5bb4c16bfd7d93cc12eChris Larsen if (is64bit) { 448e384547851a9d9e5d89ae5bb4c16bfd7d93cc12eChris Larsen Register in_lo = locations->InAt(0).AsRegisterPairLow<Register>(); 449e384547851a9d9e5d89ae5bb4c16bfd7d93cc12eChris Larsen Register in_hi = locations->InAt(0).AsRegisterPairHigh<Register>(); 450e384547851a9d9e5d89ae5bb4c16bfd7d93cc12eChris Larsen 451e384547851a9d9e5d89ae5bb4c16bfd7d93cc12eChris Larsen if (isR6) { 452e384547851a9d9e5d89ae5bb4c16bfd7d93cc12eChris Larsen __ ClzR6(AT, in_hi); 453e384547851a9d9e5d89ae5bb4c16bfd7d93cc12eChris Larsen __ ClzR6(TMP, in_lo); 454e384547851a9d9e5d89ae5bb4c16bfd7d93cc12eChris Larsen __ Seleqz(TMP, TMP, in_hi); 455e384547851a9d9e5d89ae5bb4c16bfd7d93cc12eChris Larsen } else { 456e384547851a9d9e5d89ae5bb4c16bfd7d93cc12eChris Larsen __ ClzR2(AT, in_hi); 457e384547851a9d9e5d89ae5bb4c16bfd7d93cc12eChris Larsen __ ClzR2(TMP, in_lo); 458e384547851a9d9e5d89ae5bb4c16bfd7d93cc12eChris Larsen __ Movn(TMP, ZERO, in_hi); 459e384547851a9d9e5d89ae5bb4c16bfd7d93cc12eChris Larsen } 460e384547851a9d9e5d89ae5bb4c16bfd7d93cc12eChris Larsen __ Addu(out, AT, TMP); 461e384547851a9d9e5d89ae5bb4c16bfd7d93cc12eChris Larsen } else { 462e384547851a9d9e5d89ae5bb4c16bfd7d93cc12eChris Larsen Register in = locations->InAt(0).AsRegister<Register>(); 463e384547851a9d9e5d89ae5bb4c16bfd7d93cc12eChris Larsen 464e384547851a9d9e5d89ae5bb4c16bfd7d93cc12eChris Larsen if (isR6) { 465e384547851a9d9e5d89ae5bb4c16bfd7d93cc12eChris Larsen __ ClzR6(out, in); 466e384547851a9d9e5d89ae5bb4c16bfd7d93cc12eChris Larsen } else { 467e384547851a9d9e5d89ae5bb4c16bfd7d93cc12eChris Larsen __ ClzR2(out, in); 468e384547851a9d9e5d89ae5bb4c16bfd7d93cc12eChris Larsen } 469e384547851a9d9e5d89ae5bb4c16bfd7d93cc12eChris Larsen } 470e384547851a9d9e5d89ae5bb4c16bfd7d93cc12eChris Larsen} 471e384547851a9d9e5d89ae5bb4c16bfd7d93cc12eChris Larsen 472e384547851a9d9e5d89ae5bb4c16bfd7d93cc12eChris Larsen// int java.lang.Integer.numberOfLeadingZeros(int i) 473e384547851a9d9e5d89ae5bb4c16bfd7d93cc12eChris Larsenvoid IntrinsicLocationsBuilderMIPS::VisitIntegerNumberOfLeadingZeros(HInvoke* invoke) { 474e384547851a9d9e5d89ae5bb4c16bfd7d93cc12eChris Larsen CreateIntToIntLocations(arena_, invoke); 475e384547851a9d9e5d89ae5bb4c16bfd7d93cc12eChris Larsen} 476e384547851a9d9e5d89ae5bb4c16bfd7d93cc12eChris Larsen 477e384547851a9d9e5d89ae5bb4c16bfd7d93cc12eChris Larsenvoid IntrinsicCodeGeneratorMIPS::VisitIntegerNumberOfLeadingZeros(HInvoke* invoke) { 478b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen GenNumberOfLeadingZeroes(invoke->GetLocations(), /* is64bit */ false, IsR6(), GetAssembler()); 479e384547851a9d9e5d89ae5bb4c16bfd7d93cc12eChris Larsen} 480e384547851a9d9e5d89ae5bb4c16bfd7d93cc12eChris Larsen 481e384547851a9d9e5d89ae5bb4c16bfd7d93cc12eChris Larsen// int java.lang.Long.numberOfLeadingZeros(long i) 482e384547851a9d9e5d89ae5bb4c16bfd7d93cc12eChris Larsenvoid IntrinsicLocationsBuilderMIPS::VisitLongNumberOfLeadingZeros(HInvoke* invoke) { 483e384547851a9d9e5d89ae5bb4c16bfd7d93cc12eChris Larsen CreateIntToIntLocations(arena_, invoke); 484e384547851a9d9e5d89ae5bb4c16bfd7d93cc12eChris Larsen} 485e384547851a9d9e5d89ae5bb4c16bfd7d93cc12eChris Larsen 486e384547851a9d9e5d89ae5bb4c16bfd7d93cc12eChris Larsenvoid IntrinsicCodeGeneratorMIPS::VisitLongNumberOfLeadingZeros(HInvoke* invoke) { 487b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen GenNumberOfLeadingZeroes(invoke->GetLocations(), /* is64bit */ true, IsR6(), GetAssembler()); 488e384547851a9d9e5d89ae5bb4c16bfd7d93cc12eChris Larsen} 489e384547851a9d9e5d89ae5bb4c16bfd7d93cc12eChris Larsen 4908682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsenstatic void GenNumberOfTrailingZeroes(LocationSummary* locations, 4918682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsen bool is64bit, 4928682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsen bool isR6, 4938682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsen MipsAssembler* assembler) { 4948682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsen Register out = locations->Out().AsRegister<Register>(); 4958682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsen Register in_lo; 4968682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsen Register in; 4978682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsen 4988682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsen if (is64bit) { 4998682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsen Register in_hi = locations->InAt(0).AsRegisterPairHigh<Register>(); 5008682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsen 5018682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsen in_lo = locations->InAt(0).AsRegisterPairLow<Register>(); 5028682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsen 5038682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsen // If in_lo is zero then count the number of trailing zeroes in in_hi; 5048682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsen // otherwise count the number of trailing zeroes in in_lo. 505bbb2ebedfa5bf66513beb83f17f21fe6ac83fd0eChris Larsen // out = in_lo ? in_lo : in_hi; 5068682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsen if (isR6) { 5078682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsen __ Seleqz(out, in_hi, in_lo); 5088682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsen __ Selnez(TMP, in_lo, in_lo); 5098682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsen __ Or(out, out, TMP); 5108682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsen } else { 5118682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsen __ Movz(out, in_hi, in_lo); 5128682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsen __ Movn(out, in_lo, in_lo); 5138682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsen } 5148682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsen 5158682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsen in = out; 5168682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsen } else { 5178682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsen in = locations->InAt(0).AsRegister<Register>(); 5188682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsen // Give in_lo a dummy value to keep the compiler from complaining. 5198682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsen // Since we only get here in the 32-bit case, this value will never 5208682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsen // be used. 5218682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsen in_lo = in; 5228682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsen } 5238682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsen 524bbb2ebedfa5bf66513beb83f17f21fe6ac83fd0eChris Larsen if (isR6) { 525bbb2ebedfa5bf66513beb83f17f21fe6ac83fd0eChris Larsen // We don't have an instruction to count the number of trailing zeroes. 526bbb2ebedfa5bf66513beb83f17f21fe6ac83fd0eChris Larsen // Start by flipping the bits end-for-end so we can count the number of 527bbb2ebedfa5bf66513beb83f17f21fe6ac83fd0eChris Larsen // leading zeroes instead. 5288682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsen __ Rotr(out, in, 16); 5298682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsen __ Wsbh(out, out); 5308682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsen __ Bitswap(out, out); 5318682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsen __ ClzR6(out, out); 5328682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsen } else { 533bbb2ebedfa5bf66513beb83f17f21fe6ac83fd0eChris Larsen // Convert trailing zeroes to trailing ones, and bits to their left 534bbb2ebedfa5bf66513beb83f17f21fe6ac83fd0eChris Larsen // to zeroes. 535bbb2ebedfa5bf66513beb83f17f21fe6ac83fd0eChris Larsen __ Addiu(TMP, in, -1); 536bbb2ebedfa5bf66513beb83f17f21fe6ac83fd0eChris Larsen __ Xor(out, TMP, in); 537bbb2ebedfa5bf66513beb83f17f21fe6ac83fd0eChris Larsen __ And(out, out, TMP); 538bbb2ebedfa5bf66513beb83f17f21fe6ac83fd0eChris Larsen // Count number of leading zeroes. 5398682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsen __ ClzR2(out, out); 540bbb2ebedfa5bf66513beb83f17f21fe6ac83fd0eChris Larsen // Subtract number of leading zeroes from 32 to get number of trailing ones. 541bbb2ebedfa5bf66513beb83f17f21fe6ac83fd0eChris Larsen // Remember that the trailing ones were formerly trailing zeroes. 542bbb2ebedfa5bf66513beb83f17f21fe6ac83fd0eChris Larsen __ LoadConst32(TMP, 32); 543bbb2ebedfa5bf66513beb83f17f21fe6ac83fd0eChris Larsen __ Subu(out, TMP, out); 5448682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsen } 5458682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsen 5468682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsen if (is64bit) { 5478682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsen // If in_lo is zero, then we counted the number of trailing zeroes in in_hi so we must add the 5488682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsen // number of trailing zeroes in in_lo (32) to get the correct final count 5498682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsen __ LoadConst32(TMP, 32); 5508682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsen if (isR6) { 5518682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsen __ Seleqz(TMP, TMP, in_lo); 5528682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsen } else { 5538682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsen __ Movn(TMP, ZERO, in_lo); 5548682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsen } 5558682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsen __ Addu(out, out, TMP); 5568682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsen } 5578682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsen} 5588682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsen 5598682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsen// int java.lang.Integer.numberOfTrailingZeros(int i) 5608682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsenvoid IntrinsicLocationsBuilderMIPS::VisitIntegerNumberOfTrailingZeros(HInvoke* invoke) { 5618682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsen CreateIntToIntLocations(arena_, invoke, Location::kOutputOverlap); 5628682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsen} 5638682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsen 5648682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsenvoid IntrinsicCodeGeneratorMIPS::VisitIntegerNumberOfTrailingZeros(HInvoke* invoke) { 565bbb2ebedfa5bf66513beb83f17f21fe6ac83fd0eChris Larsen GenNumberOfTrailingZeroes(invoke->GetLocations(), /* is64bit */ false, IsR6(), GetAssembler()); 5668682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsen} 5678682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsen 5688682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsen// int java.lang.Long.numberOfTrailingZeros(long i) 5698682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsenvoid IntrinsicLocationsBuilderMIPS::VisitLongNumberOfTrailingZeros(HInvoke* invoke) { 5708682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsen CreateIntToIntLocations(arena_, invoke, Location::kOutputOverlap); 5718682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsen} 5728682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsen 5738682960da00c013f8955985b8e9bb6c55b3f3bacChris Larsenvoid IntrinsicCodeGeneratorMIPS::VisitLongNumberOfTrailingZeros(HInvoke* invoke) { 574bbb2ebedfa5bf66513beb83f17f21fe6ac83fd0eChris Larsen GenNumberOfTrailingZeroes(invoke->GetLocations(), /* is64bit */ true, IsR6(), GetAssembler()); 575e16ce5a52da4fcbb8c6b5d1ec696863fcf113409Chris Larsen} 576e16ce5a52da4fcbb8c6b5d1ec696863fcf113409Chris Larsen 57770014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen// int java.lang.Integer.reverse(int) 57870014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsenvoid IntrinsicLocationsBuilderMIPS::VisitIntegerReverse(HInvoke* invoke) { 57970014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen CreateIntToIntLocations(arena_, invoke); 58070014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen} 58170014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen 58270014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsenvoid IntrinsicCodeGeneratorMIPS::VisitIntegerReverse(HInvoke* invoke) { 58370014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen GenReverse(invoke->GetLocations(), 58470014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen Primitive::kPrimInt, 585e16ce5a52da4fcbb8c6b5d1ec696863fcf113409Chris Larsen IsR2OrNewer(), 586e16ce5a52da4fcbb8c6b5d1ec696863fcf113409Chris Larsen IsR6(), 587b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen /* reverseBits */ true, 58870014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen GetAssembler()); 58970014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen} 59070014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen 59170014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen// long java.lang.Long.reverse(long) 59270014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsenvoid IntrinsicLocationsBuilderMIPS::VisitLongReverse(HInvoke* invoke) { 59370014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen CreateIntToIntLocations(arena_, invoke); 59470014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen} 59570014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen 59670014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsenvoid IntrinsicCodeGeneratorMIPS::VisitLongReverse(HInvoke* invoke) { 59770014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen GenReverse(invoke->GetLocations(), 59870014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen Primitive::kPrimLong, 599e16ce5a52da4fcbb8c6b5d1ec696863fcf113409Chris Larsen IsR2OrNewer(), 600e16ce5a52da4fcbb8c6b5d1ec696863fcf113409Chris Larsen IsR6(), 601b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen /* reverseBits */ true, 60270014c8af8d3a20c2987c308788bc86671bc39e9Chris Larsen GetAssembler()); 6033f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen} 6043f8bf65f36e14650bb6eb6876a42d9344a9d64d9Chris Larsen 605b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsenstatic void CreateFPToFPLocations(ArenaAllocator* arena, HInvoke* invoke) { 606b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen LocationSummary* locations = new (arena) LocationSummary(invoke, 607b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen LocationSummary::kNoCall, 608b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen kIntrinsified); 609b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen locations->SetInAt(0, Location::RequiresFpuRegister()); 610b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap); 611b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen} 612b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 613edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsenstatic void GenBitCount(LocationSummary* locations, 614edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen Primitive::Type type, 615edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen bool isR6, 616edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen MipsAssembler* assembler) { 617edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen Register out = locations->Out().AsRegister<Register>(); 618edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen 619edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen // https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel 620edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen // 621edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen // A generalization of the best bit counting method to integers of 622edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen // bit-widths up to 128 (parameterized by type T) is this: 623edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen // 624edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen // v = v - ((v >> 1) & (T)~(T)0/3); // temp 625edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen // v = (v & (T)~(T)0/15*3) + ((v >> 2) & (T)~(T)0/15*3); // temp 626edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen // v = (v + (v >> 4)) & (T)~(T)0/255*15; // temp 627edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen // c = (T)(v * ((T)~(T)0/255)) >> (sizeof(T) - 1) * BITS_PER_BYTE; // count 628edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen // 629edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen // For comparison, for 32-bit quantities, this algorithm can be executed 630edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen // using 20 MIPS instructions (the calls to LoadConst32() generate two 631edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen // machine instructions each for the values being used in this algorithm). 632edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen // A(n unrolled) loop-based algorithm required 25 instructions. 633edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen // 634edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen // For 64-bit quantities, this algorithm gets executed twice, (once 635edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen // for in_lo, and again for in_hi), but saves a few instructions 636edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen // because the mask values only have to be loaded once. Using this 637edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen // algorithm the count for a 64-bit operand can be performed in 33 638edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen // instructions compared to a loop-based algorithm which required 47 639edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen // instructions. 640edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen 641edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen if (type == Primitive::kPrimInt) { 642edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen Register in = locations->InAt(0).AsRegister<Register>(); 643edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen 644edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen __ Srl(TMP, in, 1); 645edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen __ LoadConst32(AT, 0x55555555); 646edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen __ And(TMP, TMP, AT); 647edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen __ Subu(TMP, in, TMP); 648edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen __ LoadConst32(AT, 0x33333333); 649edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen __ And(out, TMP, AT); 650edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen __ Srl(TMP, TMP, 2); 651edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen __ And(TMP, TMP, AT); 652edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen __ Addu(TMP, out, TMP); 653edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen __ Srl(out, TMP, 4); 654edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen __ Addu(out, out, TMP); 655edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen __ LoadConst32(AT, 0x0F0F0F0F); 656edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen __ And(out, out, AT); 657edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen __ LoadConst32(TMP, 0x01010101); 658edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen if (isR6) { 659edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen __ MulR6(out, out, TMP); 660edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen } else { 661edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen __ MulR2(out, out, TMP); 662edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen } 663edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen __ Srl(out, out, 24); 664fa3912edfac60a9f0a9b95a5862c7361b403fcc2Roland Levillain } else { 665fa3912edfac60a9f0a9b95a5862c7361b403fcc2Roland Levillain DCHECK_EQ(type, Primitive::kPrimLong); 666edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen Register in_lo = locations->InAt(0).AsRegisterPairLow<Register>(); 667edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen Register in_hi = locations->InAt(0).AsRegisterPairHigh<Register>(); 668edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen Register tmp_hi = locations->GetTemp(0).AsRegister<Register>(); 669edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen Register out_hi = locations->GetTemp(1).AsRegister<Register>(); 670edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen Register tmp_lo = TMP; 671edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen Register out_lo = out; 672edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen 673edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen __ Srl(tmp_lo, in_lo, 1); 674edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen __ Srl(tmp_hi, in_hi, 1); 675edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen 676edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen __ LoadConst32(AT, 0x55555555); 677edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen 678edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen __ And(tmp_lo, tmp_lo, AT); 679edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen __ Subu(tmp_lo, in_lo, tmp_lo); 680edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen 681edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen __ And(tmp_hi, tmp_hi, AT); 682edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen __ Subu(tmp_hi, in_hi, tmp_hi); 683edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen 684edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen __ LoadConst32(AT, 0x33333333); 685edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen 686edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen __ And(out_lo, tmp_lo, AT); 687edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen __ Srl(tmp_lo, tmp_lo, 2); 688edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen __ And(tmp_lo, tmp_lo, AT); 689edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen __ Addu(tmp_lo, out_lo, tmp_lo); 690edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen __ Srl(out_lo, tmp_lo, 4); 691edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen __ Addu(out_lo, out_lo, tmp_lo); 692edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen 693edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen __ And(out_hi, tmp_hi, AT); 694edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen __ Srl(tmp_hi, tmp_hi, 2); 695edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen __ And(tmp_hi, tmp_hi, AT); 696edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen __ Addu(tmp_hi, out_hi, tmp_hi); 697edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen __ Srl(out_hi, tmp_hi, 4); 698edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen __ Addu(out_hi, out_hi, tmp_hi); 699edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen 700edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen __ LoadConst32(AT, 0x0F0F0F0F); 701edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen 702edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen __ And(out_lo, out_lo, AT); 703edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen __ And(out_hi, out_hi, AT); 704edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen 705edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen __ LoadConst32(AT, 0x01010101); 706edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen 707edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen if (isR6) { 708edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen __ MulR6(out_lo, out_lo, AT); 709edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen 710edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen __ MulR6(out_hi, out_hi, AT); 711edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen } else { 712edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen __ MulR2(out_lo, out_lo, AT); 713edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen 714edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen __ MulR2(out_hi, out_hi, AT); 715edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen } 716edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen 717edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen __ Srl(out_lo, out_lo, 24); 718edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen __ Srl(out_hi, out_hi, 24); 719edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen 720edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen __ Addu(out, out_hi, out_lo); 721edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen } 722edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen} 723edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen 724edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen// int java.lang.Integer.bitCount(int) 725edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsenvoid IntrinsicLocationsBuilderMIPS::VisitIntegerBitCount(HInvoke* invoke) { 726edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen CreateIntToIntLocations(arena_, invoke); 727edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen} 728edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen 729edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsenvoid IntrinsicCodeGeneratorMIPS::VisitIntegerBitCount(HInvoke* invoke) { 730edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen GenBitCount(invoke->GetLocations(), Primitive::kPrimInt, IsR6(), GetAssembler()); 731edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen} 732edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen 733edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen// int java.lang.Long.bitCount(int) 734edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsenvoid IntrinsicLocationsBuilderMIPS::VisitLongBitCount(HInvoke* invoke) { 735edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen LocationSummary* locations = new (arena_) LocationSummary(invoke, 736edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen LocationSummary::kNoCall, 737edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen kIntrinsified); 738edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen locations->SetInAt(0, Location::RequiresRegister()); 739edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen locations->SetOut(Location::RequiresRegister()); 740edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen locations->AddTemp(Location::RequiresRegister()); 741edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen locations->AddTemp(Location::RequiresRegister()); 742edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen} 743edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen 744edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsenvoid IntrinsicCodeGeneratorMIPS::VisitLongBitCount(HInvoke* invoke) { 745edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen GenBitCount(invoke->GetLocations(), Primitive::kPrimLong, IsR6(), GetAssembler()); 746edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen} 747edc16451dc62df5487a49f62aec36f9c1df77d30Chris Larsen 748b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsenstatic void MathAbsFP(LocationSummary* locations, bool is64bit, MipsAssembler* assembler) { 749b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen FRegister in = locations->InAt(0).AsFpuRegister<FRegister>(); 750b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen FRegister out = locations->Out().AsFpuRegister<FRegister>(); 751b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 752b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen if (is64bit) { 753b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ AbsD(out, in); 754b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } else { 755b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ AbsS(out, in); 756b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } 757b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen} 758b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 759b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen// double java.lang.Math.abs(double) 760b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsenvoid IntrinsicLocationsBuilderMIPS::VisitMathAbsDouble(HInvoke* invoke) { 761b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen CreateFPToFPLocations(arena_, invoke); 762b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen} 763b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 764b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsenvoid IntrinsicCodeGeneratorMIPS::VisitMathAbsDouble(HInvoke* invoke) { 765b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen MathAbsFP(invoke->GetLocations(), /* is64bit */ true, GetAssembler()); 766b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen} 767b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 768b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen// float java.lang.Math.abs(float) 769b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsenvoid IntrinsicLocationsBuilderMIPS::VisitMathAbsFloat(HInvoke* invoke) { 770b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen CreateFPToFPLocations(arena_, invoke); 771b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen} 772b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 773b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsenvoid IntrinsicCodeGeneratorMIPS::VisitMathAbsFloat(HInvoke* invoke) { 774b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen MathAbsFP(invoke->GetLocations(), /* is64bit */ false, GetAssembler()); 775b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen} 776b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 777b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsenstatic void GenAbsInteger(LocationSummary* locations, bool is64bit, MipsAssembler* assembler) { 778b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen if (is64bit) { 779b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen Register in_lo = locations->InAt(0).AsRegisterPairLow<Register>(); 780b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen Register in_hi = locations->InAt(0).AsRegisterPairHigh<Register>(); 781b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen Register out_lo = locations->Out().AsRegisterPairLow<Register>(); 782b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen Register out_hi = locations->Out().AsRegisterPairHigh<Register>(); 783b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 784b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen // The comments in this section show the analogous operations which would 785b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen // be performed if we had 64-bit registers "in", and "out". 786b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen // __ Dsra32(AT, in, 31); 787b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Sra(AT, in_hi, 31); 788b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen // __ Xor(out, in, AT); 789b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Xor(TMP, in_lo, AT); 790b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Xor(out_hi, in_hi, AT); 791b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen // __ Dsubu(out, out, AT); 792b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Subu(out_lo, TMP, AT); 793b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Sltu(TMP, out_lo, TMP); 794b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Addu(out_hi, out_hi, TMP); 795b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } else { 796b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen Register in = locations->InAt(0).AsRegister<Register>(); 797b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen Register out = locations->Out().AsRegister<Register>(); 798b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 799b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Sra(AT, in, 31); 800b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Xor(out, in, AT); 801b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Subu(out, out, AT); 802b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } 803b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen} 804b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 805b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen// int java.lang.Math.abs(int) 806b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsenvoid IntrinsicLocationsBuilderMIPS::VisitMathAbsInt(HInvoke* invoke) { 807b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen CreateIntToIntLocations(arena_, invoke); 808b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen} 809b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 810b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsenvoid IntrinsicCodeGeneratorMIPS::VisitMathAbsInt(HInvoke* invoke) { 811b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen GenAbsInteger(invoke->GetLocations(), /* is64bit */ false, GetAssembler()); 812b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen} 813b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 814b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen// long java.lang.Math.abs(long) 815b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsenvoid IntrinsicLocationsBuilderMIPS::VisitMathAbsLong(HInvoke* invoke) { 816b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen CreateIntToIntLocations(arena_, invoke); 817b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen} 818b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 819b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsenvoid IntrinsicCodeGeneratorMIPS::VisitMathAbsLong(HInvoke* invoke) { 820b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen GenAbsInteger(invoke->GetLocations(), /* is64bit */ true, GetAssembler()); 821b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen} 822b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 823b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsenstatic void GenMinMaxFP(LocationSummary* locations, 824b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen bool is_min, 825b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen Primitive::Type type, 826b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen bool is_R6, 827b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen MipsAssembler* assembler) { 828b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen FRegister out = locations->Out().AsFpuRegister<FRegister>(); 829b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen FRegister a = locations->InAt(0).AsFpuRegister<FRegister>(); 830b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen FRegister b = locations->InAt(1).AsFpuRegister<FRegister>(); 831b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 832b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen if (is_R6) { 833b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen MipsLabel noNaNs; 834b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen MipsLabel done; 835b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen FRegister ftmp = ((out != a) && (out != b)) ? out : FTMP; 836b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 837b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen // When Java computes min/max it prefers a NaN to a number; the 838b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen // behavior of MIPSR6 is to prefer numbers to NaNs, i.e., if one of 839b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen // the inputs is a NaN and the other is a valid number, the MIPS 840b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen // instruction will return the number; Java wants the NaN value 841b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen // returned. This is why there is extra logic preceding the use of 842b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen // the MIPS min.fmt/max.fmt instructions. If either a, or b holds a 843b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen // NaN, return the NaN, otherwise return the min/max. 844b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen if (type == Primitive::kPrimDouble) { 845b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ CmpUnD(FTMP, a, b); 846b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Bc1eqz(FTMP, &noNaNs); 847b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 848b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen // One of the inputs is a NaN 849b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ CmpEqD(ftmp, a, a); 850b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen // If a == a then b is the NaN, otherwise a is the NaN. 851b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ SelD(ftmp, a, b); 852b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 853b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen if (ftmp != out) { 854b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ MovD(out, ftmp); 855b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } 856b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 857b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ B(&done); 858b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 859b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Bind(&noNaNs); 860b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 861b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen if (is_min) { 862b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ MinD(out, a, b); 863b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } else { 864b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ MaxD(out, a, b); 865b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } 866b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } else { 867b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen DCHECK_EQ(type, Primitive::kPrimFloat); 868b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ CmpUnS(FTMP, a, b); 869b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Bc1eqz(FTMP, &noNaNs); 870b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 871b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen // One of the inputs is a NaN 872b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ CmpEqS(ftmp, a, a); 873b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen // If a == a then b is the NaN, otherwise a is the NaN. 874b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ SelS(ftmp, a, b); 875b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 876b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen if (ftmp != out) { 877b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ MovS(out, ftmp); 878b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } 879b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 880b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ B(&done); 881b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 882b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Bind(&noNaNs); 883b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 884b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen if (is_min) { 885b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ MinS(out, a, b); 886b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } else { 887b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ MaxS(out, a, b); 888b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } 889b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } 890b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 891b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Bind(&done); 892b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } else { 893b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen MipsLabel ordered; 894b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen MipsLabel compare; 895b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen MipsLabel select; 896b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen MipsLabel done; 897b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 898b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen if (type == Primitive::kPrimDouble) { 899b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ CunD(a, b); 900b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } else { 901b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen DCHECK_EQ(type, Primitive::kPrimFloat); 902b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ CunS(a, b); 903b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } 904b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Bc1f(&ordered); 905b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 906b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen // a or b (or both) is a NaN. Return one, which is a NaN. 907b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen if (type == Primitive::kPrimDouble) { 908b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ CeqD(b, b); 909b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } else { 910b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ CeqS(b, b); 911b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } 912b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ B(&select); 913b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 914b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Bind(&ordered); 915b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 916b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen // Neither is a NaN. 917b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen // a == b? (-0.0 compares equal with +0.0) 918b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen // If equal, handle zeroes, else compare further. 919b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen if (type == Primitive::kPrimDouble) { 920b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ CeqD(a, b); 921b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } else { 922b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ CeqS(a, b); 923b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } 924b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Bc1f(&compare); 925b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 926b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen // a == b either bit for bit or one is -0.0 and the other is +0.0. 927b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen if (type == Primitive::kPrimDouble) { 928b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ MoveFromFpuHigh(TMP, a); 929b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ MoveFromFpuHigh(AT, b); 930b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } else { 931b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Mfc1(TMP, a); 932b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Mfc1(AT, b); 933b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } 934b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 935b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen if (is_min) { 936b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen // -0.0 prevails over +0.0. 937b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Or(TMP, TMP, AT); 938b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } else { 939b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen // +0.0 prevails over -0.0. 940b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ And(TMP, TMP, AT); 941b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } 942b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 943b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen if (type == Primitive::kPrimDouble) { 944b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Mfc1(AT, a); 945b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Mtc1(AT, out); 946b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ MoveToFpuHigh(TMP, out); 947b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } else { 948b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Mtc1(TMP, out); 949b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } 950b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ B(&done); 951b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 952b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Bind(&compare); 953b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 954b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen if (type == Primitive::kPrimDouble) { 955b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen if (is_min) { 956b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen // return (a <= b) ? a : b; 957b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ ColeD(a, b); 958b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } else { 959b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen // return (a >= b) ? a : b; 960b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ ColeD(b, a); // b <= a 961b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } 962b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } else { 963b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen if (is_min) { 964b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen // return (a <= b) ? a : b; 965b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ ColeS(a, b); 966b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } else { 967b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen // return (a >= b) ? a : b; 968b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ ColeS(b, a); // b <= a 969b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } 970b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } 971b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 972b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Bind(&select); 973b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 974b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen if (type == Primitive::kPrimDouble) { 975b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ MovtD(out, a); 976b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ MovfD(out, b); 977b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } else { 978b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ MovtS(out, a); 979b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ MovfS(out, b); 980b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } 981b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 982b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Bind(&done); 983b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } 984b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen} 985b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 986b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsenstatic void CreateFPFPToFPLocations(ArenaAllocator* arena, HInvoke* invoke) { 987b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen LocationSummary* locations = new (arena) LocationSummary(invoke, 988b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen LocationSummary::kNoCall, 989b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen kIntrinsified); 990b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen locations->SetInAt(0, Location::RequiresFpuRegister()); 991b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen locations->SetInAt(1, Location::RequiresFpuRegister()); 992b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen locations->SetOut(Location::RequiresFpuRegister(), Location::kOutputOverlap); 993b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen} 994b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 995b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen// double java.lang.Math.min(double, double) 996b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsenvoid IntrinsicLocationsBuilderMIPS::VisitMathMinDoubleDouble(HInvoke* invoke) { 997b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen CreateFPFPToFPLocations(arena_, invoke); 998b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen} 999b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 1000b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsenvoid IntrinsicCodeGeneratorMIPS::VisitMathMinDoubleDouble(HInvoke* invoke) { 1001b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen GenMinMaxFP(invoke->GetLocations(), 1002b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen /* is_min */ true, 1003b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen Primitive::kPrimDouble, 1004b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen IsR6(), 1005b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen GetAssembler()); 1006b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen} 1007b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 1008b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen// float java.lang.Math.min(float, float) 1009b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsenvoid IntrinsicLocationsBuilderMIPS::VisitMathMinFloatFloat(HInvoke* invoke) { 1010b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen CreateFPFPToFPLocations(arena_, invoke); 1011b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen} 1012b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 1013b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsenvoid IntrinsicCodeGeneratorMIPS::VisitMathMinFloatFloat(HInvoke* invoke) { 1014b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen GenMinMaxFP(invoke->GetLocations(), 1015b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen /* is_min */ true, 1016b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen Primitive::kPrimFloat, 1017b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen IsR6(), 1018b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen GetAssembler()); 1019b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen} 1020b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 1021b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen// double java.lang.Math.max(double, double) 1022b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsenvoid IntrinsicLocationsBuilderMIPS::VisitMathMaxDoubleDouble(HInvoke* invoke) { 1023b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen CreateFPFPToFPLocations(arena_, invoke); 1024b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen} 1025b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 1026b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsenvoid IntrinsicCodeGeneratorMIPS::VisitMathMaxDoubleDouble(HInvoke* invoke) { 1027b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen GenMinMaxFP(invoke->GetLocations(), 1028b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen /* is_min */ false, 1029b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen Primitive::kPrimDouble, 1030b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen IsR6(), 1031b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen GetAssembler()); 1032b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen} 1033b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 1034b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen// float java.lang.Math.max(float, float) 1035b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsenvoid IntrinsicLocationsBuilderMIPS::VisitMathMaxFloatFloat(HInvoke* invoke) { 1036b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen CreateFPFPToFPLocations(arena_, invoke); 1037b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen} 1038b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 1039b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsenvoid IntrinsicCodeGeneratorMIPS::VisitMathMaxFloatFloat(HInvoke* invoke) { 1040b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen GenMinMaxFP(invoke->GetLocations(), 1041b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen /* is_min */ false, 1042b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen Primitive::kPrimFloat, 1043b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen IsR6(), 1044b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen GetAssembler()); 1045b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen} 1046b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 1047b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsenstatic void CreateIntIntToIntLocations(ArenaAllocator* arena, HInvoke* invoke) { 1048b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen LocationSummary* locations = new (arena) LocationSummary(invoke, 1049b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen LocationSummary::kNoCall, 1050b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen kIntrinsified); 1051b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen locations->SetInAt(0, Location::RequiresRegister()); 1052b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen locations->SetInAt(1, Location::RequiresRegister()); 1053b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); 1054b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen} 1055b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 1056b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsenstatic void GenMinMax(LocationSummary* locations, 1057b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen bool is_min, 1058b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen Primitive::Type type, 1059b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen bool is_R6, 1060b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen MipsAssembler* assembler) { 1061b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen if (is_R6) { 1062b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen // Some architectures, such as ARM and MIPS (prior to r6), have a 1063b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen // conditional move instruction which only changes the target 1064b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen // (output) register if the condition is true (MIPS prior to r6 had 1065b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen // MOVF, MOVT, MOVN, and MOVZ). The SELEQZ and SELNEZ instructions 1066b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen // always change the target (output) register. If the condition is 1067b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen // true the output register gets the contents of the "rs" register; 1068b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen // otherwise, the output register is set to zero. One consequence 1069b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen // of this is that to implement something like "rd = c==0 ? rs : rt" 1070b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen // MIPS64r6 needs to use a pair of SELEQZ/SELNEZ instructions. 1071b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen // After executing this pair of instructions one of the output 1072b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen // registers from the pair will necessarily contain zero. Then the 1073b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen // code ORs the output registers from the SELEQZ/SELNEZ instructions 1074b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen // to get the final result. 1075b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen // 1076b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen // The initial test to see if the output register is same as the 1077b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen // first input register is needed to make sure that value in the 1078b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen // first input register isn't clobbered before we've finished 1079b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen // computing the output value. The logic in the corresponding else 1080b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen // clause performs the same task but makes sure the second input 1081b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen // register isn't clobbered in the event that it's the same register 1082b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen // as the output register; the else clause also handles the case 1083b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen // where the output register is distinct from both the first, and the 1084b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen // second input registers. 1085b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen if (type == Primitive::kPrimLong) { 1086b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen Register a_lo = locations->InAt(0).AsRegisterPairLow<Register>(); 1087b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen Register a_hi = locations->InAt(0).AsRegisterPairHigh<Register>(); 1088b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen Register b_lo = locations->InAt(1).AsRegisterPairLow<Register>(); 1089b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen Register b_hi = locations->InAt(1).AsRegisterPairHigh<Register>(); 1090b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen Register out_lo = locations->Out().AsRegisterPairLow<Register>(); 1091b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen Register out_hi = locations->Out().AsRegisterPairHigh<Register>(); 1092b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 1093b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen MipsLabel compare_done; 1094b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 1095b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen if (a_lo == b_lo) { 1096b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen if (out_lo != a_lo) { 1097b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Move(out_lo, a_lo); 1098b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Move(out_hi, a_hi); 1099b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } 1100b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } else { 1101b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Slt(TMP, b_hi, a_hi); 1102b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Bne(b_hi, a_hi, &compare_done); 1103b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 1104b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Sltu(TMP, b_lo, a_lo); 1105b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 1106b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Bind(&compare_done); 1107b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 1108b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen if (is_min) { 1109b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Seleqz(AT, a_lo, TMP); 1110b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Selnez(out_lo, b_lo, TMP); // Safe even if out_lo == a_lo/b_lo 1111b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen // because at this point we're 1112b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen // done using a_lo/b_lo. 1113b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } else { 1114b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Selnez(AT, a_lo, TMP); 1115b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Seleqz(out_lo, b_lo, TMP); // ditto 1116b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } 1117b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Or(out_lo, out_lo, AT); 1118b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen if (is_min) { 1119b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Seleqz(AT, a_hi, TMP); 1120b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Selnez(out_hi, b_hi, TMP); // ditto but for out_hi & a_hi/b_hi 1121b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } else { 1122b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Selnez(AT, a_hi, TMP); 1123b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Seleqz(out_hi, b_hi, TMP); // ditto but for out_hi & a_hi/b_hi 1124b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } 1125b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Or(out_hi, out_hi, AT); 1126b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } 1127b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } else { 1128b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen DCHECK_EQ(type, Primitive::kPrimInt); 1129b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen Register a = locations->InAt(0).AsRegister<Register>(); 1130b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen Register b = locations->InAt(1).AsRegister<Register>(); 1131b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen Register out = locations->Out().AsRegister<Register>(); 1132b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 1133b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen if (a == b) { 1134b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen if (out != a) { 1135b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Move(out, a); 1136b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } 1137b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } else { 1138b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Slt(AT, b, a); 1139b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen if (is_min) { 1140b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Seleqz(TMP, a, AT); 1141b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Selnez(AT, b, AT); 1142b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } else { 1143b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Selnez(TMP, a, AT); 1144b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Seleqz(AT, b, AT); 1145b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } 1146b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Or(out, TMP, AT); 1147b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } 1148b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } 1149b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } else { 1150b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen if (type == Primitive::kPrimLong) { 1151b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen Register a_lo = locations->InAt(0).AsRegisterPairLow<Register>(); 1152b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen Register a_hi = locations->InAt(0).AsRegisterPairHigh<Register>(); 1153b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen Register b_lo = locations->InAt(1).AsRegisterPairLow<Register>(); 1154b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen Register b_hi = locations->InAt(1).AsRegisterPairHigh<Register>(); 1155b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen Register out_lo = locations->Out().AsRegisterPairLow<Register>(); 1156b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen Register out_hi = locations->Out().AsRegisterPairHigh<Register>(); 1157b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 1158b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen MipsLabel compare_done; 1159b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 1160b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen if (a_lo == b_lo) { 1161b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen if (out_lo != a_lo) { 1162b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Move(out_lo, a_lo); 1163b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Move(out_hi, a_hi); 1164b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } 1165b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } else { 1166b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Slt(TMP, a_hi, b_hi); 1167b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Bne(a_hi, b_hi, &compare_done); 1168b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 1169b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Sltu(TMP, a_lo, b_lo); 1170b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 1171b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Bind(&compare_done); 1172b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 1173b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen if (is_min) { 1174b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen if (out_lo != a_lo) { 1175b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Movn(out_hi, a_hi, TMP); 1176b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Movn(out_lo, a_lo, TMP); 1177b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } 1178b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen if (out_lo != b_lo) { 1179b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Movz(out_hi, b_hi, TMP); 1180b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Movz(out_lo, b_lo, TMP); 1181b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } 1182b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } else { 1183b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen if (out_lo != a_lo) { 1184b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Movz(out_hi, a_hi, TMP); 1185b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Movz(out_lo, a_lo, TMP); 1186b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } 1187b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen if (out_lo != b_lo) { 1188b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Movn(out_hi, b_hi, TMP); 1189b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Movn(out_lo, b_lo, TMP); 1190b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } 1191b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } 1192b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } 1193b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } else { 1194b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen DCHECK_EQ(type, Primitive::kPrimInt); 1195b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen Register a = locations->InAt(0).AsRegister<Register>(); 1196b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen Register b = locations->InAt(1).AsRegister<Register>(); 1197b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen Register out = locations->Out().AsRegister<Register>(); 1198b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 1199b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen if (a == b) { 1200b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen if (out != a) { 1201b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Move(out, a); 1202b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } 1203b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } else { 1204b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Slt(AT, a, b); 1205b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen if (is_min) { 1206b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen if (out != a) { 1207b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Movn(out, a, AT); 1208b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } 1209b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen if (out != b) { 1210b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Movz(out, b, AT); 1211b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } 1212b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } else { 1213b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen if (out != a) { 1214b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Movz(out, a, AT); 1215b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } 1216b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen if (out != b) { 1217b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ Movn(out, b, AT); 1218b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } 1219b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } 1220b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } 1221b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } 1222b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen } 1223b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen} 1224b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 1225b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen// int java.lang.Math.min(int, int) 1226b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsenvoid IntrinsicLocationsBuilderMIPS::VisitMathMinIntInt(HInvoke* invoke) { 1227b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen CreateIntIntToIntLocations(arena_, invoke); 1228b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen} 1229b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 1230b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsenvoid IntrinsicCodeGeneratorMIPS::VisitMathMinIntInt(HInvoke* invoke) { 1231b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen GenMinMax(invoke->GetLocations(), 1232b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen /* is_min */ true, 1233b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen Primitive::kPrimInt, 1234b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen IsR6(), 1235b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen GetAssembler()); 1236b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen} 1237b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 1238b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen// long java.lang.Math.min(long, long) 1239b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsenvoid IntrinsicLocationsBuilderMIPS::VisitMathMinLongLong(HInvoke* invoke) { 1240b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen CreateIntIntToIntLocations(arena_, invoke); 1241b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen} 1242b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 1243b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsenvoid IntrinsicCodeGeneratorMIPS::VisitMathMinLongLong(HInvoke* invoke) { 1244b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen GenMinMax(invoke->GetLocations(), 1245b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen /* is_min */ true, 1246b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen Primitive::kPrimLong, 1247b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen IsR6(), 1248b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen GetAssembler()); 1249b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen} 1250b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 1251b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen// int java.lang.Math.max(int, int) 1252b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsenvoid IntrinsicLocationsBuilderMIPS::VisitMathMaxIntInt(HInvoke* invoke) { 1253b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen CreateIntIntToIntLocations(arena_, invoke); 1254b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen} 1255b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 1256b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsenvoid IntrinsicCodeGeneratorMIPS::VisitMathMaxIntInt(HInvoke* invoke) { 1257b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen GenMinMax(invoke->GetLocations(), 1258b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen /* is_min */ false, 1259b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen Primitive::kPrimInt, 1260b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen IsR6(), 1261b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen GetAssembler()); 1262b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen} 1263b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 1264b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen// long java.lang.Math.max(long, long) 1265b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsenvoid IntrinsicLocationsBuilderMIPS::VisitMathMaxLongLong(HInvoke* invoke) { 1266b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen CreateIntIntToIntLocations(arena_, invoke); 1267b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen} 1268b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 1269b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsenvoid IntrinsicCodeGeneratorMIPS::VisitMathMaxLongLong(HInvoke* invoke) { 1270b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen GenMinMax(invoke->GetLocations(), 1271b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen /* is_min */ false, 1272b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen Primitive::kPrimLong, 1273b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen IsR6(), 1274b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen GetAssembler()); 1275b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen} 1276b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 1277b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen// double java.lang.Math.sqrt(double) 1278b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsenvoid IntrinsicLocationsBuilderMIPS::VisitMathSqrt(HInvoke* invoke) { 1279b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen CreateFPToFPLocations(arena_, invoke); 1280b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen} 1281b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 1282b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsenvoid IntrinsicCodeGeneratorMIPS::VisitMathSqrt(HInvoke* invoke) { 1283b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen LocationSummary* locations = invoke->GetLocations(); 1284b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen MipsAssembler* assembler = GetAssembler(); 1285b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen FRegister in = locations->InAt(0).AsFpuRegister<FRegister>(); 1286b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen FRegister out = locations->Out().AsFpuRegister<FRegister>(); 1287b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 1288b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen __ SqrtD(out, in); 1289b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen} 1290b74353a6765447b1551b337fd76803eb6aa86b8bChris Larsen 12913acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen// byte libcore.io.Memory.peekByte(long address) 12923acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsenvoid IntrinsicLocationsBuilderMIPS::VisitMemoryPeekByte(HInvoke* invoke) { 12933acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen CreateIntToIntLocations(arena_, invoke); 12943acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen} 12953acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen 12963acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsenvoid IntrinsicCodeGeneratorMIPS::VisitMemoryPeekByte(HInvoke* invoke) { 12973acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen MipsAssembler* assembler = GetAssembler(); 12983acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen Register adr = invoke->GetLocations()->InAt(0).AsRegisterPairLow<Register>(); 12993acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen Register out = invoke->GetLocations()->Out().AsRegister<Register>(); 13003acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen 13013acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen __ Lb(out, adr, 0); 13023acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen} 13033acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen 13043acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen// short libcore.io.Memory.peekShort(long address) 13053acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsenvoid IntrinsicLocationsBuilderMIPS::VisitMemoryPeekShortNative(HInvoke* invoke) { 13063acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen CreateIntToIntLocations(arena_, invoke); 13073acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen} 13083acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen 13093acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsenvoid IntrinsicCodeGeneratorMIPS::VisitMemoryPeekShortNative(HInvoke* invoke) { 13103acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen MipsAssembler* assembler = GetAssembler(); 13113acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen Register adr = invoke->GetLocations()->InAt(0).AsRegisterPairLow<Register>(); 13123acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen Register out = invoke->GetLocations()->Out().AsRegister<Register>(); 13133acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen 13143acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen if (IsR6()) { 13153acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen __ Lh(out, adr, 0); 13163acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen } else if (IsR2OrNewer()) { 13173acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen // Unlike for words, there are no lhl/lhr instructions to load 13183acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen // unaligned halfwords so the code loads individual bytes, in case 13193acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen // the address isn't halfword-aligned, and assembles them into a 13203acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen // signed halfword. 13213acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen __ Lb(AT, adr, 1); // This byte must be sign-extended. 13223acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen __ Lb(out, adr, 0); // This byte can be either sign-extended, or 13233acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen // zero-extended because the following 13243acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen // instruction overwrites the sign bits. 13253acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen __ Ins(out, AT, 8, 24); 13263acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen } else { 13273acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen __ Lbu(AT, adr, 0); // This byte must be zero-extended. If it's not 13283acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen // the "or" instruction below will destroy the upper 13293acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen // 24 bits of the final result. 13303acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen __ Lb(out, adr, 1); // This byte must be sign-extended. 13313acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen __ Sll(out, out, 8); 13323acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen __ Or(out, out, AT); 13333acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen } 13343acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen} 13353acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen 13363acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen// int libcore.io.Memory.peekInt(long address) 13373acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsenvoid IntrinsicLocationsBuilderMIPS::VisitMemoryPeekIntNative(HInvoke* invoke) { 13383acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen CreateIntToIntLocations(arena_, invoke, Location::kOutputOverlap); 13393acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen} 13403acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen 13413acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsenvoid IntrinsicCodeGeneratorMIPS::VisitMemoryPeekIntNative(HInvoke* invoke) { 13423acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen MipsAssembler* assembler = GetAssembler(); 13433acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen Register adr = invoke->GetLocations()->InAt(0).AsRegisterPairLow<Register>(); 13443acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen Register out = invoke->GetLocations()->Out().AsRegister<Register>(); 13453acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen 13463acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen if (IsR6()) { 13473acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen __ Lw(out, adr, 0); 13483acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen } else { 13493acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen __ Lwr(out, adr, 0); 13503acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen __ Lwl(out, adr, 3); 13513acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen } 13523acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen} 13533acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen 13543acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen// long libcore.io.Memory.peekLong(long address) 13553acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsenvoid IntrinsicLocationsBuilderMIPS::VisitMemoryPeekLongNative(HInvoke* invoke) { 13563acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen CreateIntToIntLocations(arena_, invoke, Location::kOutputOverlap); 13573acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen} 13583acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen 13593acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsenvoid IntrinsicCodeGeneratorMIPS::VisitMemoryPeekLongNative(HInvoke* invoke) { 13603acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen MipsAssembler* assembler = GetAssembler(); 13613acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen Register adr = invoke->GetLocations()->InAt(0).AsRegisterPairLow<Register>(); 13623acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen Register out_lo = invoke->GetLocations()->Out().AsRegisterPairLow<Register>(); 13633acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen Register out_hi = invoke->GetLocations()->Out().AsRegisterPairHigh<Register>(); 13643acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen 13653acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen if (IsR6()) { 13663acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen __ Lw(out_lo, adr, 0); 13673acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen __ Lw(out_hi, adr, 4); 13683acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen } else { 13693acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen __ Lwr(out_lo, adr, 0); 13703acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen __ Lwl(out_lo, adr, 3); 13713acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen __ Lwr(out_hi, adr, 4); 13723acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen __ Lwl(out_hi, adr, 7); 13733acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen } 13743acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen} 13753acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen 13763acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsenstatic void CreateIntIntToVoidLocations(ArenaAllocator* arena, HInvoke* invoke) { 13773acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen LocationSummary* locations = new (arena) LocationSummary(invoke, 13783acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen LocationSummary::kNoCall, 13793acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen kIntrinsified); 13803acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen locations->SetInAt(0, Location::RequiresRegister()); 13813acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen locations->SetInAt(1, Location::RequiresRegister()); 13823acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen} 13833acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen 13843acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen// void libcore.io.Memory.pokeByte(long address, byte value) 13853acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsenvoid IntrinsicLocationsBuilderMIPS::VisitMemoryPokeByte(HInvoke* invoke) { 13863acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen CreateIntIntToVoidLocations(arena_, invoke); 13873acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen} 13883acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen 13893acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsenvoid IntrinsicCodeGeneratorMIPS::VisitMemoryPokeByte(HInvoke* invoke) { 13903acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen MipsAssembler* assembler = GetAssembler(); 13913acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen Register adr = invoke->GetLocations()->InAt(0).AsRegisterPairLow<Register>(); 13923acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen Register val = invoke->GetLocations()->InAt(1).AsRegister<Register>(); 13933acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen 13943acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen __ Sb(val, adr, 0); 13953acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen} 13963acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen 13973acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen// void libcore.io.Memory.pokeShort(long address, short value) 13983acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsenvoid IntrinsicLocationsBuilderMIPS::VisitMemoryPokeShortNative(HInvoke* invoke) { 13993acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen CreateIntIntToVoidLocations(arena_, invoke); 14003acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen} 14013acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen 14023acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsenvoid IntrinsicCodeGeneratorMIPS::VisitMemoryPokeShortNative(HInvoke* invoke) { 14033acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen MipsAssembler* assembler = GetAssembler(); 14043acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen Register adr = invoke->GetLocations()->InAt(0).AsRegisterPairLow<Register>(); 14053acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen Register val = invoke->GetLocations()->InAt(1).AsRegister<Register>(); 14063acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen 14073acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen if (IsR6()) { 14083acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen __ Sh(val, adr, 0); 14093acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen } else { 14103acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen // Unlike for words, there are no shl/shr instructions to store 14113acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen // unaligned halfwords so the code stores individual bytes, in case 14123acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen // the address isn't halfword-aligned. 14133acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen __ Sb(val, adr, 0); 14143acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen __ Srl(AT, val, 8); 14153acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen __ Sb(AT, adr, 1); 14163acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen } 14173acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen} 14183acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen 14193acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen// void libcore.io.Memory.pokeInt(long address, int value) 14203acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsenvoid IntrinsicLocationsBuilderMIPS::VisitMemoryPokeIntNative(HInvoke* invoke) { 14213acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen CreateIntIntToVoidLocations(arena_, invoke); 14223acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen} 14233acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen 14243acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsenvoid IntrinsicCodeGeneratorMIPS::VisitMemoryPokeIntNative(HInvoke* invoke) { 14253acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen MipsAssembler* assembler = GetAssembler(); 14263acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen Register adr = invoke->GetLocations()->InAt(0).AsRegisterPairLow<Register>(); 14273acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen Register val = invoke->GetLocations()->InAt(1).AsRegister<Register>(); 14283acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen 14293acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen if (IsR6()) { 14303acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen __ Sw(val, adr, 0); 14313acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen } else { 14323acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen __ Swr(val, adr, 0); 14333acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen __ Swl(val, adr, 3); 14343acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen } 14353acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen} 14363acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen 14373acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen// void libcore.io.Memory.pokeLong(long address, long value) 14383acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsenvoid IntrinsicLocationsBuilderMIPS::VisitMemoryPokeLongNative(HInvoke* invoke) { 14393acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen CreateIntIntToVoidLocations(arena_, invoke); 14403acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen} 14413acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen 14423acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsenvoid IntrinsicCodeGeneratorMIPS::VisitMemoryPokeLongNative(HInvoke* invoke) { 14433acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen MipsAssembler* assembler = GetAssembler(); 14443acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen Register adr = invoke->GetLocations()->InAt(0).AsRegisterPairLow<Register>(); 14453acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen Register val_lo = invoke->GetLocations()->InAt(1).AsRegisterPairLow<Register>(); 14463acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen Register val_hi = invoke->GetLocations()->InAt(1).AsRegisterPairHigh<Register>(); 14473acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen 14483acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen if (IsR6()) { 14493acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen __ Sw(val_lo, adr, 0); 14503acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen __ Sw(val_hi, adr, 4); 14513acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen } else { 14523acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen __ Swr(val_lo, adr, 0); 14533acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen __ Swl(val_lo, adr, 3); 14543acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen __ Swr(val_hi, adr, 4); 14553acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen __ Swl(val_hi, adr, 7); 14563acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen } 14573acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen} 14583acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen 1459cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen// Thread java.lang.Thread.currentThread() 1460cf283daf579e9eda586f312c3fc89444601e2525Chris Larsenvoid IntrinsicLocationsBuilderMIPS::VisitThreadCurrentThread(HInvoke* invoke) { 1461cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen LocationSummary* locations = new (arena_) LocationSummary(invoke, 1462cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen LocationSummary::kNoCall, 1463cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen kIntrinsified); 1464cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen locations->SetOut(Location::RequiresRegister()); 1465cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen} 1466cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen 1467cf283daf579e9eda586f312c3fc89444601e2525Chris Larsenvoid IntrinsicCodeGeneratorMIPS::VisitThreadCurrentThread(HInvoke* invoke) { 1468cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen MipsAssembler* assembler = GetAssembler(); 1469cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen Register out = invoke->GetLocations()->Out().AsRegister<Register>(); 1470cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen 1471cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen __ LoadFromOffset(kLoadWord, 1472cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen out, 1473cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen TR, 1474cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen Thread::PeerOffset<kMipsPointerSize>().Int32Value()); 1475cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen} 1476cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen 14774fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsenstatic void CreateIntIntIntToIntLocations(ArenaAllocator* arena, HInvoke* invoke) { 14784fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen bool can_call = 14794fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen invoke->GetIntrinsic() == Intrinsics::kUnsafeGetObject || 14804fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen invoke->GetIntrinsic() == Intrinsics::kUnsafeGetObjectVolatile; 14814fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen LocationSummary* locations = new (arena) LocationSummary(invoke, 14824fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen can_call ? 14834fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen LocationSummary::kCallOnSlowPath : 14844fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen LocationSummary::kNoCall, 14854fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen kIntrinsified); 14864fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen locations->SetInAt(0, Location::NoLocation()); // Unused receiver. 14874fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen locations->SetInAt(1, Location::RequiresRegister()); 14884fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen locations->SetInAt(2, Location::RequiresRegister()); 14894fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); 14904fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen} 14914fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen 14924fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsenstatic void GenUnsafeGet(HInvoke* invoke, 14934fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen Primitive::Type type, 14944fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen bool is_volatile, 14954fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen bool is_R6, 14964fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen CodeGeneratorMIPS* codegen) { 14974fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen LocationSummary* locations = invoke->GetLocations(); 14984fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen DCHECK((type == Primitive::kPrimInt) || 14994fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen (type == Primitive::kPrimLong) || 15004fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen (type == Primitive::kPrimNot)) << type; 15014fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen MipsAssembler* assembler = codegen->GetAssembler(); 15024fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen // Object pointer. 15034fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen Register base = locations->InAt(1).AsRegister<Register>(); 15044fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen // The "offset" argument is passed as a "long". Since this code is for 15054fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen // a 32-bit processor, we can only use 32-bit addresses, so we only 15064fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen // need the low 32-bits of offset. 15074fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen Register offset_lo = invoke->GetLocations()->InAt(2).AsRegisterPairLow<Register>(); 15084fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen 15094fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen __ Addu(TMP, base, offset_lo); 15104fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen if (is_volatile) { 15114fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen __ Sync(0); 15124fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen } 15134fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen if (type == Primitive::kPrimLong) { 15144fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen Register trg_lo = locations->Out().AsRegisterPairLow<Register>(); 15154fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen Register trg_hi = locations->Out().AsRegisterPairHigh<Register>(); 15164fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen 15174fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen if (is_R6) { 15184fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen __ Lw(trg_lo, TMP, 0); 15194fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen __ Lw(trg_hi, TMP, 4); 15204fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen } else { 15214fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen __ Lwr(trg_lo, TMP, 0); 15224fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen __ Lwl(trg_lo, TMP, 3); 15234fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen __ Lwr(trg_hi, TMP, 4); 15244fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen __ Lwl(trg_hi, TMP, 7); 15254fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen } 15264fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen } else { 15274fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen Register trg = locations->Out().AsRegister<Register>(); 15284fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen 15294fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen if (is_R6) { 15304fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen __ Lw(trg, TMP, 0); 15314fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen } else { 15324fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen __ Lwr(trg, TMP, 0); 15334fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen __ Lwl(trg, TMP, 3); 15344fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen } 15354fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen } 15364fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen} 15374fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen 15384fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen// int sun.misc.Unsafe.getInt(Object o, long offset) 15394fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsenvoid IntrinsicLocationsBuilderMIPS::VisitUnsafeGet(HInvoke* invoke) { 15404fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen CreateIntIntIntToIntLocations(arena_, invoke); 15414fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen} 15424fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen 15434fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsenvoid IntrinsicCodeGeneratorMIPS::VisitUnsafeGet(HInvoke* invoke) { 15444fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen GenUnsafeGet(invoke, Primitive::kPrimInt, /* is_volatile */ false, IsR6(), codegen_); 15454fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen} 15464fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen 15474fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen// int sun.misc.Unsafe.getIntVolatile(Object o, long offset) 15484fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsenvoid IntrinsicLocationsBuilderMIPS::VisitUnsafeGetVolatile(HInvoke* invoke) { 15494fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen CreateIntIntIntToIntLocations(arena_, invoke); 15504fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen} 15514fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen 15524fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsenvoid IntrinsicCodeGeneratorMIPS::VisitUnsafeGetVolatile(HInvoke* invoke) { 15534fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen GenUnsafeGet(invoke, Primitive::kPrimInt, /* is_volatile */ true, IsR6(), codegen_); 15544fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen} 15554fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen 15564fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen// long sun.misc.Unsafe.getLong(Object o, long offset) 15574fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsenvoid IntrinsicLocationsBuilderMIPS::VisitUnsafeGetLong(HInvoke* invoke) { 15584fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen CreateIntIntIntToIntLocations(arena_, invoke); 15594fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen} 15604fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen 15614fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsenvoid IntrinsicCodeGeneratorMIPS::VisitUnsafeGetLong(HInvoke* invoke) { 15624fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen GenUnsafeGet(invoke, Primitive::kPrimLong, /* is_volatile */ false, IsR6(), codegen_); 15634fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen} 15644fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen 15654fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen// long sun.misc.Unsafe.getLongVolatile(Object o, long offset) 15664fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsenvoid IntrinsicLocationsBuilderMIPS::VisitUnsafeGetLongVolatile(HInvoke* invoke) { 15674fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen CreateIntIntIntToIntLocations(arena_, invoke); 15684fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen} 15694fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen 15704fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsenvoid IntrinsicCodeGeneratorMIPS::VisitUnsafeGetLongVolatile(HInvoke* invoke) { 15714fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen GenUnsafeGet(invoke, Primitive::kPrimLong, /* is_volatile */ true, IsR6(), codegen_); 15724fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen} 15734fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen 15744fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen// Object sun.misc.Unsafe.getObject(Object o, long offset) 15754fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsenvoid IntrinsicLocationsBuilderMIPS::VisitUnsafeGetObject(HInvoke* invoke) { 15764fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen CreateIntIntIntToIntLocations(arena_, invoke); 15774fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen} 15784fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen 15794fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsenvoid IntrinsicCodeGeneratorMIPS::VisitUnsafeGetObject(HInvoke* invoke) { 15804fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen GenUnsafeGet(invoke, Primitive::kPrimNot, /* is_volatile */ false, IsR6(), codegen_); 15814fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen} 15824fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen 15834fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen// Object sun.misc.Unsafe.getObjectVolatile(Object o, long offset) 15844fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsenvoid IntrinsicLocationsBuilderMIPS::VisitUnsafeGetObjectVolatile(HInvoke* invoke) { 15854fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen CreateIntIntIntToIntLocations(arena_, invoke); 15864fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen} 15874fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen 15884fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsenvoid IntrinsicCodeGeneratorMIPS::VisitUnsafeGetObjectVolatile(HInvoke* invoke) { 15894fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen GenUnsafeGet(invoke, Primitive::kPrimNot, /* is_volatile */ true, IsR6(), codegen_); 15904fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen} 15914fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen 15924fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsenstatic void CreateIntIntIntIntToVoidLocations(ArenaAllocator* arena, HInvoke* invoke) { 15934fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen LocationSummary* locations = new (arena) LocationSummary(invoke, 15944fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen LocationSummary::kNoCall, 15954fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen kIntrinsified); 15964fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen locations->SetInAt(0, Location::NoLocation()); // Unused receiver. 15974fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen locations->SetInAt(1, Location::RequiresRegister()); 15984fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen locations->SetInAt(2, Location::RequiresRegister()); 15994fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen locations->SetInAt(3, Location::RequiresRegister()); 16004fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen} 16014fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen 16024fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsenstatic void GenUnsafePut(LocationSummary* locations, 16034fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen Primitive::Type type, 16044fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen bool is_volatile, 16054fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen bool is_ordered, 16064fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen bool is_R6, 16074fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen CodeGeneratorMIPS* codegen) { 16084fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen DCHECK((type == Primitive::kPrimInt) || 16094fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen (type == Primitive::kPrimLong) || 16104fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen (type == Primitive::kPrimNot)) << type; 16114fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen MipsAssembler* assembler = codegen->GetAssembler(); 16124fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen // Object pointer. 16134fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen Register base = locations->InAt(1).AsRegister<Register>(); 16144fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen // The "offset" argument is passed as a "long", i.e., it's 64-bits in 16154fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen // size. Since this code is for a 32-bit processor, we can only use 16164fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen // 32-bit addresses, so we only need the low 32-bits of offset. 16174fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen Register offset_lo = locations->InAt(2).AsRegisterPairLow<Register>(); 16184fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen 16194fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen __ Addu(TMP, base, offset_lo); 16204fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen if (is_volatile || is_ordered) { 16214fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen __ Sync(0); 16224fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen } 16234fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen if ((type == Primitive::kPrimInt) || (type == Primitive::kPrimNot)) { 16244fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen Register value = locations->InAt(3).AsRegister<Register>(); 16254fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen 16264fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen if (is_R6) { 16274fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen __ Sw(value, TMP, 0); 16284fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen } else { 16294fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen __ Swr(value, TMP, 0); 16304fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen __ Swl(value, TMP, 3); 16314fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen } 16324fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen } else { 16334fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen Register value_lo = locations->InAt(3).AsRegisterPairLow<Register>(); 16344fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen Register value_hi = locations->InAt(3).AsRegisterPairHigh<Register>(); 16354fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen 16364fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen if (is_R6) { 16374fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen __ Sw(value_lo, TMP, 0); 16384fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen __ Sw(value_hi, TMP, 4); 16394fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen } else { 16404fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen __ Swr(value_lo, TMP, 0); 16414fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen __ Swl(value_lo, TMP, 3); 16424fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen __ Swr(value_hi, TMP, 4); 16434fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen __ Swl(value_hi, TMP, 7); 16444fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen } 16454fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen } 16464fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen 16474fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen if (is_volatile) { 16484fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen __ Sync(0); 16494fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen } 16504fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen 16514fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen if (type == Primitive::kPrimNot) { 16524fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen codegen->MarkGCCard(base, locations->InAt(3).AsRegister<Register>()); 16534fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen } 16544fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen} 16554fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen 16564fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen// void sun.misc.Unsafe.putInt(Object o, long offset, int x) 16574fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsenvoid IntrinsicLocationsBuilderMIPS::VisitUnsafePut(HInvoke* invoke) { 16584fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen CreateIntIntIntIntToVoidLocations(arena_, invoke); 16594fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen} 16604fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen 16614fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsenvoid IntrinsicCodeGeneratorMIPS::VisitUnsafePut(HInvoke* invoke) { 16624fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen GenUnsafePut(invoke->GetLocations(), 16634fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen Primitive::kPrimInt, 16644fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen /* is_volatile */ false, 16654fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen /* is_ordered */ false, 16664fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen IsR6(), 16674fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen codegen_); 16684fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen} 16694fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen 16704fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen// void sun.misc.Unsafe.putOrderedInt(Object o, long offset, int x) 16714fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsenvoid IntrinsicLocationsBuilderMIPS::VisitUnsafePutOrdered(HInvoke* invoke) { 16724fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen CreateIntIntIntIntToVoidLocations(arena_, invoke); 16734fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen} 16744fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen 16754fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsenvoid IntrinsicCodeGeneratorMIPS::VisitUnsafePutOrdered(HInvoke* invoke) { 16764fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen GenUnsafePut(invoke->GetLocations(), 16774fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen Primitive::kPrimInt, 16784fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen /* is_volatile */ false, 16794fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen /* is_ordered */ true, 16804fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen IsR6(), 16814fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen codegen_); 16824fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen} 16834fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen 16844fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen// void sun.misc.Unsafe.putIntVolatile(Object o, long offset, int x) 16854fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsenvoid IntrinsicLocationsBuilderMIPS::VisitUnsafePutVolatile(HInvoke* invoke) { 16864fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen CreateIntIntIntIntToVoidLocations(arena_, invoke); 16874fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen} 16884fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen 16894fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsenvoid IntrinsicCodeGeneratorMIPS::VisitUnsafePutVolatile(HInvoke* invoke) { 16904fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen GenUnsafePut(invoke->GetLocations(), 16914fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen Primitive::kPrimInt, 16924fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen /* is_volatile */ true, 16934fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen /* is_ordered */ false, 16944fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen IsR6(), 16954fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen codegen_); 16964fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen} 16974fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen 16984fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen// void sun.misc.Unsafe.putObject(Object o, long offset, Object x) 16994fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsenvoid IntrinsicLocationsBuilderMIPS::VisitUnsafePutObject(HInvoke* invoke) { 17004fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen CreateIntIntIntIntToVoidLocations(arena_, invoke); 17014fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen} 17024fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen 17034fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsenvoid IntrinsicCodeGeneratorMIPS::VisitUnsafePutObject(HInvoke* invoke) { 17044fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen GenUnsafePut(invoke->GetLocations(), 17054fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen Primitive::kPrimNot, 17064fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen /* is_volatile */ false, 17074fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen /* is_ordered */ false, 17084fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen IsR6(), 17094fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen codegen_); 17104fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen} 17114fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen 17124fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen// void sun.misc.Unsafe.putOrderedObject(Object o, long offset, Object x) 17134fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsenvoid IntrinsicLocationsBuilderMIPS::VisitUnsafePutObjectOrdered(HInvoke* invoke) { 17144fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen CreateIntIntIntIntToVoidLocations(arena_, invoke); 17154fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen} 17164fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen 17174fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsenvoid IntrinsicCodeGeneratorMIPS::VisitUnsafePutObjectOrdered(HInvoke* invoke) { 17184fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen GenUnsafePut(invoke->GetLocations(), 17194fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen Primitive::kPrimNot, 17204fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen /* is_volatile */ false, 17214fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen /* is_ordered */ true, 17224fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen IsR6(), 17234fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen codegen_); 17244fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen} 17254fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen 17264fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen// void sun.misc.Unsafe.putObjectVolatile(Object o, long offset, Object x) 17274fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsenvoid IntrinsicLocationsBuilderMIPS::VisitUnsafePutObjectVolatile(HInvoke* invoke) { 17284fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen CreateIntIntIntIntToVoidLocations(arena_, invoke); 17294fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen} 17304fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen 17314fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsenvoid IntrinsicCodeGeneratorMIPS::VisitUnsafePutObjectVolatile(HInvoke* invoke) { 17324fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen GenUnsafePut(invoke->GetLocations(), 17334fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen Primitive::kPrimNot, 17344fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen /* is_volatile */ true, 17354fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen /* is_ordered */ false, 17364fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen IsR6(), 17374fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen codegen_); 17384fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen} 17394fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen 17404fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen// void sun.misc.Unsafe.putLong(Object o, long offset, long x) 17414fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsenvoid IntrinsicLocationsBuilderMIPS::VisitUnsafePutLong(HInvoke* invoke) { 17424fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen CreateIntIntIntIntToVoidLocations(arena_, invoke); 17434fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen} 17444fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen 17454fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsenvoid IntrinsicCodeGeneratorMIPS::VisitUnsafePutLong(HInvoke* invoke) { 17464fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen GenUnsafePut(invoke->GetLocations(), 17474fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen Primitive::kPrimLong, 17484fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen /* is_volatile */ false, 17494fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen /* is_ordered */ false, 17504fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen IsR6(), 17514fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen codegen_); 17524fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen} 17534fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen 17544fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen// void sun.misc.Unsafe.putOrderedLong(Object o, long offset, long x) 17554fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsenvoid IntrinsicLocationsBuilderMIPS::VisitUnsafePutLongOrdered(HInvoke* invoke) { 17564fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen CreateIntIntIntIntToVoidLocations(arena_, invoke); 17574fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen} 17584fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen 17594fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsenvoid IntrinsicCodeGeneratorMIPS::VisitUnsafePutLongOrdered(HInvoke* invoke) { 17604fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen GenUnsafePut(invoke->GetLocations(), 17614fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen Primitive::kPrimLong, 17624fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen /* is_volatile */ false, 17634fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen /* is_ordered */ true, 17644fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen IsR6(), 17654fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen codegen_); 17664fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen} 17674fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen 17684fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen// void sun.misc.Unsafe.putLongVolatile(Object o, long offset, long x) 17694fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsenvoid IntrinsicLocationsBuilderMIPS::VisitUnsafePutLongVolatile(HInvoke* invoke) { 17704fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen CreateIntIntIntIntToVoidLocations(arena_, invoke); 17714fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen} 17724fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen 17734fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsenvoid IntrinsicCodeGeneratorMIPS::VisitUnsafePutLongVolatile(HInvoke* invoke) { 17744fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen GenUnsafePut(invoke->GetLocations(), 17754fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen Primitive::kPrimLong, 17764fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen /* is_volatile */ true, 17774fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen /* is_ordered */ false, 17784fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen IsR6(), 17794fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen codegen_); 17804fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen} 17814fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen 178251aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunzestatic void CreateIntIntIntIntIntToIntLocations(ArenaAllocator* arena, HInvoke* invoke) { 178351aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze LocationSummary* locations = new (arena) LocationSummary(invoke, 178451aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze LocationSummary::kNoCall, 178551aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze kIntrinsified); 178651aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze locations->SetInAt(0, Location::NoLocation()); // Unused receiver. 178751aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze locations->SetInAt(1, Location::RequiresRegister()); 178851aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze locations->SetInAt(2, Location::RequiresRegister()); 178951aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze locations->SetInAt(3, Location::RequiresRegister()); 179051aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze locations->SetInAt(4, Location::RequiresRegister()); 179151aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze 179251aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze locations->SetOut(Location::RequiresRegister()); 179351aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze} 179451aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze 179551aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunzestatic void GenCas(LocationSummary* locations, Primitive::Type type, CodeGeneratorMIPS* codegen) { 179651aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze MipsAssembler* assembler = codegen->GetAssembler(); 179751aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze bool isR6 = codegen->GetInstructionSetFeatures().IsR6(); 179851aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze Register base = locations->InAt(1).AsRegister<Register>(); 179951aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze Register offset_lo = locations->InAt(2).AsRegisterPairLow<Register>(); 180051aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze Register expected = locations->InAt(3).AsRegister<Register>(); 180151aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze Register value = locations->InAt(4).AsRegister<Register>(); 180251aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze Register out = locations->Out().AsRegister<Register>(); 180351aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze 180451aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze DCHECK_NE(base, out); 180551aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze DCHECK_NE(offset_lo, out); 180651aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze DCHECK_NE(expected, out); 180751aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze 180851aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze if (type == Primitive::kPrimNot) { 180951aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze // Mark card for object assuming new value is stored. 181051aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze codegen->MarkGCCard(base, value); 181151aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze } 181251aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze 181351aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze // do { 181451aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze // tmp_value = [tmp_ptr] - expected; 181551aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze // } while (tmp_value == 0 && failure([tmp_ptr] <- r_new_value)); 181651aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze // result = tmp_value != 0; 181751aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze 181851aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze MipsLabel loop_head, exit_loop; 181951aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze __ Addu(TMP, base, offset_lo); 182051aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze __ Sync(0); 182151aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze __ Bind(&loop_head); 182251aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze if ((type == Primitive::kPrimInt) || (type == Primitive::kPrimNot)) { 182351aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze if (isR6) { 182451aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze __ LlR6(out, TMP); 182551aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze } else { 182651aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze __ LlR2(out, TMP); 182751aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze } 182851aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze } else { 182951aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze LOG(FATAL) << "Unsupported op size " << type; 183051aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze UNREACHABLE(); 183151aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze } 183251aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze __ Subu(out, out, expected); // If we didn't get the 'expected' 183351aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze __ Sltiu(out, out, 1); // value, set 'out' to false, and 183451aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze __ Beqz(out, &exit_loop); // return. 183551aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze __ Move(out, value); // Use 'out' for the 'store conditional' instruction. 183651aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze // If we use 'value' directly, we would lose 'value' 183751aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze // in the case that the store fails. Whether the 183851aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze // store succeeds, or fails, it will load the 183951aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze // correct boolean value into the 'out' register. 184051aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze // This test isn't really necessary. We only support Primitive::kPrimInt, 184151aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze // Primitive::kPrimNot, and we already verified that we're working on one 184251aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze // of those two types. It's left here in case the code needs to support 184351aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze // other types in the future. 184451aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze if ((type == Primitive::kPrimInt) || (type == Primitive::kPrimNot)) { 184551aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze if (isR6) { 184651aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze __ ScR6(out, TMP); 184751aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze } else { 184851aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze __ ScR2(out, TMP); 184951aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze } 185051aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze } 185151aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze __ Beqz(out, &loop_head); // If we couldn't do the read-modify-write 185251aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze // cycle atomically then retry. 185351aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze __ Bind(&exit_loop); 185451aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze __ Sync(0); 185551aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze} 185651aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze 185751aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze// boolean sun.misc.Unsafe.compareAndSwapInt(Object o, long offset, int expected, int x) 185851aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunzevoid IntrinsicLocationsBuilderMIPS::VisitUnsafeCASInt(HInvoke* invoke) { 185951aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze CreateIntIntIntIntIntToIntLocations(arena_, invoke); 186051aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze} 186151aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze 186251aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunzevoid IntrinsicCodeGeneratorMIPS::VisitUnsafeCASInt(HInvoke* invoke) { 186351aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze GenCas(invoke->GetLocations(), Primitive::kPrimInt, codegen_); 186451aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze} 186551aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze 186651aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze// boolean sun.misc.Unsafe.compareAndSwapObject(Object o, long offset, Object expected, Object x) 186751aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunzevoid IntrinsicLocationsBuilderMIPS::VisitUnsafeCASObject(HInvoke* invoke) { 186851aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze CreateIntIntIntIntIntToIntLocations(arena_, invoke); 186951aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze} 187051aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze 187151aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunzevoid IntrinsicCodeGeneratorMIPS::VisitUnsafeCASObject(HInvoke* invoke) { 187251aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze GenCas(invoke->GetLocations(), Primitive::kPrimNot, codegen_); 187351aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze} 187451aff3a6564303cab0b7ac82495b4e2e349c6ff3Alexey Frunze 18753acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen// char java.lang.String.charAt(int index) 18763acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsenvoid IntrinsicLocationsBuilderMIPS::VisitStringCharAt(HInvoke* invoke) { 18773acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen LocationSummary* locations = new (arena_) LocationSummary(invoke, 18783acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen LocationSummary::kCallOnSlowPath, 18793acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen kIntrinsified); 18803acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen locations->SetInAt(0, Location::RequiresRegister()); 18813acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen locations->SetInAt(1, Location::RequiresRegister()); 18824fdc6d9eff2d4654d13cb24e43f341d393aba1c5Chris Larsen // The inputs will be considered live at the last instruction and restored. This would overwrite 188331f477eb7f28c9e4647df3c18f7e4271436640beGoran Jakovljevic // the output with kNoOutputOverlap. 188431f477eb7f28c9e4647df3c18f7e4271436640beGoran Jakovljevic locations->SetOut(Location::RequiresRegister(), Location::kOutputOverlap); 18853acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen} 18863acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen 18873acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsenvoid IntrinsicCodeGeneratorMIPS::VisitStringCharAt(HInvoke* invoke) { 18883acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen LocationSummary* locations = invoke->GetLocations(); 18893acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen MipsAssembler* assembler = GetAssembler(); 18903acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen 18913acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen // Location of reference to data array 18923acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen const int32_t value_offset = mirror::String::ValueOffset().Int32Value(); 18933acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen // Location of count 18943acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen const int32_t count_offset = mirror::String::CountOffset().Int32Value(); 18953acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen 18963acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen Register obj = locations->InAt(0).AsRegister<Register>(); 18973acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen Register idx = locations->InAt(1).AsRegister<Register>(); 18983acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen Register out = locations->Out().AsRegister<Register>(); 18993acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen 19003acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen // TODO: Maybe we can support range check elimination. Overall, 19013acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen // though, I think it's not worth the cost. 19023acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen // TODO: For simplicity, the index parameter is requested in a 19033acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen // register, so different from Quick we will not optimize the 19043acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen // code for constants (which would save a register). 19053acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen 19063acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen SlowPathCodeMIPS* slow_path = new (GetAllocator()) IntrinsicSlowPathMIPS(invoke); 19073acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen codegen_->AddSlowPath(slow_path); 19083acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen 19093acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen // Load the string size 19103acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen __ Lw(TMP, obj, count_offset); 19113acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen codegen_->MaybeRecordImplicitNullCheck(invoke); 19123acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen // Revert to slow path if idx is too large, or negative 19133acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen __ Bgeu(idx, TMP, slow_path->GetEntryLabel()); 19143acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen 19153acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen // out = obj[2*idx]. 19163acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen __ Sll(TMP, idx, 1); // idx * 2 19173acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen __ Addu(TMP, TMP, obj); // Address of char at location idx 19183acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen __ Lhu(out, TMP, value_offset); // Load char at location idx 19193acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen 19203acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen __ Bind(slow_path->GetExitLabel()); 19213acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen} 19223acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen 1923cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen// int java.lang.String.compareTo(String anotherString) 1924cf283daf579e9eda586f312c3fc89444601e2525Chris Larsenvoid IntrinsicLocationsBuilderMIPS::VisitStringCompareTo(HInvoke* invoke) { 1925cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen LocationSummary* locations = new (arena_) LocationSummary(invoke, 1926cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen LocationSummary::kCall, 1927cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen kIntrinsified); 1928cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen InvokeRuntimeCallingConvention calling_convention; 1929cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0))); 1930cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen locations->SetInAt(1, Location::RegisterLocation(calling_convention.GetRegisterAt(1))); 1931cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen Location outLocation = calling_convention.GetReturnLocation(Primitive::kPrimInt); 1932cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen locations->SetOut(Location::RegisterLocation(outLocation.AsRegister<Register>())); 1933cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen} 1934cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen 1935cf283daf579e9eda586f312c3fc89444601e2525Chris Larsenvoid IntrinsicCodeGeneratorMIPS::VisitStringCompareTo(HInvoke* invoke) { 1936cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen MipsAssembler* assembler = GetAssembler(); 1937cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen LocationSummary* locations = invoke->GetLocations(); 1938cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen 1939cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen // Note that the null check must have been done earlier. 1940cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen DCHECK(!invoke->CanDoImplicitNullCheckOn(invoke->InputAt(0))); 1941cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen 1942cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen Register argument = locations->InAt(1).AsRegister<Register>(); 1943cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen SlowPathCodeMIPS* slow_path = new (GetAllocator()) IntrinsicSlowPathMIPS(invoke); 1944cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen codegen_->AddSlowPath(slow_path); 1945cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen __ Beqz(argument, slow_path->GetEntryLabel()); 1946cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen 1947cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen __ LoadFromOffset(kLoadWord, 1948ddc4055abab40740e689d91e9a4fe20a7b8e5d28Goran Jakovljevic T9, 1949cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen TR, 1950cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen QUICK_ENTRYPOINT_OFFSET(kMipsWordSize, 1951cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen pStringCompareTo).Int32Value()); 1952ddc4055abab40740e689d91e9a4fe20a7b8e5d28Goran Jakovljevic __ Jalr(T9); 1953cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen __ Nop(); 1954cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen __ Bind(slow_path->GetExitLabel()); 1955cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen} 1956cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen 195716ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen// boolean java.lang.String.equals(Object anObject) 195816ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsenvoid IntrinsicLocationsBuilderMIPS::VisitStringEquals(HInvoke* invoke) { 195916ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen LocationSummary* locations = new (arena_) LocationSummary(invoke, 196016ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen LocationSummary::kNoCall, 196116ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen kIntrinsified); 196216ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen locations->SetInAt(0, Location::RequiresRegister()); 196316ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen locations->SetInAt(1, Location::RequiresRegister()); 196416ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen locations->SetOut(Location::RequiresRegister()); 196516ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen 196616ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen // Temporary registers to store lengths of strings and for calculations. 196716ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen locations->AddTemp(Location::RequiresRegister()); 196816ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen locations->AddTemp(Location::RequiresRegister()); 196916ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen locations->AddTemp(Location::RequiresRegister()); 197016ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen} 197116ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen 197216ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsenvoid IntrinsicCodeGeneratorMIPS::VisitStringEquals(HInvoke* invoke) { 197316ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen MipsAssembler* assembler = GetAssembler(); 197416ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen LocationSummary* locations = invoke->GetLocations(); 197516ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen 197616ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen Register str = locations->InAt(0).AsRegister<Register>(); 197716ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen Register arg = locations->InAt(1).AsRegister<Register>(); 197816ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen Register out = locations->Out().AsRegister<Register>(); 197916ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen 198016ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen Register temp1 = locations->GetTemp(0).AsRegister<Register>(); 198116ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen Register temp2 = locations->GetTemp(1).AsRegister<Register>(); 198216ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen Register temp3 = locations->GetTemp(2).AsRegister<Register>(); 198316ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen 198416ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen MipsLabel loop; 198516ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen MipsLabel end; 198616ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen MipsLabel return_true; 198716ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen MipsLabel return_false; 198816ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen 198916ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen // Get offsets of count, value, and class fields within a string object. 199016ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen const uint32_t count_offset = mirror::String::CountOffset().Uint32Value(); 199116ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen const uint32_t value_offset = mirror::String::ValueOffset().Uint32Value(); 199216ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen const uint32_t class_offset = mirror::Object::ClassOffset().Uint32Value(); 199316ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen 199416ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen // Note that the null check must have been done earlier. 199516ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen DCHECK(!invoke->CanDoImplicitNullCheckOn(invoke->InputAt(0))); 199616ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen 199716ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen // If the register containing the pointer to "this", and the register 199816ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen // containing the pointer to "anObject" are the same register then 199916ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen // "this", and "anObject" are the same object and we can 200016ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen // short-circuit the logic to a true result. 200116ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen if (str == arg) { 200216ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen __ LoadConst32(out, 1); 200316ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen return; 200416ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen } 200516ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen 200616ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen // Check if input is null, return false if it is. 200716ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen __ Beqz(arg, &return_false); 200816ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen 200916ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen // Reference equality check, return true if same reference. 201016ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen __ Beq(str, arg, &return_true); 201116ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen 201216ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen // Instanceof check for the argument by comparing class fields. 201316ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen // All string objects must have the same type since String cannot be subclassed. 201416ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen // Receiver must be a string object, so its class field is equal to all strings' class fields. 201516ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen // If the argument is a string object, its class field must be equal to receiver's class field. 201616ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen __ Lw(temp1, str, class_offset); 201716ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen __ Lw(temp2, arg, class_offset); 201816ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen __ Bne(temp1, temp2, &return_false); 201916ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen 202016ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen // Load lengths of this and argument strings. 202116ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen __ Lw(temp1, str, count_offset); 202216ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen __ Lw(temp2, arg, count_offset); 202316ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen // Check if lengths are equal, return false if they're not. 202416ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen __ Bne(temp1, temp2, &return_false); 202516ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen // Return true if both strings are empty. 202616ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen __ Beqz(temp1, &return_true); 202716ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen 202816ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen // Don't overwrite input registers 202916ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen __ Move(TMP, str); 203016ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen __ Move(temp3, arg); 203116ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen 203216ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen // Assertions that must hold in order to compare strings 2 characters at a time. 203316ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen DCHECK_ALIGNED(value_offset, 4); 203416ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen static_assert(IsAligned<4>(kObjectAlignment), "String of odd length is not zero padded"); 203516ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen 203616ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen // Loop to compare strings 2 characters at a time starting at the beginning of the string. 203716ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen // Ok to do this because strings are zero-padded. 203816ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen __ Bind(&loop); 203916ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen __ Lw(out, TMP, value_offset); 204016ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen __ Lw(temp2, temp3, value_offset); 204116ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen __ Bne(out, temp2, &return_false); 204216ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen __ Addiu(TMP, TMP, 4); 204316ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen __ Addiu(temp3, temp3, 4); 204416ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen __ Addiu(temp1, temp1, -2); 204516ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen __ Bgtz(temp1, &loop); 204616ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen 204716ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen // Return true and exit the function. 204816ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen // If loop does not result in returning false, we return true. 204916ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen __ Bind(&return_true); 205016ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen __ LoadConst32(out, 1); 205116ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen __ B(&end); 205216ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen 205316ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen // Return false and exit the function. 205416ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen __ Bind(&return_false); 205516ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen __ LoadConst32(out, 0); 205616ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen __ Bind(&end); 205716ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen} 205816ba2b4726cafc2d83cae4a65132aac15f372689Chris Larsen 2059cf283daf579e9eda586f312c3fc89444601e2525Chris Larsenstatic void GenerateStringIndexOf(HInvoke* invoke, 2060cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen bool start_at_zero, 2061cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen MipsAssembler* assembler, 2062cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen CodeGeneratorMIPS* codegen, 2063cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen ArenaAllocator* allocator) { 2064cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen LocationSummary* locations = invoke->GetLocations(); 2065cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen Register tmp_reg = start_at_zero ? locations->GetTemp(0).AsRegister<Register>() : TMP; 2066cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen 2067cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen // Note that the null check must have been done earlier. 2068cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen DCHECK(!invoke->CanDoImplicitNullCheckOn(invoke->InputAt(0))); 2069cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen 2070cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen // Check for code points > 0xFFFF. Either a slow-path check when we 2071cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen // don't know statically, or directly dispatch if we have a constant. 2072cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen SlowPathCodeMIPS* slow_path = nullptr; 2073cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen if (invoke->InputAt(1)->IsIntConstant()) { 2074cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen if (!IsUint<16>(invoke->InputAt(1)->AsIntConstant()->GetValue())) { 2075cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen // Always needs the slow-path. We could directly dispatch to it, 2076cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen // but this case should be rare, so for simplicity just put the 2077cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen // full slow-path down and branch unconditionally. 2078cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen slow_path = new (allocator) IntrinsicSlowPathMIPS(invoke); 2079cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen codegen->AddSlowPath(slow_path); 2080cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen __ B(slow_path->GetEntryLabel()); 2081cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen __ Bind(slow_path->GetExitLabel()); 2082cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen return; 2083cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen } 2084cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen } else { 2085cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen Register char_reg = locations->InAt(1).AsRegister<Register>(); 2086cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen // The "bltu" conditional branch tests to see if the character value 2087cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen // fits in a valid 16-bit (MIPS halfword) value. If it doesn't then 2088cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen // the character being searched for, if it exists in the string, is 2089cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen // encoded using UTF-16 and stored in the string as two (16-bit) 2090cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen // halfwords. Currently the assembly code used to implement this 2091cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen // intrinsic doesn't support searching for a character stored as 2092cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen // two halfwords so we fallback to using the generic implementation 2093cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen // of indexOf(). 2094cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen __ LoadConst32(tmp_reg, std::numeric_limits<uint16_t>::max()); 2095cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen slow_path = new (allocator) IntrinsicSlowPathMIPS(invoke); 2096cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen codegen->AddSlowPath(slow_path); 2097cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen __ Bltu(tmp_reg, char_reg, slow_path->GetEntryLabel()); 2098cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen } 2099cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen 2100cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen if (start_at_zero) { 2101cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen DCHECK_EQ(tmp_reg, A2); 2102cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen // Start-index = 0. 2103cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen __ Clear(tmp_reg); 2104cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen } 2105cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen 2106cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen __ LoadFromOffset(kLoadWord, 2107ddc4055abab40740e689d91e9a4fe20a7b8e5d28Goran Jakovljevic T9, 2108cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen TR, 2109cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen QUICK_ENTRYPOINT_OFFSET(kMipsWordSize, pIndexOf).Int32Value()); 2110ddc4055abab40740e689d91e9a4fe20a7b8e5d28Goran Jakovljevic __ Jalr(T9); 2111cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen __ Nop(); 2112cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen 2113cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen if (slow_path != nullptr) { 2114cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen __ Bind(slow_path->GetExitLabel()); 2115cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen } 2116cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen} 2117cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen 2118cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen// int java.lang.String.indexOf(int ch) 2119cf283daf579e9eda586f312c3fc89444601e2525Chris Larsenvoid IntrinsicLocationsBuilderMIPS::VisitStringIndexOf(HInvoke* invoke) { 2120cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen LocationSummary* locations = new (arena_) LocationSummary(invoke, 2121cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen LocationSummary::kCall, 2122cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen kIntrinsified); 2123cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen // We have a hand-crafted assembly stub that follows the runtime 2124cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen // calling convention. So it's best to align the inputs accordingly. 2125cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen InvokeRuntimeCallingConvention calling_convention; 2126cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0))); 2127cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen locations->SetInAt(1, Location::RegisterLocation(calling_convention.GetRegisterAt(1))); 2128cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen Location outLocation = calling_convention.GetReturnLocation(Primitive::kPrimInt); 2129cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen locations->SetOut(Location::RegisterLocation(outLocation.AsRegister<Register>())); 2130cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen 2131cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen // Need a temp for slow-path codepoint compare, and need to send start-index=0. 2132cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen locations->AddTemp(Location::RegisterLocation(calling_convention.GetRegisterAt(2))); 2133cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen} 2134cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen 2135cf283daf579e9eda586f312c3fc89444601e2525Chris Larsenvoid IntrinsicCodeGeneratorMIPS::VisitStringIndexOf(HInvoke* invoke) { 2136cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen GenerateStringIndexOf(invoke, 2137cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen /* start_at_zero */ true, 2138cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen GetAssembler(), 2139cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen codegen_, 2140cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen GetAllocator()); 2141cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen} 2142cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen 2143cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen// int java.lang.String.indexOf(int ch, int fromIndex) 2144cf283daf579e9eda586f312c3fc89444601e2525Chris Larsenvoid IntrinsicLocationsBuilderMIPS::VisitStringIndexOfAfter(HInvoke* invoke) { 2145cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen LocationSummary* locations = new (arena_) LocationSummary(invoke, 2146cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen LocationSummary::kCall, 2147cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen kIntrinsified); 2148cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen // We have a hand-crafted assembly stub that follows the runtime 2149cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen // calling convention. So it's best to align the inputs accordingly. 2150cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen InvokeRuntimeCallingConvention calling_convention; 2151cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0))); 2152cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen locations->SetInAt(1, Location::RegisterLocation(calling_convention.GetRegisterAt(1))); 2153cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen locations->SetInAt(2, Location::RegisterLocation(calling_convention.GetRegisterAt(2))); 2154cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen Location outLocation = calling_convention.GetReturnLocation(Primitive::kPrimInt); 2155cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen locations->SetOut(Location::RegisterLocation(outLocation.AsRegister<Register>())); 2156cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen 2157cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen // Need a temp for slow-path codepoint compare. 2158cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen locations->AddTemp(Location::RequiresRegister()); 2159cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen} 2160cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen 2161cf283daf579e9eda586f312c3fc89444601e2525Chris Larsenvoid IntrinsicCodeGeneratorMIPS::VisitStringIndexOfAfter(HInvoke* invoke) { 2162cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen GenerateStringIndexOf(invoke, 2163cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen /* start_at_zero */ false, 2164cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen GetAssembler(), 2165cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen codegen_, 2166cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen GetAllocator()); 2167cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen} 2168cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen 2169cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen// java.lang.StringFactory.newStringFromBytes(byte[] data, int high, int offset, int byteCount) 2170cf283daf579e9eda586f312c3fc89444601e2525Chris Larsenvoid IntrinsicLocationsBuilderMIPS::VisitStringNewStringFromBytes(HInvoke* invoke) { 2171cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen LocationSummary* locations = new (arena_) LocationSummary(invoke, 2172cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen LocationSummary::kCall, 2173cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen kIntrinsified); 2174cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen InvokeRuntimeCallingConvention calling_convention; 2175cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0))); 2176cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen locations->SetInAt(1, Location::RegisterLocation(calling_convention.GetRegisterAt(1))); 2177cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen locations->SetInAt(2, Location::RegisterLocation(calling_convention.GetRegisterAt(2))); 2178cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen locations->SetInAt(3, Location::RegisterLocation(calling_convention.GetRegisterAt(3))); 2179cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen Location outLocation = calling_convention.GetReturnLocation(Primitive::kPrimInt); 2180cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen locations->SetOut(Location::RegisterLocation(outLocation.AsRegister<Register>())); 2181cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen} 2182cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen 2183cf283daf579e9eda586f312c3fc89444601e2525Chris Larsenvoid IntrinsicCodeGeneratorMIPS::VisitStringNewStringFromBytes(HInvoke* invoke) { 2184cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen MipsAssembler* assembler = GetAssembler(); 2185cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen LocationSummary* locations = invoke->GetLocations(); 2186cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen 2187cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen Register byte_array = locations->InAt(0).AsRegister<Register>(); 2188cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen SlowPathCodeMIPS* slow_path = new (GetAllocator()) IntrinsicSlowPathMIPS(invoke); 2189cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen codegen_->AddSlowPath(slow_path); 2190cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen __ Beqz(byte_array, slow_path->GetEntryLabel()); 2191cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen 2192cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen __ LoadFromOffset(kLoadWord, 2193ddc4055abab40740e689d91e9a4fe20a7b8e5d28Goran Jakovljevic T9, 2194cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen TR, 2195cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen QUICK_ENTRYPOINT_OFFSET(kMipsWordSize, pAllocStringFromBytes).Int32Value()); 2196ddc4055abab40740e689d91e9a4fe20a7b8e5d28Goran Jakovljevic __ Jalr(T9); 2197cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen __ Nop(); 2198cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen codegen_->RecordPcInfo(invoke, invoke->GetDexPc()); 2199cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen __ Bind(slow_path->GetExitLabel()); 2200cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen} 2201cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen 2202cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen// java.lang.StringFactory.newStringFromChars(int offset, int charCount, char[] data) 2203cf283daf579e9eda586f312c3fc89444601e2525Chris Larsenvoid IntrinsicLocationsBuilderMIPS::VisitStringNewStringFromChars(HInvoke* invoke) { 2204cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen LocationSummary* locations = new (arena_) LocationSummary(invoke, 2205cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen LocationSummary::kCall, 2206cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen kIntrinsified); 2207cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen InvokeRuntimeCallingConvention calling_convention; 2208cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0))); 2209cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen locations->SetInAt(1, Location::RegisterLocation(calling_convention.GetRegisterAt(1))); 2210cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen locations->SetInAt(2, Location::RegisterLocation(calling_convention.GetRegisterAt(2))); 2211cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen Location outLocation = calling_convention.GetReturnLocation(Primitive::kPrimInt); 2212cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen locations->SetOut(Location::RegisterLocation(outLocation.AsRegister<Register>())); 2213cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen} 2214cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen 2215cf283daf579e9eda586f312c3fc89444601e2525Chris Larsenvoid IntrinsicCodeGeneratorMIPS::VisitStringNewStringFromChars(HInvoke* invoke) { 2216cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen MipsAssembler* assembler = GetAssembler(); 2217cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen 2218cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen // No need to emit code checking whether `locations->InAt(2)` is a null 2219cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen // pointer, as callers of the native method 2220cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen // 2221cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen // java.lang.StringFactory.newStringFromChars(int offset, int charCount, char[] data) 2222cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen // 2223cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen // all include a null check on `data` before calling that method. 2224cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen 2225cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen __ LoadFromOffset(kLoadWord, 2226ddc4055abab40740e689d91e9a4fe20a7b8e5d28Goran Jakovljevic T9, 2227cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen TR, 2228cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen QUICK_ENTRYPOINT_OFFSET(kMipsWordSize, pAllocStringFromChars).Int32Value()); 2229ddc4055abab40740e689d91e9a4fe20a7b8e5d28Goran Jakovljevic __ Jalr(T9); 2230cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen __ Nop(); 2231cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen codegen_->RecordPcInfo(invoke, invoke->GetDexPc()); 2232cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen} 2233cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen 2234cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen// java.lang.StringFactory.newStringFromString(String toCopy) 2235cf283daf579e9eda586f312c3fc89444601e2525Chris Larsenvoid IntrinsicLocationsBuilderMIPS::VisitStringNewStringFromString(HInvoke* invoke) { 2236cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen LocationSummary* locations = new (arena_) LocationSummary(invoke, 2237cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen LocationSummary::kCall, 2238cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen kIntrinsified); 2239cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen InvokeRuntimeCallingConvention calling_convention; 2240cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0))); 2241cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen Location outLocation = calling_convention.GetReturnLocation(Primitive::kPrimInt); 2242cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen locations->SetOut(Location::RegisterLocation(outLocation.AsRegister<Register>())); 2243cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen} 2244cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen 2245cf283daf579e9eda586f312c3fc89444601e2525Chris Larsenvoid IntrinsicCodeGeneratorMIPS::VisitStringNewStringFromString(HInvoke* invoke) { 2246cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen MipsAssembler* assembler = GetAssembler(); 2247cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen LocationSummary* locations = invoke->GetLocations(); 2248cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen 2249cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen Register string_to_copy = locations->InAt(0).AsRegister<Register>(); 2250cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen SlowPathCodeMIPS* slow_path = new (GetAllocator()) IntrinsicSlowPathMIPS(invoke); 2251cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen codegen_->AddSlowPath(slow_path); 2252cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen __ Beqz(string_to_copy, slow_path->GetEntryLabel()); 2253cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen 2254cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen __ LoadFromOffset(kLoadWord, 2255ddc4055abab40740e689d91e9a4fe20a7b8e5d28Goran Jakovljevic T9, 2256cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen TR, 2257cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen QUICK_ENTRYPOINT_OFFSET(kMipsWordSize, pAllocStringFromString).Int32Value()); 2258ddc4055abab40740e689d91e9a4fe20a7b8e5d28Goran Jakovljevic __ Jalr(T9); 2259cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen __ Nop(); 2260cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen codegen_->RecordPcInfo(invoke, invoke->GetDexPc()); 2261cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen __ Bind(slow_path->GetExitLabel()); 2262cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen} 2263cf283daf579e9eda586f312c3fc89444601e2525Chris Larsen 22642714fe681fa9850bcbe3e2d3c3c72a5c77ca26b8Chris Larsenstatic void GenIsInfinite(LocationSummary* locations, 22652714fe681fa9850bcbe3e2d3c3c72a5c77ca26b8Chris Larsen const Primitive::Type type, 22662714fe681fa9850bcbe3e2d3c3c72a5c77ca26b8Chris Larsen const bool isR6, 22672714fe681fa9850bcbe3e2d3c3c72a5c77ca26b8Chris Larsen MipsAssembler* assembler) { 22682714fe681fa9850bcbe3e2d3c3c72a5c77ca26b8Chris Larsen FRegister in = locations->InAt(0).AsFpuRegister<FRegister>(); 22692714fe681fa9850bcbe3e2d3c3c72a5c77ca26b8Chris Larsen Register out = locations->Out().AsRegister<Register>(); 22702714fe681fa9850bcbe3e2d3c3c72a5c77ca26b8Chris Larsen 22712714fe681fa9850bcbe3e2d3c3c72a5c77ca26b8Chris Larsen DCHECK(type == Primitive::kPrimFloat || type == Primitive::kPrimDouble); 22722714fe681fa9850bcbe3e2d3c3c72a5c77ca26b8Chris Larsen 22732714fe681fa9850bcbe3e2d3c3c72a5c77ca26b8Chris Larsen if (isR6) { 22742714fe681fa9850bcbe3e2d3c3c72a5c77ca26b8Chris Larsen if (type == Primitive::kPrimDouble) { 22752714fe681fa9850bcbe3e2d3c3c72a5c77ca26b8Chris Larsen __ ClassD(FTMP, in); 22762714fe681fa9850bcbe3e2d3c3c72a5c77ca26b8Chris Larsen } else { 22772714fe681fa9850bcbe3e2d3c3c72a5c77ca26b8Chris Larsen __ ClassS(FTMP, in); 22782714fe681fa9850bcbe3e2d3c3c72a5c77ca26b8Chris Larsen } 22792714fe681fa9850bcbe3e2d3c3c72a5c77ca26b8Chris Larsen __ Mfc1(out, FTMP); 22802714fe681fa9850bcbe3e2d3c3c72a5c77ca26b8Chris Larsen __ Andi(out, out, kPositiveInfinity | kNegativeInfinity); 22812714fe681fa9850bcbe3e2d3c3c72a5c77ca26b8Chris Larsen __ Sltu(out, ZERO, out); 22822714fe681fa9850bcbe3e2d3c3c72a5c77ca26b8Chris Larsen } else { 22832714fe681fa9850bcbe3e2d3c3c72a5c77ca26b8Chris Larsen // If one, or more, of the exponent bits is zero, then the number can't be infinite. 22842714fe681fa9850bcbe3e2d3c3c72a5c77ca26b8Chris Larsen if (type == Primitive::kPrimDouble) { 22852714fe681fa9850bcbe3e2d3c3c72a5c77ca26b8Chris Larsen __ MoveFromFpuHigh(TMP, in); 22862714fe681fa9850bcbe3e2d3c3c72a5c77ca26b8Chris Larsen __ LoadConst32(AT, 0x7FF00000); 22872714fe681fa9850bcbe3e2d3c3c72a5c77ca26b8Chris Larsen } else { 22882714fe681fa9850bcbe3e2d3c3c72a5c77ca26b8Chris Larsen __ Mfc1(TMP, in); 22892714fe681fa9850bcbe3e2d3c3c72a5c77ca26b8Chris Larsen __ LoadConst32(AT, 0x7F800000); 22902714fe681fa9850bcbe3e2d3c3c72a5c77ca26b8Chris Larsen } 22912714fe681fa9850bcbe3e2d3c3c72a5c77ca26b8Chris Larsen __ Xor(TMP, TMP, AT); 22922714fe681fa9850bcbe3e2d3c3c72a5c77ca26b8Chris Larsen 22932714fe681fa9850bcbe3e2d3c3c72a5c77ca26b8Chris Larsen __ Sll(TMP, TMP, 1); 22942714fe681fa9850bcbe3e2d3c3c72a5c77ca26b8Chris Larsen 22952714fe681fa9850bcbe3e2d3c3c72a5c77ca26b8Chris Larsen if (type == Primitive::kPrimDouble) { 22962714fe681fa9850bcbe3e2d3c3c72a5c77ca26b8Chris Larsen __ Mfc1(AT, in); 22972714fe681fa9850bcbe3e2d3c3c72a5c77ca26b8Chris Larsen __ Or(TMP, TMP, AT); 22982714fe681fa9850bcbe3e2d3c3c72a5c77ca26b8Chris Larsen } 22992714fe681fa9850bcbe3e2d3c3c72a5c77ca26b8Chris Larsen // If any of the significand bits are one, then the number is not infinite. 23002714fe681fa9850bcbe3e2d3c3c72a5c77ca26b8Chris Larsen __ Sltiu(out, TMP, 1); 23012714fe681fa9850bcbe3e2d3c3c72a5c77ca26b8Chris Larsen } 23022714fe681fa9850bcbe3e2d3c3c72a5c77ca26b8Chris Larsen} 23032714fe681fa9850bcbe3e2d3c3c72a5c77ca26b8Chris Larsen 23042714fe681fa9850bcbe3e2d3c3c72a5c77ca26b8Chris Larsen// boolean java.lang.Float.isInfinite(float) 23052714fe681fa9850bcbe3e2d3c3c72a5c77ca26b8Chris Larsenvoid IntrinsicLocationsBuilderMIPS::VisitFloatIsInfinite(HInvoke* invoke) { 23062714fe681fa9850bcbe3e2d3c3c72a5c77ca26b8Chris Larsen CreateFPToIntLocations(arena_, invoke); 23072714fe681fa9850bcbe3e2d3c3c72a5c77ca26b8Chris Larsen} 23082714fe681fa9850bcbe3e2d3c3c72a5c77ca26b8Chris Larsen 23092714fe681fa9850bcbe3e2d3c3c72a5c77ca26b8Chris Larsenvoid IntrinsicCodeGeneratorMIPS::VisitFloatIsInfinite(HInvoke* invoke) { 23102714fe681fa9850bcbe3e2d3c3c72a5c77ca26b8Chris Larsen GenIsInfinite(invoke->GetLocations(), Primitive::kPrimFloat, IsR6(), GetAssembler()); 23112714fe681fa9850bcbe3e2d3c3c72a5c77ca26b8Chris Larsen} 23122714fe681fa9850bcbe3e2d3c3c72a5c77ca26b8Chris Larsen 23132714fe681fa9850bcbe3e2d3c3c72a5c77ca26b8Chris Larsen// boolean java.lang.Double.isInfinite(double) 23142714fe681fa9850bcbe3e2d3c3c72a5c77ca26b8Chris Larsenvoid IntrinsicLocationsBuilderMIPS::VisitDoubleIsInfinite(HInvoke* invoke) { 23152714fe681fa9850bcbe3e2d3c3c72a5c77ca26b8Chris Larsen CreateFPToIntLocations(arena_, invoke); 23162714fe681fa9850bcbe3e2d3c3c72a5c77ca26b8Chris Larsen} 23172714fe681fa9850bcbe3e2d3c3c72a5c77ca26b8Chris Larsen 23182714fe681fa9850bcbe3e2d3c3c72a5c77ca26b8Chris Larsenvoid IntrinsicCodeGeneratorMIPS::VisitDoubleIsInfinite(HInvoke* invoke) { 23192714fe681fa9850bcbe3e2d3c3c72a5c77ca26b8Chris Larsen GenIsInfinite(invoke->GetLocations(), Primitive::kPrimDouble, IsR6(), GetAssembler()); 23202714fe681fa9850bcbe3e2d3c3c72a5c77ca26b8Chris Larsen} 23212714fe681fa9850bcbe3e2d3c3c72a5c77ca26b8Chris Larsen 23229775934cb141deb096183f89449ca28ec7c11798Chris Larsenstatic void GenHighestOneBit(LocationSummary* locations, 23239775934cb141deb096183f89449ca28ec7c11798Chris Larsen const Primitive::Type type, 23249775934cb141deb096183f89449ca28ec7c11798Chris Larsen bool isR6, 23259775934cb141deb096183f89449ca28ec7c11798Chris Larsen MipsAssembler* assembler) { 23269775934cb141deb096183f89449ca28ec7c11798Chris Larsen DCHECK(type == Primitive::kPrimInt || type == Primitive::kPrimLong); 23279775934cb141deb096183f89449ca28ec7c11798Chris Larsen 23289775934cb141deb096183f89449ca28ec7c11798Chris Larsen if (type == Primitive::kPrimLong) { 23299775934cb141deb096183f89449ca28ec7c11798Chris Larsen Register in_lo = locations->InAt(0).AsRegisterPairLow<Register>(); 23309775934cb141deb096183f89449ca28ec7c11798Chris Larsen Register in_hi = locations->InAt(0).AsRegisterPairHigh<Register>(); 23319775934cb141deb096183f89449ca28ec7c11798Chris Larsen Register out_lo = locations->Out().AsRegisterPairLow<Register>(); 23329775934cb141deb096183f89449ca28ec7c11798Chris Larsen Register out_hi = locations->Out().AsRegisterPairHigh<Register>(); 23339775934cb141deb096183f89449ca28ec7c11798Chris Larsen 23349775934cb141deb096183f89449ca28ec7c11798Chris Larsen if (isR6) { 23359775934cb141deb096183f89449ca28ec7c11798Chris Larsen __ ClzR6(TMP, in_hi); 23369775934cb141deb096183f89449ca28ec7c11798Chris Larsen } else { 23379775934cb141deb096183f89449ca28ec7c11798Chris Larsen __ ClzR2(TMP, in_hi); 23389775934cb141deb096183f89449ca28ec7c11798Chris Larsen } 23399775934cb141deb096183f89449ca28ec7c11798Chris Larsen __ LoadConst32(AT, 0x80000000); 23409775934cb141deb096183f89449ca28ec7c11798Chris Larsen __ Srlv(out_hi, AT, TMP); 23419775934cb141deb096183f89449ca28ec7c11798Chris Larsen __ And(out_hi, out_hi, in_hi); 23429775934cb141deb096183f89449ca28ec7c11798Chris Larsen if (isR6) { 23439775934cb141deb096183f89449ca28ec7c11798Chris Larsen __ ClzR6(TMP, in_lo); 23449775934cb141deb096183f89449ca28ec7c11798Chris Larsen } else { 23459775934cb141deb096183f89449ca28ec7c11798Chris Larsen __ ClzR2(TMP, in_lo); 23469775934cb141deb096183f89449ca28ec7c11798Chris Larsen } 23479775934cb141deb096183f89449ca28ec7c11798Chris Larsen __ Srlv(out_lo, AT, TMP); 23489775934cb141deb096183f89449ca28ec7c11798Chris Larsen __ And(out_lo, out_lo, in_lo); 23499775934cb141deb096183f89449ca28ec7c11798Chris Larsen if (isR6) { 23509775934cb141deb096183f89449ca28ec7c11798Chris Larsen __ Seleqz(out_lo, out_lo, out_hi); 23519775934cb141deb096183f89449ca28ec7c11798Chris Larsen } else { 23529775934cb141deb096183f89449ca28ec7c11798Chris Larsen __ Movn(out_lo, ZERO, out_hi); 23539775934cb141deb096183f89449ca28ec7c11798Chris Larsen } 23549775934cb141deb096183f89449ca28ec7c11798Chris Larsen } else { 23559775934cb141deb096183f89449ca28ec7c11798Chris Larsen Register in = locations->InAt(0).AsRegister<Register>(); 23569775934cb141deb096183f89449ca28ec7c11798Chris Larsen Register out = locations->Out().AsRegister<Register>(); 23579775934cb141deb096183f89449ca28ec7c11798Chris Larsen 23589775934cb141deb096183f89449ca28ec7c11798Chris Larsen if (isR6) { 23599775934cb141deb096183f89449ca28ec7c11798Chris Larsen __ ClzR6(TMP, in); 23609775934cb141deb096183f89449ca28ec7c11798Chris Larsen } else { 23619775934cb141deb096183f89449ca28ec7c11798Chris Larsen __ ClzR2(TMP, in); 23629775934cb141deb096183f89449ca28ec7c11798Chris Larsen } 23639775934cb141deb096183f89449ca28ec7c11798Chris Larsen __ LoadConst32(AT, 0x80000000); 23649775934cb141deb096183f89449ca28ec7c11798Chris Larsen __ Srlv(AT, AT, TMP); // Srlv shifts in the range of [0;31] bits (lower 5 bits of arg). 23659775934cb141deb096183f89449ca28ec7c11798Chris Larsen __ And(out, AT, in); // So this is required for 0 (=shift by 32). 23669775934cb141deb096183f89449ca28ec7c11798Chris Larsen } 23679775934cb141deb096183f89449ca28ec7c11798Chris Larsen} 23689775934cb141deb096183f89449ca28ec7c11798Chris Larsen 23699775934cb141deb096183f89449ca28ec7c11798Chris Larsen// int java.lang.Integer.highestOneBit(int) 23709775934cb141deb096183f89449ca28ec7c11798Chris Larsenvoid IntrinsicLocationsBuilderMIPS::VisitIntegerHighestOneBit(HInvoke* invoke) { 23719775934cb141deb096183f89449ca28ec7c11798Chris Larsen CreateIntToIntLocations(arena_, invoke); 23729775934cb141deb096183f89449ca28ec7c11798Chris Larsen} 23739775934cb141deb096183f89449ca28ec7c11798Chris Larsen 23749775934cb141deb096183f89449ca28ec7c11798Chris Larsenvoid IntrinsicCodeGeneratorMIPS::VisitIntegerHighestOneBit(HInvoke* invoke) { 23759775934cb141deb096183f89449ca28ec7c11798Chris Larsen GenHighestOneBit(invoke->GetLocations(), Primitive::kPrimInt, IsR6(), GetAssembler()); 23769775934cb141deb096183f89449ca28ec7c11798Chris Larsen} 23779775934cb141deb096183f89449ca28ec7c11798Chris Larsen 23789775934cb141deb096183f89449ca28ec7c11798Chris Larsen// long java.lang.Long.highestOneBit(long) 23799775934cb141deb096183f89449ca28ec7c11798Chris Larsenvoid IntrinsicLocationsBuilderMIPS::VisitLongHighestOneBit(HInvoke* invoke) { 23809775934cb141deb096183f89449ca28ec7c11798Chris Larsen CreateIntToIntLocations(arena_, invoke, Location::kOutputOverlap); 23819775934cb141deb096183f89449ca28ec7c11798Chris Larsen} 23829775934cb141deb096183f89449ca28ec7c11798Chris Larsen 23839775934cb141deb096183f89449ca28ec7c11798Chris Larsenvoid IntrinsicCodeGeneratorMIPS::VisitLongHighestOneBit(HInvoke* invoke) { 23849775934cb141deb096183f89449ca28ec7c11798Chris Larsen GenHighestOneBit(invoke->GetLocations(), Primitive::kPrimLong, IsR6(), GetAssembler()); 23859775934cb141deb096183f89449ca28ec7c11798Chris Larsen} 23869775934cb141deb096183f89449ca28ec7c11798Chris Larsen 23879775934cb141deb096183f89449ca28ec7c11798Chris Larsenstatic void GenLowestOneBit(LocationSummary* locations, 23889775934cb141deb096183f89449ca28ec7c11798Chris Larsen const Primitive::Type type, 23899775934cb141deb096183f89449ca28ec7c11798Chris Larsen bool isR6, 23909775934cb141deb096183f89449ca28ec7c11798Chris Larsen MipsAssembler* assembler) { 23919775934cb141deb096183f89449ca28ec7c11798Chris Larsen DCHECK(type == Primitive::kPrimInt || type == Primitive::kPrimLong); 23929775934cb141deb096183f89449ca28ec7c11798Chris Larsen 23939775934cb141deb096183f89449ca28ec7c11798Chris Larsen if (type == Primitive::kPrimLong) { 23949775934cb141deb096183f89449ca28ec7c11798Chris Larsen Register in_lo = locations->InAt(0).AsRegisterPairLow<Register>(); 23959775934cb141deb096183f89449ca28ec7c11798Chris Larsen Register in_hi = locations->InAt(0).AsRegisterPairHigh<Register>(); 23969775934cb141deb096183f89449ca28ec7c11798Chris Larsen Register out_lo = locations->Out().AsRegisterPairLow<Register>(); 23979775934cb141deb096183f89449ca28ec7c11798Chris Larsen Register out_hi = locations->Out().AsRegisterPairHigh<Register>(); 23989775934cb141deb096183f89449ca28ec7c11798Chris Larsen 23999775934cb141deb096183f89449ca28ec7c11798Chris Larsen __ Subu(TMP, ZERO, in_lo); 24009775934cb141deb096183f89449ca28ec7c11798Chris Larsen __ And(out_lo, TMP, in_lo); 24019775934cb141deb096183f89449ca28ec7c11798Chris Larsen __ Subu(TMP, ZERO, in_hi); 24029775934cb141deb096183f89449ca28ec7c11798Chris Larsen __ And(out_hi, TMP, in_hi); 24039775934cb141deb096183f89449ca28ec7c11798Chris Larsen if (isR6) { 24049775934cb141deb096183f89449ca28ec7c11798Chris Larsen __ Seleqz(out_hi, out_hi, out_lo); 24059775934cb141deb096183f89449ca28ec7c11798Chris Larsen } else { 24069775934cb141deb096183f89449ca28ec7c11798Chris Larsen __ Movn(out_hi, ZERO, out_lo); 24079775934cb141deb096183f89449ca28ec7c11798Chris Larsen } 24089775934cb141deb096183f89449ca28ec7c11798Chris Larsen } else { 24099775934cb141deb096183f89449ca28ec7c11798Chris Larsen Register in = locations->InAt(0).AsRegister<Register>(); 24109775934cb141deb096183f89449ca28ec7c11798Chris Larsen Register out = locations->Out().AsRegister<Register>(); 24119775934cb141deb096183f89449ca28ec7c11798Chris Larsen 24129775934cb141deb096183f89449ca28ec7c11798Chris Larsen __ Subu(TMP, ZERO, in); 24139775934cb141deb096183f89449ca28ec7c11798Chris Larsen __ And(out, TMP, in); 24149775934cb141deb096183f89449ca28ec7c11798Chris Larsen } 24159775934cb141deb096183f89449ca28ec7c11798Chris Larsen} 24169775934cb141deb096183f89449ca28ec7c11798Chris Larsen 24179775934cb141deb096183f89449ca28ec7c11798Chris Larsen// int java.lang.Integer.lowestOneBit(int) 24189775934cb141deb096183f89449ca28ec7c11798Chris Larsenvoid IntrinsicLocationsBuilderMIPS::VisitIntegerLowestOneBit(HInvoke* invoke) { 24199775934cb141deb096183f89449ca28ec7c11798Chris Larsen CreateIntToIntLocations(arena_, invoke); 24209775934cb141deb096183f89449ca28ec7c11798Chris Larsen} 24219775934cb141deb096183f89449ca28ec7c11798Chris Larsen 24229775934cb141deb096183f89449ca28ec7c11798Chris Larsenvoid IntrinsicCodeGeneratorMIPS::VisitIntegerLowestOneBit(HInvoke* invoke) { 24239775934cb141deb096183f89449ca28ec7c11798Chris Larsen GenLowestOneBit(invoke->GetLocations(), Primitive::kPrimInt, IsR6(), GetAssembler()); 24249775934cb141deb096183f89449ca28ec7c11798Chris Larsen} 24259775934cb141deb096183f89449ca28ec7c11798Chris Larsen 24269775934cb141deb096183f89449ca28ec7c11798Chris Larsen// long java.lang.Long.lowestOneBit(long) 24279775934cb141deb096183f89449ca28ec7c11798Chris Larsenvoid IntrinsicLocationsBuilderMIPS::VisitLongLowestOneBit(HInvoke* invoke) { 24289775934cb141deb096183f89449ca28ec7c11798Chris Larsen CreateIntToIntLocations(arena_, invoke); 24299775934cb141deb096183f89449ca28ec7c11798Chris Larsen} 24309775934cb141deb096183f89449ca28ec7c11798Chris Larsen 24319775934cb141deb096183f89449ca28ec7c11798Chris Larsenvoid IntrinsicCodeGeneratorMIPS::VisitLongLowestOneBit(HInvoke* invoke) { 24329775934cb141deb096183f89449ca28ec7c11798Chris Larsen GenLowestOneBit(invoke->GetLocations(), Primitive::kPrimLong, IsR6(), GetAssembler()); 24339775934cb141deb096183f89449ca28ec7c11798Chris Larsen} 24349775934cb141deb096183f89449ca28ec7c11798Chris Larsen 24352714fe681fa9850bcbe3e2d3c3c72a5c77ca26b8Chris Larsen// Unimplemented intrinsics. 24362714fe681fa9850bcbe3e2d3c3c72a5c77ca26b8Chris Larsen 24372f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart BikUNIMPLEMENTED_INTRINSIC(MIPS, MathCeil) 24382f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart BikUNIMPLEMENTED_INTRINSIC(MIPS, MathFloor) 24392f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart BikUNIMPLEMENTED_INTRINSIC(MIPS, MathRint) 24402f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart BikUNIMPLEMENTED_INTRINSIC(MIPS, MathRoundDouble) 24412f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart BikUNIMPLEMENTED_INTRINSIC(MIPS, MathRoundFloat) 24422f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart BikUNIMPLEMENTED_INTRINSIC(MIPS, UnsafeCASLong) 24432f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik 24442f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart BikUNIMPLEMENTED_INTRINSIC(MIPS, ReferenceGetReferent) 24452f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart BikUNIMPLEMENTED_INTRINSIC(MIPS, StringGetCharsNoCheck) 24462f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart BikUNIMPLEMENTED_INTRINSIC(MIPS, SystemArrayCopyChar) 24472f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart BikUNIMPLEMENTED_INTRINSIC(MIPS, SystemArrayCopy) 24482f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik 24492f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart BikUNIMPLEMENTED_INTRINSIC(MIPS, MathCos) 24502f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart BikUNIMPLEMENTED_INTRINSIC(MIPS, MathSin) 24512f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart BikUNIMPLEMENTED_INTRINSIC(MIPS, MathAcos) 24522f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart BikUNIMPLEMENTED_INTRINSIC(MIPS, MathAsin) 24532f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart BikUNIMPLEMENTED_INTRINSIC(MIPS, MathAtan) 24542f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart BikUNIMPLEMENTED_INTRINSIC(MIPS, MathAtan2) 24552f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart BikUNIMPLEMENTED_INTRINSIC(MIPS, MathCbrt) 24562f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart BikUNIMPLEMENTED_INTRINSIC(MIPS, MathCosh) 24572f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart BikUNIMPLEMENTED_INTRINSIC(MIPS, MathExp) 24582f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart BikUNIMPLEMENTED_INTRINSIC(MIPS, MathExpm1) 24592f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart BikUNIMPLEMENTED_INTRINSIC(MIPS, MathHypot) 24602f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart BikUNIMPLEMENTED_INTRINSIC(MIPS, MathLog) 24612f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart BikUNIMPLEMENTED_INTRINSIC(MIPS, MathLog10) 24622f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart BikUNIMPLEMENTED_INTRINSIC(MIPS, MathNextAfter) 24632f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart BikUNIMPLEMENTED_INTRINSIC(MIPS, MathSinh) 24642f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart BikUNIMPLEMENTED_INTRINSIC(MIPS, MathTan) 24652f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart BikUNIMPLEMENTED_INTRINSIC(MIPS, MathTanh) 24662f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik 24670e54c0160c84894696c05af6cad9eae3690f9496Aart Bik// 1.8. 24680e54c0160c84894696c05af6cad9eae3690f9496Aart BikUNIMPLEMENTED_INTRINSIC(MIPS, UnsafeGetAndAddInt) 24690e54c0160c84894696c05af6cad9eae3690f9496Aart BikUNIMPLEMENTED_INTRINSIC(MIPS, UnsafeGetAndAddLong) 24700e54c0160c84894696c05af6cad9eae3690f9496Aart BikUNIMPLEMENTED_INTRINSIC(MIPS, UnsafeGetAndSetInt) 24710e54c0160c84894696c05af6cad9eae3690f9496Aart BikUNIMPLEMENTED_INTRINSIC(MIPS, UnsafeGetAndSetLong) 24720e54c0160c84894696c05af6cad9eae3690f9496Aart BikUNIMPLEMENTED_INTRINSIC(MIPS, UnsafeGetAndSetObject) 2473701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen 24740e54c0160c84894696c05af6cad9eae3690f9496Aart BikUNREACHABLE_INTRINSICS(MIPS) 24752714fe681fa9850bcbe3e2d3c3c72a5c77ca26b8Chris Larsen 2476701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen#undef __ 2477701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen 2478701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen} // namespace mips 2479701566aaae098d5aab9d912e2003a18d44fb850dChris Larsen} // namespace art 2480