blob: 5efcf4eadf3f6294311af4cfd2cb2bf68f3a8f26 [file] [log] [blame]
Chris Larsen701566a2015-10-27 15:29:13 -07001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "intrinsics_mips.h"
18
19#include "arch/mips/instruction_set_features_mips.h"
20#include "art_method.h"
21#include "code_generator_mips.h"
22#include "entrypoints/quick/quick_entrypoints.h"
23#include "intrinsics.h"
24#include "mirror/array-inl.h"
25#include "mirror/string.h"
26#include "thread.h"
27#include "utils/mips/assembler_mips.h"
28#include "utils/mips/constants_mips.h"
29
30namespace art {
31
32namespace mips {
33
34IntrinsicLocationsBuilderMIPS::IntrinsicLocationsBuilderMIPS(CodeGeneratorMIPS* codegen)
35 : arena_(codegen->GetGraph()->GetArena()) {
36}
37
38MipsAssembler* IntrinsicCodeGeneratorMIPS::GetAssembler() {
39 return reinterpret_cast<MipsAssembler*>(codegen_->GetAssembler());
40}
41
42ArenaAllocator* IntrinsicCodeGeneratorMIPS::GetAllocator() {
43 return codegen_->GetGraph()->GetArena();
44}
45
46#define __ codegen->GetAssembler()->
47
48static void MoveFromReturnRegister(Location trg,
49 Primitive::Type type,
50 CodeGeneratorMIPS* codegen) {
51 if (!trg.IsValid()) {
52 DCHECK_EQ(type, Primitive::kPrimVoid);
53 return;
54 }
55
56 DCHECK_NE(type, Primitive::kPrimVoid);
57
58 if (Primitive::IsIntegralType(type) || type == Primitive::kPrimNot) {
59 Register trg_reg = trg.AsRegister<Register>();
60 if (trg_reg != V0) {
61 __ Move(V0, trg_reg);
62 }
63 } else {
64 FRegister trg_reg = trg.AsFpuRegister<FRegister>();
65 if (trg_reg != F0) {
66 if (type == Primitive::kPrimFloat) {
67 __ MovS(F0, trg_reg);
68 } else {
69 __ MovD(F0, trg_reg);
70 }
71 }
72 }
73}
74
75static void MoveArguments(HInvoke* invoke, CodeGeneratorMIPS* codegen) {
76 InvokeDexCallingConventionVisitorMIPS calling_convention_visitor;
77 IntrinsicVisitor::MoveArguments(invoke, codegen, &calling_convention_visitor);
78}
79
80// Slow-path for fallback (calling the managed code to handle the
81// intrinsic) in an intrinsified call. This will copy the arguments
82// into the positions for a regular call.
83//
84// Note: The actual parameters are required to be in the locations
85// given by the invoke's location summary. If an intrinsic
86// modifies those locations before a slowpath call, they must be
87// restored!
88class IntrinsicSlowPathMIPS : public SlowPathCodeMIPS {
89 public:
90 explicit IntrinsicSlowPathMIPS(HInvoke* invoke) : invoke_(invoke) { }
91
92 void EmitNativeCode(CodeGenerator* codegen_in) OVERRIDE {
93 CodeGeneratorMIPS* codegen = down_cast<CodeGeneratorMIPS*>(codegen_in);
94
95 __ Bind(GetEntryLabel());
96
97 SaveLiveRegisters(codegen, invoke_->GetLocations());
98
99 MoveArguments(invoke_, codegen);
100
101 if (invoke_->IsInvokeStaticOrDirect()) {
102 codegen->GenerateStaticOrDirectCall(invoke_->AsInvokeStaticOrDirect(),
103 Location::RegisterLocation(A0));
104 codegen->RecordPcInfo(invoke_, invoke_->GetDexPc(), this);
105 } else {
106 UNIMPLEMENTED(FATAL) << "Non-direct intrinsic slow-path not yet implemented";
107 UNREACHABLE();
108 }
109
110 // Copy the result back to the expected output.
111 Location out = invoke_->GetLocations()->Out();
112 if (out.IsValid()) {
113 DCHECK(out.IsRegister()); // TODO: Replace this when we support output in memory.
114 DCHECK(!invoke_->GetLocations()->GetLiveRegisters()->ContainsCoreRegister(out.reg()));
115 MoveFromReturnRegister(out, invoke_->GetType(), codegen);
116 }
117
118 RestoreLiveRegisters(codegen, invoke_->GetLocations());
119 __ B(GetExitLabel());
120 }
121
122 const char* GetDescription() const OVERRIDE { return "IntrinsicSlowPathMIPS"; }
123
124 private:
125 // The instruction where this slow path is happening.
126 HInvoke* const invoke_;
127
128 DISALLOW_COPY_AND_ASSIGN(IntrinsicSlowPathMIPS);
129};
130
131#undef __
132
133bool IntrinsicLocationsBuilderMIPS::TryDispatch(HInvoke* invoke) {
134 Dispatch(invoke);
135 LocationSummary* res = invoke->GetLocations();
136 return res != nullptr && res->Intrinsified();
137}
138
139#define __ assembler->
140
141// Unimplemented intrinsics.
142
143#define UNIMPLEMENTED_INTRINSIC(Name) \
144void IntrinsicLocationsBuilderMIPS::Visit ## Name(HInvoke* invoke ATTRIBUTE_UNUSED) { \
145} \
146void IntrinsicCodeGeneratorMIPS::Visit ## Name(HInvoke* invoke ATTRIBUTE_UNUSED) { \
147}
148
149UNIMPLEMENTED_INTRINSIC(IntegerReverse)
150UNIMPLEMENTED_INTRINSIC(LongReverse)
151UNIMPLEMENTED_INTRINSIC(ShortReverseBytes)
152UNIMPLEMENTED_INTRINSIC(IntegerReverseBytes)
153UNIMPLEMENTED_INTRINSIC(LongReverseBytes)
154UNIMPLEMENTED_INTRINSIC(LongNumberOfLeadingZeros)
155UNIMPLEMENTED_INTRINSIC(IntegerNumberOfLeadingZeros)
156UNIMPLEMENTED_INTRINSIC(FloatIntBitsToFloat)
157UNIMPLEMENTED_INTRINSIC(DoubleLongBitsToDouble)
158UNIMPLEMENTED_INTRINSIC(FloatFloatToRawIntBits)
159UNIMPLEMENTED_INTRINSIC(DoubleDoubleToRawLongBits)
160UNIMPLEMENTED_INTRINSIC(MathAbsDouble)
161UNIMPLEMENTED_INTRINSIC(MathAbsFloat)
162UNIMPLEMENTED_INTRINSIC(MathAbsInt)
163UNIMPLEMENTED_INTRINSIC(MathAbsLong)
164UNIMPLEMENTED_INTRINSIC(MathMinDoubleDouble)
165UNIMPLEMENTED_INTRINSIC(MathMinFloatFloat)
166UNIMPLEMENTED_INTRINSIC(MathMaxDoubleDouble)
167UNIMPLEMENTED_INTRINSIC(MathMaxFloatFloat)
168UNIMPLEMENTED_INTRINSIC(MathMinIntInt)
169UNIMPLEMENTED_INTRINSIC(MathMinLongLong)
170UNIMPLEMENTED_INTRINSIC(MathMaxIntInt)
171UNIMPLEMENTED_INTRINSIC(MathMaxLongLong)
172UNIMPLEMENTED_INTRINSIC(MathSqrt)
173UNIMPLEMENTED_INTRINSIC(MathCeil)
174UNIMPLEMENTED_INTRINSIC(MathFloor)
175UNIMPLEMENTED_INTRINSIC(MathRint)
176UNIMPLEMENTED_INTRINSIC(MathRoundDouble)
177UNIMPLEMENTED_INTRINSIC(MathRoundFloat)
178UNIMPLEMENTED_INTRINSIC(MemoryPeekByte)
179UNIMPLEMENTED_INTRINSIC(MemoryPeekIntNative)
180UNIMPLEMENTED_INTRINSIC(MemoryPeekLongNative)
181UNIMPLEMENTED_INTRINSIC(MemoryPeekShortNative)
182UNIMPLEMENTED_INTRINSIC(MemoryPokeByte)
183UNIMPLEMENTED_INTRINSIC(MemoryPokeIntNative)
184UNIMPLEMENTED_INTRINSIC(MemoryPokeLongNative)
185UNIMPLEMENTED_INTRINSIC(MemoryPokeShortNative)
186UNIMPLEMENTED_INTRINSIC(ThreadCurrentThread)
187UNIMPLEMENTED_INTRINSIC(UnsafeGet)
188UNIMPLEMENTED_INTRINSIC(UnsafeGetVolatile)
189UNIMPLEMENTED_INTRINSIC(UnsafeGetLong)
190UNIMPLEMENTED_INTRINSIC(UnsafeGetLongVolatile)
191UNIMPLEMENTED_INTRINSIC(UnsafeGetObject)
192UNIMPLEMENTED_INTRINSIC(UnsafeGetObjectVolatile)
193UNIMPLEMENTED_INTRINSIC(UnsafePut)
194UNIMPLEMENTED_INTRINSIC(UnsafePutOrdered)
195UNIMPLEMENTED_INTRINSIC(UnsafePutVolatile)
196UNIMPLEMENTED_INTRINSIC(UnsafePutObject)
197UNIMPLEMENTED_INTRINSIC(UnsafePutObjectOrdered)
198UNIMPLEMENTED_INTRINSIC(UnsafePutObjectVolatile)
199UNIMPLEMENTED_INTRINSIC(UnsafePutLong)
200UNIMPLEMENTED_INTRINSIC(UnsafePutLongOrdered)
201UNIMPLEMENTED_INTRINSIC(UnsafePutLongVolatile)
202UNIMPLEMENTED_INTRINSIC(UnsafeCASInt)
203UNIMPLEMENTED_INTRINSIC(UnsafeCASLong)
204UNIMPLEMENTED_INTRINSIC(UnsafeCASObject)
205UNIMPLEMENTED_INTRINSIC(StringCharAt)
206UNIMPLEMENTED_INTRINSIC(StringCompareTo)
207UNIMPLEMENTED_INTRINSIC(StringEquals)
208UNIMPLEMENTED_INTRINSIC(StringIndexOf)
209UNIMPLEMENTED_INTRINSIC(StringIndexOfAfter)
210UNIMPLEMENTED_INTRINSIC(StringNewStringFromBytes)
211UNIMPLEMENTED_INTRINSIC(StringNewStringFromChars)
212UNIMPLEMENTED_INTRINSIC(StringNewStringFromString)
213UNIMPLEMENTED_INTRINSIC(LongRotateLeft)
214UNIMPLEMENTED_INTRINSIC(LongRotateRight)
215UNIMPLEMENTED_INTRINSIC(LongNumberOfTrailingZeros)
216UNIMPLEMENTED_INTRINSIC(IntegerRotateLeft)
217UNIMPLEMENTED_INTRINSIC(IntegerRotateRight)
218UNIMPLEMENTED_INTRINSIC(IntegerNumberOfTrailingZeros)
219
220UNIMPLEMENTED_INTRINSIC(ReferenceGetReferent)
221UNIMPLEMENTED_INTRINSIC(StringGetCharsNoCheck)
222UNIMPLEMENTED_INTRINSIC(SystemArrayCopyChar)
223UNIMPLEMENTED_INTRINSIC(SystemArrayCopy)
224
225#undef UNIMPLEMENTED_INTRINSIC
226
227#undef __
228
229} // namespace mips
230} // namespace art