blob: 27691ac080a83afc7ade268c4a9683248f0ac608 [file] [log] [blame]
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +00001/*
2 * Copyright (C) 2014 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 "code_generator_arm.h"
18#include "utils/assembler.h"
19#include "utils/arm/assembler_arm.h"
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +010020#include "utils/arm/managed_register_arm.h"
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000021
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +000022#include "mirror/array.h"
23#include "mirror/art_method.h"
24
Nicolas Geoffray787c3072014-03-17 10:20:19 +000025#define __ reinterpret_cast<ArmAssembler*>(GetAssembler())->
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000026
27namespace art {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +010028
29arm::ArmManagedRegister Location::AsArm() const {
30 return reg().AsArm();
31}
32
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000033namespace arm {
34
Nicolas Geoffray4a34a422014-04-03 10:38:37 +010035static constexpr int kNumberOfPushedRegistersAtEntry = 1;
36static constexpr int kCurrentMethodStackOffset = 0;
37
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +010038static Location ArmCoreLocation(Register reg) {
39 return Location::RegisterLocation(ArmManagedRegister::FromCoreRegister(reg));
40}
41
Nicolas Geoffray4a34a422014-04-03 10:38:37 +010042InstructionCodeGeneratorARM::InstructionCodeGeneratorARM(HGraph* graph, CodeGeneratorARM* codegen)
43 : HGraphVisitor(graph),
44 assembler_(codegen->GetAssembler()),
45 codegen_(codegen) {}
46
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000047void CodeGeneratorARM::GenerateFrameEntry() {
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +000048 core_spill_mask_ |= (1 << LR);
Nicolas Geoffray4a34a422014-04-03 10:38:37 +010049 __ PushList((1 << LR));
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +000050
Nicolas Geoffraya747a392014-04-17 14:56:23 +010051 SetFrameSize(RoundUp(
52 (GetGraph()->GetMaximumNumberOfOutVRegs() + GetGraph()->GetNumberOfVRegs()) * kVRegSize
53 + kVRegSize // filler
54 + kArmWordSize // Art method
55 + kNumberOfPushedRegistersAtEntry * kArmWordSize,
Nicolas Geoffrayf583e592014-04-07 13:20:42 +010056 kStackAlignment));
57 // The return PC has already been pushed on the stack.
Nicolas Geoffray707c8092014-04-04 10:50:14 +010058 __ AddConstant(SP, -(GetFrameSize() - kNumberOfPushedRegistersAtEntry * kArmWordSize));
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +000059 __ str(R0, Address(SP, 0));
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000060}
61
62void CodeGeneratorARM::GenerateFrameExit() {
Nicolas Geoffray707c8092014-04-04 10:50:14 +010063 __ AddConstant(SP, GetFrameSize() - kNumberOfPushedRegistersAtEntry * kArmWordSize);
Nicolas Geoffray4a34a422014-04-03 10:38:37 +010064 __ PopList((1 << PC));
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000065}
66
67void CodeGeneratorARM::Bind(Label* label) {
68 __ Bind(label);
69}
70
Nicolas Geoffray4a34a422014-04-03 10:38:37 +010071int32_t CodeGeneratorARM::GetStackSlot(HLocal* local) const {
Nicolas Geoffrayf583e592014-04-07 13:20:42 +010072 uint16_t reg_number = local->GetRegNumber();
73 uint16_t number_of_vregs = GetGraph()->GetNumberOfVRegs();
74 uint16_t number_of_in_vregs = GetGraph()->GetNumberOfInVRegs();
75 if (reg_number >= number_of_vregs - number_of_in_vregs) {
76 // Local is a parameter of the method. It is stored in the caller's frame.
77 return GetFrameSize() + kArmWordSize // ART method
Nicolas Geoffraya747a392014-04-17 14:56:23 +010078 + (reg_number - number_of_vregs + number_of_in_vregs) * kVRegSize;
Nicolas Geoffrayf583e592014-04-07 13:20:42 +010079 } else {
80 // Local is a temporary in this method. It is stored in this method's frame.
81 return GetFrameSize() - (kNumberOfPushedRegistersAtEntry * kArmWordSize)
Nicolas Geoffraya747a392014-04-17 14:56:23 +010082 - kVRegSize // filler.
83 - (number_of_vregs * kVRegSize)
84 + (reg_number * kVRegSize);
Nicolas Geoffrayf583e592014-04-07 13:20:42 +010085 }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +000086}
87
Nicolas Geoffraya747a392014-04-17 14:56:23 +010088Location InvokeDexCallingConventionVisitor::GetNextLocation(Primitive::Type type) {
89 switch (type) {
90 case Primitive::kPrimBoolean:
91 case Primitive::kPrimByte:
92 case Primitive::kPrimChar:
93 case Primitive::kPrimShort:
94 case Primitive::kPrimInt:
95 case Primitive::kPrimNot: {
96 uint32_t index = gp_index_++;
97 if (index < calling_convention.GetNumberOfRegisters()) {
98 return ArmCoreLocation(calling_convention.GetRegisterAt(index));
99 } else {
100 return Location::StackSlot(calling_convention.GetStackOffsetOf(index, kArmWordSize));
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100101 }
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100102 }
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100103
104 case Primitive::kPrimLong: {
105 uint32_t index = gp_index_;
106 gp_index_ += 2;
107 if (index + 1 < calling_convention.GetNumberOfRegisters()) {
108 return Location::RegisterLocation(ArmManagedRegister::FromRegisterPair(
109 calling_convention.GetRegisterPairAt(index)));
110 } else if (index + 1 == calling_convention.GetNumberOfRegisters()) {
111 return Location::QuickParameter(index);
112 } else {
113 return Location::DoubleStackSlot(calling_convention.GetStackOffsetOf(index, kArmWordSize));
114 }
115 }
116
117 case Primitive::kPrimDouble:
118 case Primitive::kPrimFloat:
119 LOG(FATAL) << "Unimplemented parameter type " << type;
120 break;
121
122 case Primitive::kPrimVoid:
123 LOG(FATAL) << "Unexpected parameter type " << type;
124 break;
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100125 }
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100126 return Location();
127}
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100128
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100129void CodeGeneratorARM::Move32(Location destination, Location source) {
130 if (source.Equals(destination)) {
131 return;
132 }
133 if (destination.IsRegister()) {
134 if (source.IsRegister()) {
135 __ Mov(destination.AsArm().AsCoreRegister(), source.AsArm().AsCoreRegister());
136 } else {
137 __ ldr(destination.AsArm().AsCoreRegister(), Address(SP, source.GetStackIndex()));
138 }
139 } else {
140 DCHECK(destination.IsStackSlot());
141 if (source.IsRegister()) {
142 __ str(source.AsArm().AsCoreRegister(), Address(SP, destination.GetStackIndex()));
143 } else {
144 __ ldr(R0, Address(SP, source.GetStackIndex()));
145 __ str(R0, Address(SP, destination.GetStackIndex()));
146 }
147 }
148}
149
150void CodeGeneratorARM::Move64(Location destination, Location source) {
151 if (source.Equals(destination)) {
152 return;
153 }
154 if (destination.IsRegister()) {
155 if (source.IsRegister()) {
156 __ Mov(destination.AsArm().AsRegisterPairLow(), source.AsArm().AsRegisterPairLow());
157 __ Mov(destination.AsArm().AsRegisterPairHigh(), source.AsArm().AsRegisterPairHigh());
158 } else if (source.IsQuickParameter()) {
159 uint32_t argument_index = source.GetQuickParameterIndex();
160 InvokeDexCallingConvention calling_convention;
161 __ Mov(destination.AsArm().AsRegisterPairLow(),
162 calling_convention.GetRegisterAt(argument_index));
163 __ ldr(destination.AsArm().AsRegisterPairHigh(),
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100164 Address(SP, calling_convention.GetStackOffsetOf(argument_index + 1, kArmWordSize) + GetFrameSize()));
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100165 } else {
166 DCHECK(source.IsDoubleStackSlot());
167 if (destination.AsArm().AsRegisterPair() == R1_R2) {
168 __ ldr(R1, Address(SP, source.GetStackIndex()));
169 __ ldr(R2, Address(SP, source.GetHighStackIndex(kArmWordSize)));
170 } else {
171 __ LoadFromOffset(kLoadWordPair, destination.AsArm().AsRegisterPairLow(),
172 SP, source.GetStackIndex());
173 }
174 }
175 } else if (destination.IsQuickParameter()) {
176 InvokeDexCallingConvention calling_convention;
177 uint32_t argument_index = destination.GetQuickParameterIndex();
178 if (source.IsRegister()) {
179 __ Mov(calling_convention.GetRegisterAt(argument_index), source.AsArm().AsRegisterPairLow());
180 __ str(source.AsArm().AsRegisterPairHigh(),
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100181 Address(SP, calling_convention.GetStackOffsetOf(argument_index + 1, kArmWordSize)));
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100182 } else {
183 DCHECK(source.IsDoubleStackSlot());
184 __ ldr(calling_convention.GetRegisterAt(argument_index), Address(SP, source.GetStackIndex()));
185 __ ldr(R0, Address(SP, source.GetHighStackIndex(kArmWordSize)));
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100186 __ str(R0, Address(SP, calling_convention.GetStackOffsetOf(argument_index + 1, kArmWordSize)));
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100187 }
188 } else {
189 DCHECK(destination.IsDoubleStackSlot());
190 if (source.IsRegister()) {
191 if (source.AsArm().AsRegisterPair() == R1_R2) {
192 __ str(R1, Address(SP, destination.GetStackIndex()));
193 __ str(R2, Address(SP, destination.GetHighStackIndex(kArmWordSize)));
194 } else {
195 __ StoreToOffset(kStoreWordPair, source.AsArm().AsRegisterPairLow(),
196 SP, destination.GetStackIndex());
197 }
198 } else if (source.IsQuickParameter()) {
199 InvokeDexCallingConvention calling_convention;
200 uint32_t argument_index = source.GetQuickParameterIndex();
201 __ str(calling_convention.GetRegisterAt(argument_index),
202 Address(SP, destination.GetStackIndex()));
203 __ ldr(R0,
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100204 Address(SP, calling_convention.GetStackOffsetOf(argument_index + 1, kArmWordSize) + GetFrameSize()));
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100205 __ str(R0, Address(SP, destination.GetHighStackIndex(kArmWordSize)));
206 } else {
207 DCHECK(source.IsDoubleStackSlot());
208 __ ldr(R0, Address(SP, source.GetStackIndex()));
209 __ str(R0, Address(SP, destination.GetStackIndex()));
210 __ ldr(R0, Address(SP, source.GetHighStackIndex(kArmWordSize)));
211 __ str(R0, Address(SP, destination.GetHighStackIndex(kArmWordSize)));
212 }
213 }
214}
215
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100216void CodeGeneratorARM::Move(HInstruction* instruction, Location location, HInstruction* move_for) {
217 if (instruction->AsIntConstant() != nullptr) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100218 int32_t value = instruction->AsIntConstant()->GetValue();
219 if (location.IsRegister()) {
220 __ LoadImmediate(location.AsArm().AsCoreRegister(), value);
221 } else {
222 __ LoadImmediate(R0, value);
223 __ str(R0, Address(SP, location.GetStackIndex()));
224 }
225 } else if (instruction->AsLongConstant() != nullptr) {
226 int64_t value = instruction->AsLongConstant()->GetValue();
227 if (location.IsRegister()) {
228 __ LoadImmediate(location.AsArm().AsRegisterPairLow(), Low32Bits(value));
229 __ LoadImmediate(location.AsArm().AsRegisterPairHigh(), High32Bits(value));
230 } else {
231 __ LoadImmediate(R0, Low32Bits(value));
232 __ str(R0, Address(SP, location.GetStackIndex()));
233 __ LoadImmediate(R0, High32Bits(value));
234 __ str(R0, Address(SP, location.GetHighStackIndex(kArmWordSize)));
235 }
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100236 } else if (instruction->AsLoadLocal() != nullptr) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100237 uint32_t stack_slot = GetStackSlot(instruction->AsLoadLocal()->GetLocal());
238 switch (instruction->GetType()) {
239 case Primitive::kPrimBoolean:
240 case Primitive::kPrimByte:
241 case Primitive::kPrimChar:
242 case Primitive::kPrimShort:
243 case Primitive::kPrimInt:
244 case Primitive::kPrimNot:
245 Move32(location, Location::StackSlot(stack_slot));
246 break;
247
248 case Primitive::kPrimLong:
249 Move64(location, Location::DoubleStackSlot(stack_slot));
250 break;
251
252 default:
253 LOG(FATAL) << "Unimplemented type " << instruction->GetType();
254 }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000255 } else {
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100256 // This can currently only happen when the instruction that requests the move
257 // is the next to be compiled.
258 DCHECK_EQ(instruction->GetNext(), move_for);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100259 switch (instruction->GetType()) {
260 case Primitive::kPrimBoolean:
261 case Primitive::kPrimByte:
262 case Primitive::kPrimChar:
263 case Primitive::kPrimShort:
264 case Primitive::kPrimNot:
265 case Primitive::kPrimInt:
266 Move32(location, instruction->GetLocations()->Out());
267 break;
268
269 case Primitive::kPrimLong:
270 Move64(location, instruction->GetLocations()->Out());
271 break;
272
273 default:
274 LOG(FATAL) << "Unimplemented type " << instruction->GetType();
275 }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000276 }
277}
278
279void LocationsBuilderARM::VisitGoto(HGoto* got) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000280 got->SetLocations(nullptr);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000281}
282
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000283void InstructionCodeGeneratorARM::VisitGoto(HGoto* got) {
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000284 HBasicBlock* successor = got->GetSuccessor();
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000285 if (GetGraph()->GetExitBlock() == successor) {
286 codegen_->GenerateFrameExit();
287 } else if (!codegen_->GoesToNextBlock(got->GetBlock(), successor)) {
288 __ b(codegen_->GetLabelOf(successor));
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000289 }
290}
291
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000292void LocationsBuilderARM::VisitExit(HExit* exit) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000293 exit->SetLocations(nullptr);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000294}
295
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000296void InstructionCodeGeneratorARM::VisitExit(HExit* exit) {
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000297 if (kIsDebugBuild) {
298 __ Comment("Unreachable");
299 __ bkpt(0);
300 }
301}
302
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000303void LocationsBuilderARM::VisitIf(HIf* if_instr) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000304 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(if_instr);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100305 locations->SetInAt(0, ArmCoreLocation(R0));
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000306 if_instr->SetLocations(locations);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000307}
308
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000309void InstructionCodeGeneratorARM::VisitIf(HIf* if_instr) {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000310 // TODO: Generate the input as a condition, instead of materializing in a register.
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100311 __ cmp(if_instr->GetLocations()->InAt(0).AsArm().AsCoreRegister(), ShifterOperand(0));
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000312 __ b(codegen_->GetLabelOf(if_instr->IfFalseSuccessor()), EQ);
313 if (!codegen_->GoesToNextBlock(if_instr->GetBlock(), if_instr->IfTrueSuccessor())) {
314 __ b(codegen_->GetLabelOf(if_instr->IfTrueSuccessor()));
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000315 }
316}
317
318void LocationsBuilderARM::VisitEqual(HEqual* equal) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000319 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(equal);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100320 locations->SetInAt(0, ArmCoreLocation(R0));
321 locations->SetInAt(1, ArmCoreLocation(R1));
322 locations->SetOut(ArmCoreLocation(R0));
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000323 equal->SetLocations(locations);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000324}
325
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000326void InstructionCodeGeneratorARM::VisitEqual(HEqual* equal) {
327 LocationSummary* locations = equal->GetLocations();
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100328 __ teq(locations->InAt(0).AsArm().AsCoreRegister(),
329 ShifterOperand(locations->InAt(1).AsArm().AsCoreRegister()));
330 __ mov(locations->Out().AsArm().AsCoreRegister(), ShifterOperand(1), EQ);
331 __ mov(locations->Out().AsArm().AsCoreRegister(), ShifterOperand(0), NE);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000332}
333
334void LocationsBuilderARM::VisitLocal(HLocal* local) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000335 local->SetLocations(nullptr);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000336}
337
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000338void InstructionCodeGeneratorARM::VisitLocal(HLocal* local) {
339 DCHECK_EQ(local->GetBlock(), GetGraph()->GetEntryBlock());
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000340}
341
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000342void LocationsBuilderARM::VisitLoadLocal(HLoadLocal* load) {
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100343 load->SetLocations(nullptr);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000344}
345
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000346void InstructionCodeGeneratorARM::VisitLoadLocal(HLoadLocal* load) {
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100347 // Nothing to do, this is driven by the code generator.
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000348}
349
350void LocationsBuilderARM::VisitStoreLocal(HStoreLocal* store) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000351 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(store);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100352 switch (store->InputAt(1)->GetType()) {
353 case Primitive::kPrimBoolean:
354 case Primitive::kPrimByte:
355 case Primitive::kPrimChar:
356 case Primitive::kPrimShort:
357 case Primitive::kPrimInt:
358 case Primitive::kPrimNot:
359 locations->SetInAt(1, Location::StackSlot(codegen_->GetStackSlot(store->GetLocal())));
360 break;
361
362 case Primitive::kPrimLong:
363 locations->SetInAt(1, Location::DoubleStackSlot(codegen_->GetStackSlot(store->GetLocal())));
364 break;
365
366 default:
367 LOG(FATAL) << "Unimplemented local type " << store->InputAt(1)->GetType();
368 }
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000369 store->SetLocations(locations);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000370}
371
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000372void InstructionCodeGeneratorARM::VisitStoreLocal(HStoreLocal* store) {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000373}
374
375void LocationsBuilderARM::VisitIntConstant(HIntConstant* constant) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000376 constant->SetLocations(nullptr);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000377}
378
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000379void InstructionCodeGeneratorARM::VisitIntConstant(HIntConstant* constant) {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000380 // Will be generated at use site.
381}
382
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100383void LocationsBuilderARM::VisitLongConstant(HLongConstant* constant) {
384 constant->SetLocations(nullptr);
385}
386
387void InstructionCodeGeneratorARM::VisitLongConstant(HLongConstant* constant) {
388 // Will be generated at use site.
389}
390
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000391void LocationsBuilderARM::VisitReturnVoid(HReturnVoid* ret) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000392 ret->SetLocations(nullptr);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000393}
394
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000395void InstructionCodeGeneratorARM::VisitReturnVoid(HReturnVoid* ret) {
396 codegen_->GenerateFrameExit();
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000397}
398
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000399void LocationsBuilderARM::VisitReturn(HReturn* ret) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000400 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(ret);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100401 switch (ret->InputAt(0)->GetType()) {
402 case Primitive::kPrimBoolean:
403 case Primitive::kPrimByte:
404 case Primitive::kPrimChar:
405 case Primitive::kPrimShort:
406 case Primitive::kPrimInt:
407 case Primitive::kPrimNot:
408 locations->SetInAt(0, ArmCoreLocation(R0));
409 break;
410
411 case Primitive::kPrimLong:
412 locations->SetInAt(0, Location::RegisterLocation(ArmManagedRegister::FromRegisterPair(R0_R1)));
413 break;
414
415 default:
416 LOG(FATAL) << "Unimplemented return type " << ret->InputAt(0)->GetType();
417 }
418
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000419 ret->SetLocations(locations);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000420}
421
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000422void InstructionCodeGeneratorARM::VisitReturn(HReturn* ret) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100423 if (kIsDebugBuild) {
424 switch (ret->InputAt(0)->GetType()) {
425 case Primitive::kPrimBoolean:
426 case Primitive::kPrimByte:
427 case Primitive::kPrimChar:
428 case Primitive::kPrimShort:
429 case Primitive::kPrimInt:
430 case Primitive::kPrimNot:
431 DCHECK_EQ(ret->GetLocations()->InAt(0).AsArm().AsCoreRegister(), R0);
432 break;
433
434 case Primitive::kPrimLong:
435 DCHECK_EQ(ret->GetLocations()->InAt(0).AsArm().AsRegisterPair(), R0_R1);
436 break;
437
438 default:
439 LOG(FATAL) << "Unimplemented return type " << ret->InputAt(0)->GetType();
440 }
441 }
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000442 codegen_->GenerateFrameExit();
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000443}
444
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000445void LocationsBuilderARM::VisitInvokeStatic(HInvokeStatic* invoke) {
446 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(invoke);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100447 locations->AddTemp(ArmCoreLocation(R0));
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100448
449 InvokeDexCallingConventionVisitor calling_convention_visitor;
450 for (int i = 0; i < invoke->InputCount(); i++) {
451 HInstruction* input = invoke->InputAt(i);
452 locations->SetInAt(i, calling_convention_visitor.GetNextLocation(input->GetType()));
453 }
454
455 switch (invoke->GetType()) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100456 case Primitive::kPrimBoolean:
457 case Primitive::kPrimByte:
458 case Primitive::kPrimChar:
459 case Primitive::kPrimShort:
460 case Primitive::kPrimInt:
461 case Primitive::kPrimNot:
462 locations->SetOut(ArmCoreLocation(R0));
463 break;
464
465 case Primitive::kPrimLong:
466 locations->SetOut(Location::RegisterLocation(ArmManagedRegister::FromRegisterPair(R0_R1)));
467 break;
468
469 case Primitive::kPrimVoid:
470 break;
471
472 case Primitive::kPrimDouble:
473 case Primitive::kPrimFloat:
474 LOG(FATAL) << "Unimplemented return type " << invoke->GetType();
475 break;
476 }
477
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000478 invoke->SetLocations(locations);
479}
480
481void InstructionCodeGeneratorARM::LoadCurrentMethod(Register reg) {
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100482 __ ldr(reg, Address(SP, kCurrentMethodStackOffset));
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000483}
484
485void InstructionCodeGeneratorARM::VisitInvokeStatic(HInvokeStatic* invoke) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100486 Register temp = invoke->GetLocations()->GetTemp(0).AsArm().AsCoreRegister();
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000487 size_t index_in_cache = mirror::Array::DataOffset(sizeof(mirror::Object*)).Int32Value() +
Nicolas Geoffray707c8092014-04-04 10:50:14 +0100488 invoke->GetIndexInDexCache() * kArmWordSize;
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000489
490 // TODO: Implement all kinds of calls:
491 // 1) boot -> boot
492 // 2) app -> boot
493 // 3) app -> app
494 //
495 // Currently we implement the app -> app logic, which looks up in the resolve cache.
496
497 // temp = method;
498 LoadCurrentMethod(temp);
499 // temp = temp->dex_cache_resolved_methods_;
500 __ ldr(temp, Address(temp, mirror::ArtMethod::DexCacheResolvedMethodsOffset().Int32Value()));
501 // temp = temp[index_in_cache]
502 __ ldr(temp, Address(temp, index_in_cache));
503 // LR = temp[offset_of_quick_compiled_code]
504 __ ldr(LR, Address(temp,
505 mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset().Int32Value()));
506 // LR()
507 __ blx(LR);
508
509 codegen_->RecordPcInfo(invoke->GetDexPc());
510}
511
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000512void LocationsBuilderARM::VisitAdd(HAdd* add) {
513 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(add);
514 switch (add->GetResultType()) {
515 case Primitive::kPrimInt: {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100516 locations->SetInAt(0, ArmCoreLocation(R0));
517 locations->SetInAt(1, ArmCoreLocation(R1));
518 locations->SetOut(ArmCoreLocation(R0));
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000519 break;
520 }
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100521
522 case Primitive::kPrimLong: {
523 locations->SetInAt(
524 0, Location::RegisterLocation(ArmManagedRegister::FromRegisterPair(R0_R1)));
525 locations->SetInAt(
526 1, Location::RegisterLocation(ArmManagedRegister::FromRegisterPair(R2_R3)));
527 locations->SetOut(Location::RegisterLocation(ArmManagedRegister::FromRegisterPair(R0_R1)));
528 break;
529 }
530
531 case Primitive::kPrimBoolean:
532 case Primitive::kPrimByte:
533 case Primitive::kPrimChar:
534 case Primitive::kPrimShort:
535 LOG(FATAL) << "Unexpected add type " << add->GetResultType();
536 break;
537
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000538 default:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100539 LOG(FATAL) << "Unimplemented add type " << add->GetResultType();
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000540 }
541 add->SetLocations(locations);
542}
543
544void InstructionCodeGeneratorARM::VisitAdd(HAdd* add) {
545 LocationSummary* locations = add->GetLocations();
546 switch (add->GetResultType()) {
547 case Primitive::kPrimInt:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100548 __ add(locations->Out().AsArm().AsCoreRegister(),
549 locations->InAt(0).AsArm().AsCoreRegister(),
550 ShifterOperand(locations->InAt(1).AsArm().AsCoreRegister()));
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000551 break;
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100552
553 case Primitive::kPrimLong:
554 __ adds(locations->Out().AsArm().AsRegisterPairLow(),
555 locations->InAt(0).AsArm().AsRegisterPairLow(),
556 ShifterOperand(locations->InAt(1).AsArm().AsRegisterPairLow()));
557 __ adc(locations->Out().AsArm().AsRegisterPairHigh(),
558 locations->InAt(0).AsArm().AsRegisterPairHigh(),
559 ShifterOperand(locations->InAt(1).AsArm().AsRegisterPairHigh()));
560 break;
561
562 case Primitive::kPrimBoolean:
563 case Primitive::kPrimByte:
564 case Primitive::kPrimChar:
565 case Primitive::kPrimShort:
566 LOG(FATAL) << "Unexpected add type " << add->GetResultType();
567 break;
568
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000569 default:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100570 LOG(FATAL) << "Unimplemented add type " << add->GetResultType();
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000571 }
572}
573
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100574void LocationsBuilderARM::VisitSub(HSub* sub) {
575 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(sub);
576 switch (sub->GetResultType()) {
577 case Primitive::kPrimInt: {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100578 locations->SetInAt(0, ArmCoreLocation(R0));
579 locations->SetInAt(1, ArmCoreLocation(R1));
580 locations->SetOut(ArmCoreLocation(R0));
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100581 break;
582 }
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100583
584 case Primitive::kPrimLong: {
585 locations->SetInAt(
586 0, Location::RegisterLocation(ArmManagedRegister::FromRegisterPair(R0_R1)));
587 locations->SetInAt(
588 1, Location::RegisterLocation(ArmManagedRegister::FromRegisterPair(R2_R3)));
589 locations->SetOut(Location::RegisterLocation(ArmManagedRegister::FromRegisterPair(R0_R1)));
590 break;
591 }
592
593 case Primitive::kPrimBoolean:
594 case Primitive::kPrimByte:
595 case Primitive::kPrimChar:
596 case Primitive::kPrimShort:
597 LOG(FATAL) << "Unexpected sub type " << sub->GetResultType();
598 break;
599
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100600 default:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100601 LOG(FATAL) << "Unimplemented sub type " << sub->GetResultType();
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100602 }
603 sub->SetLocations(locations);
604}
605
606void InstructionCodeGeneratorARM::VisitSub(HSub* sub) {
607 LocationSummary* locations = sub->GetLocations();
608 switch (sub->GetResultType()) {
609 case Primitive::kPrimInt:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100610 __ sub(locations->Out().AsArm().AsCoreRegister(),
611 locations->InAt(0).AsArm().AsCoreRegister(),
612 ShifterOperand(locations->InAt(1).AsArm().AsCoreRegister()));
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100613 break;
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100614
615 case Primitive::kPrimLong:
616 __ subs(locations->Out().AsArm().AsRegisterPairLow(),
617 locations->InAt(0).AsArm().AsRegisterPairLow(),
618 ShifterOperand(locations->InAt(1).AsArm().AsRegisterPairLow()));
619 __ sbc(locations->Out().AsArm().AsRegisterPairHigh(),
620 locations->InAt(0).AsArm().AsRegisterPairHigh(),
621 ShifterOperand(locations->InAt(1).AsArm().AsRegisterPairHigh()));
622 break;
623
624 case Primitive::kPrimBoolean:
625 case Primitive::kPrimByte:
626 case Primitive::kPrimChar:
627 case Primitive::kPrimShort:
628 LOG(FATAL) << "Unexpected sub type " << sub->GetResultType();
629 break;
630
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100631 default:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100632 LOG(FATAL) << "Unimplemented sub type " << sub->GetResultType();
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100633 }
634}
635
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100636static constexpr Register kRuntimeParameterCoreRegisters[] = { R0, R1 };
637static constexpr size_t kRuntimeParameterCoreRegistersLength =
638 arraysize(kRuntimeParameterCoreRegisters);
639
640class InvokeRuntimeCallingConvention : public CallingConvention<Register> {
641 public:
642 InvokeRuntimeCallingConvention()
643 : CallingConvention(kRuntimeParameterCoreRegisters,
644 kRuntimeParameterCoreRegistersLength) {}
645
646 private:
647 DISALLOW_COPY_AND_ASSIGN(InvokeRuntimeCallingConvention);
648};
649
650void LocationsBuilderARM::VisitNewInstance(HNewInstance* instruction) {
651 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100652 locations->SetOut(ArmCoreLocation(R0));
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100653 instruction->SetLocations(locations);
654}
655
656void InstructionCodeGeneratorARM::VisitNewInstance(HNewInstance* instruction) {
657 InvokeRuntimeCallingConvention calling_convention;
658 LoadCurrentMethod(calling_convention.GetRegisterAt(1));
659 __ LoadImmediate(calling_convention.GetRegisterAt(0), instruction->GetTypeIndex());
660
Nicolas Geoffray707c8092014-04-04 10:50:14 +0100661 int32_t offset = QUICK_ENTRYPOINT_OFFSET(kArmWordSize, pAllocObjectWithAccessCheck).Int32Value();
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100662 __ ldr(LR, Address(TR, offset));
663 __ blx(LR);
664
665 codegen_->RecordPcInfo(instruction->GetDexPc());
666}
667
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100668void LocationsBuilderARM::VisitParameterValue(HParameterValue* instruction) {
669 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100670 Location location = parameter_visitor_.GetNextLocation(instruction->GetType());
671 if (location.IsStackSlot()) {
672 location = Location::StackSlot(location.GetStackIndex() + codegen_->GetFrameSize());
673 } else if (location.IsDoubleStackSlot()) {
674 location = Location::DoubleStackSlot(location.GetStackIndex() + codegen_->GetFrameSize());
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100675 }
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100676 locations->SetOut(location);
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100677 instruction->SetLocations(locations);
678}
679
680void InstructionCodeGeneratorARM::VisitParameterValue(HParameterValue* instruction) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100681 // Nothing to do, the parameter is already at its location.
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100682}
683
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100684void LocationsBuilderARM::VisitNot(HNot* instruction) {
685 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100686 locations->SetInAt(0, ArmCoreLocation(R0));
687 locations->SetOut(ArmCoreLocation(R0));
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100688 instruction->SetLocations(locations);
689}
690
691void InstructionCodeGeneratorARM::VisitNot(HNot* instruction) {
692 LocationSummary* locations = instruction->GetLocations();
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100693 __ eor(locations->Out().AsArm().AsCoreRegister(),
694 locations->InAt(0).AsArm().AsCoreRegister(), ShifterOperand(1));
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100695}
696
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000697} // namespace arm
698} // namespace art