blob: d87c14b4dbaf576d0c79bd9283d18660814fcebf [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"
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000018
Ian Rogersb0fa5dc2014-04-28 16:47:08 -070019#include "entrypoints/quick/quick_entrypoints.h"
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +000020#include "mirror/array.h"
21#include "mirror/art_method.h"
Ian Rogersb0fa5dc2014-04-28 16:47:08 -070022#include "thread.h"
Nicolas Geoffray9cf35522014-06-09 18:40:10 +010023#include "utils/assembler.h"
24#include "utils/arm/assembler_arm.h"
25#include "utils/arm/managed_register_arm.h"
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +000026
Nicolas Geoffray787c3072014-03-17 10:20:19 +000027#define __ reinterpret_cast<ArmAssembler*>(GetAssembler())->
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000028
29namespace art {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +010030
31arm::ArmManagedRegister Location::AsArm() const {
32 return reg().AsArm();
33}
34
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000035namespace arm {
36
Dave Allison20dfc792014-06-16 20:44:29 -070037
38inline Condition ARMCondition(IfCondition cond) {
39 switch (cond) {
40 case kCondEQ: return EQ;
41 case kCondNE: return NE;
42 case kCondLT: return LT;
43 case kCondLE: return LE;
44 case kCondGT: return GT;
45 case kCondGE: return GE;
46 default:
47 LOG(FATAL) << "Unknown if condition";
48 }
49 return EQ; // Unreachable.
50}
51
52inline Condition ARMOppositeCondition(IfCondition cond) {
53 switch (cond) {
54 case kCondEQ: return NE;
55 case kCondNE: return EQ;
56 case kCondLT: return GE;
57 case kCondLE: return GT;
58 case kCondGT: return LE;
59 case kCondGE: return LT;
60 default:
61 LOG(FATAL) << "Unknown if condition";
62 }
63 return EQ; // Unreachable.
64}
65
Nicolas Geoffray4a34a422014-04-03 10:38:37 +010066static constexpr int kNumberOfPushedRegistersAtEntry = 1;
67static constexpr int kCurrentMethodStackOffset = 0;
68
Nicolas Geoffraya7062e02014-05-22 12:50:17 +010069void CodeGeneratorARM::DumpCoreRegister(std::ostream& stream, int reg) const {
70 stream << ArmManagedRegister::FromCoreRegister(Register(reg));
71}
72
73void CodeGeneratorARM::DumpFloatingPointRegister(std::ostream& stream, int reg) const {
74 stream << ArmManagedRegister::FromDRegister(DRegister(reg));
75}
76
Nicolas Geoffraya7aca372014-04-28 17:47:12 +010077CodeGeneratorARM::CodeGeneratorARM(HGraph* graph)
78 : CodeGenerator(graph, kNumberOfRegIds),
79 location_builder_(graph, this),
Nicolas Geoffraye27f31a2014-06-12 17:53:14 +010080 instruction_visitor_(graph, this),
81 move_resolver_(graph->GetArena(), this) {}
Nicolas Geoffraya7aca372014-04-28 17:47:12 +010082
83static bool* GetBlockedRegisterPairs(bool* blocked_registers) {
84 return blocked_registers + kNumberOfAllocIds;
85}
86
87ManagedRegister CodeGeneratorARM::AllocateFreeRegister(Primitive::Type type,
88 bool* blocked_registers) const {
89 switch (type) {
90 case Primitive::kPrimLong: {
91 size_t reg = AllocateFreeRegisterInternal(
92 GetBlockedRegisterPairs(blocked_registers), kNumberOfRegisterPairs);
93 ArmManagedRegister pair =
94 ArmManagedRegister::FromRegisterPair(static_cast<RegisterPair>(reg));
95 blocked_registers[pair.AsRegisterPairLow()] = true;
96 blocked_registers[pair.AsRegisterPairHigh()] = true;
97 return pair;
98 }
99
100 case Primitive::kPrimByte:
101 case Primitive::kPrimBoolean:
102 case Primitive::kPrimChar:
103 case Primitive::kPrimShort:
104 case Primitive::kPrimInt:
105 case Primitive::kPrimNot: {
106 size_t reg = AllocateFreeRegisterInternal(blocked_registers, kNumberOfCoreRegisters);
107 return ArmManagedRegister::FromCoreRegister(static_cast<Register>(reg));
108 }
109
110 case Primitive::kPrimFloat:
111 case Primitive::kPrimDouble:
112 LOG(FATAL) << "Unimplemented register type " << type;
113
114 case Primitive::kPrimVoid:
115 LOG(FATAL) << "Unreachable type " << type;
116 }
117
118 return ManagedRegister::NoRegister();
119}
120
121void CodeGeneratorARM::SetupBlockedRegisters(bool* blocked_registers) const {
122 bool* blocked_register_pairs = GetBlockedRegisterPairs(blocked_registers);
123
124 // Don't allocate the dalvik style register pair passing.
125 blocked_register_pairs[R1_R2] = true;
126
127 // Stack register, LR and PC are always reserved.
128 blocked_registers[SP] = true;
129 blocked_registers[LR] = true;
130 blocked_registers[PC] = true;
131
132 // Reserve R4 for suspend check.
133 blocked_registers[R4] = true;
134 blocked_register_pairs[R4_R5] = true;
135
136 // Reserve thread register.
137 blocked_registers[TR] = true;
138
Nicolas Geoffraye27f31a2014-06-12 17:53:14 +0100139 // Reserve temp register.
140 blocked_registers[IP] = true;
141
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100142 // TODO: We currently don't use Quick's callee saved registers.
143 blocked_registers[R5] = true;
144 blocked_registers[R6] = true;
145 blocked_registers[R7] = true;
146 blocked_registers[R8] = true;
147 blocked_registers[R10] = true;
148 blocked_registers[R11] = true;
149 blocked_register_pairs[R6_R7] = true;
150}
151
152size_t CodeGeneratorARM::GetNumberOfRegisters() const {
153 return kNumberOfRegIds;
154}
155
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100156static Location ArmCoreLocation(Register reg) {
157 return Location::RegisterLocation(ArmManagedRegister::FromCoreRegister(reg));
158}
159
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100160InstructionCodeGeneratorARM::InstructionCodeGeneratorARM(HGraph* graph, CodeGeneratorARM* codegen)
161 : HGraphVisitor(graph),
162 assembler_(codegen->GetAssembler()),
163 codegen_(codegen) {}
164
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100165void CodeGeneratorARM::ComputeFrameSize(size_t number_of_spill_slots) {
166 SetFrameSize(RoundUp(
167 number_of_spill_slots * kVRegSize
168 + kVRegSize // Art method
169 + kNumberOfPushedRegistersAtEntry * kArmWordSize,
170 kStackAlignment));
171}
172
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000173void CodeGeneratorARM::GenerateFrameEntry() {
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000174 core_spill_mask_ |= (1 << LR);
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100175 __ PushList((1 << LR));
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000176
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100177 // The return PC has already been pushed on the stack.
Nicolas Geoffray707c8092014-04-04 10:50:14 +0100178 __ AddConstant(SP, -(GetFrameSize() - kNumberOfPushedRegistersAtEntry * kArmWordSize));
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000179 __ str(R0, Address(SP, 0));
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000180}
181
182void CodeGeneratorARM::GenerateFrameExit() {
Nicolas Geoffray707c8092014-04-04 10:50:14 +0100183 __ AddConstant(SP, GetFrameSize() - kNumberOfPushedRegistersAtEntry * kArmWordSize);
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100184 __ PopList((1 << PC));
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000185}
186
187void CodeGeneratorARM::Bind(Label* label) {
188 __ Bind(label);
189}
190
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100191int32_t CodeGeneratorARM::GetStackSlot(HLocal* local) const {
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100192 uint16_t reg_number = local->GetRegNumber();
193 uint16_t number_of_vregs = GetGraph()->GetNumberOfVRegs();
194 uint16_t number_of_in_vregs = GetGraph()->GetNumberOfInVRegs();
195 if (reg_number >= number_of_vregs - number_of_in_vregs) {
196 // Local is a parameter of the method. It is stored in the caller's frame.
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100197 return GetFrameSize() + kVRegSize // ART method
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100198 + (reg_number - number_of_vregs + number_of_in_vregs) * kVRegSize;
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100199 } else {
200 // Local is a temporary in this method. It is stored in this method's frame.
201 return GetFrameSize() - (kNumberOfPushedRegistersAtEntry * kArmWordSize)
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100202 - kVRegSize // filler.
203 - (number_of_vregs * kVRegSize)
204 + (reg_number * kVRegSize);
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100205 }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000206}
207
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100208Location CodeGeneratorARM::GetStackLocation(HLoadLocal* load) const {
209 switch (load->GetType()) {
210 case Primitive::kPrimLong:
211 return Location::DoubleStackSlot(GetStackSlot(load->GetLocal()));
212 break;
213
214 case Primitive::kPrimInt:
215 case Primitive::kPrimNot:
216 return Location::StackSlot(GetStackSlot(load->GetLocal()));
217
218 case Primitive::kPrimFloat:
219 case Primitive::kPrimDouble:
220 LOG(FATAL) << "Unimplemented type " << load->GetType();
221
222 case Primitive::kPrimBoolean:
223 case Primitive::kPrimByte:
224 case Primitive::kPrimChar:
225 case Primitive::kPrimShort:
226 case Primitive::kPrimVoid:
227 LOG(FATAL) << "Unexpected type " << load->GetType();
228 }
229
230 LOG(FATAL) << "Unreachable";
231 return Location();
232}
233
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100234Location InvokeDexCallingConventionVisitor::GetNextLocation(Primitive::Type type) {
235 switch (type) {
236 case Primitive::kPrimBoolean:
237 case Primitive::kPrimByte:
238 case Primitive::kPrimChar:
239 case Primitive::kPrimShort:
240 case Primitive::kPrimInt:
241 case Primitive::kPrimNot: {
242 uint32_t index = gp_index_++;
243 if (index < calling_convention.GetNumberOfRegisters()) {
244 return ArmCoreLocation(calling_convention.GetRegisterAt(index));
245 } else {
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100246 return Location::StackSlot(calling_convention.GetStackOffsetOf(index));
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100247 }
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100248 }
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100249
250 case Primitive::kPrimLong: {
251 uint32_t index = gp_index_;
252 gp_index_ += 2;
253 if (index + 1 < calling_convention.GetNumberOfRegisters()) {
254 return Location::RegisterLocation(ArmManagedRegister::FromRegisterPair(
255 calling_convention.GetRegisterPairAt(index)));
256 } else if (index + 1 == calling_convention.GetNumberOfRegisters()) {
257 return Location::QuickParameter(index);
258 } else {
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100259 return Location::DoubleStackSlot(calling_convention.GetStackOffsetOf(index));
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100260 }
261 }
262
263 case Primitive::kPrimDouble:
264 case Primitive::kPrimFloat:
265 LOG(FATAL) << "Unimplemented parameter type " << type;
266 break;
267
268 case Primitive::kPrimVoid:
269 LOG(FATAL) << "Unexpected parameter type " << type;
270 break;
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100271 }
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100272 return Location();
273}
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100274
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100275void CodeGeneratorARM::Move32(Location destination, Location source) {
276 if (source.Equals(destination)) {
277 return;
278 }
279 if (destination.IsRegister()) {
280 if (source.IsRegister()) {
281 __ Mov(destination.AsArm().AsCoreRegister(), source.AsArm().AsCoreRegister());
282 } else {
283 __ ldr(destination.AsArm().AsCoreRegister(), Address(SP, source.GetStackIndex()));
284 }
285 } else {
286 DCHECK(destination.IsStackSlot());
287 if (source.IsRegister()) {
288 __ str(source.AsArm().AsCoreRegister(), Address(SP, destination.GetStackIndex()));
289 } else {
Nicolas Geoffraye27f31a2014-06-12 17:53:14 +0100290 __ ldr(IP, Address(SP, source.GetStackIndex()));
291 __ str(IP, Address(SP, destination.GetStackIndex()));
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100292 }
293 }
294}
295
296void CodeGeneratorARM::Move64(Location destination, Location source) {
297 if (source.Equals(destination)) {
298 return;
299 }
300 if (destination.IsRegister()) {
301 if (source.IsRegister()) {
302 __ Mov(destination.AsArm().AsRegisterPairLow(), source.AsArm().AsRegisterPairLow());
303 __ Mov(destination.AsArm().AsRegisterPairHigh(), source.AsArm().AsRegisterPairHigh());
304 } else if (source.IsQuickParameter()) {
305 uint32_t argument_index = source.GetQuickParameterIndex();
306 InvokeDexCallingConvention calling_convention;
307 __ Mov(destination.AsArm().AsRegisterPairLow(),
308 calling_convention.GetRegisterAt(argument_index));
309 __ ldr(destination.AsArm().AsRegisterPairHigh(),
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100310 Address(SP, calling_convention.GetStackOffsetOf(argument_index + 1) + GetFrameSize()));
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100311 } else {
312 DCHECK(source.IsDoubleStackSlot());
313 if (destination.AsArm().AsRegisterPair() == R1_R2) {
314 __ ldr(R1, Address(SP, source.GetStackIndex()));
315 __ ldr(R2, Address(SP, source.GetHighStackIndex(kArmWordSize)));
316 } else {
317 __ LoadFromOffset(kLoadWordPair, destination.AsArm().AsRegisterPairLow(),
318 SP, source.GetStackIndex());
319 }
320 }
321 } else if (destination.IsQuickParameter()) {
322 InvokeDexCallingConvention calling_convention;
323 uint32_t argument_index = destination.GetQuickParameterIndex();
324 if (source.IsRegister()) {
325 __ Mov(calling_convention.GetRegisterAt(argument_index), source.AsArm().AsRegisterPairLow());
326 __ str(source.AsArm().AsRegisterPairHigh(),
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100327 Address(SP, calling_convention.GetStackOffsetOf(argument_index + 1)));
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100328 } else {
329 DCHECK(source.IsDoubleStackSlot());
330 __ ldr(calling_convention.GetRegisterAt(argument_index), Address(SP, source.GetStackIndex()));
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100331 __ ldr(R0, Address(SP, source.GetHighStackIndex(kArmWordSize)));
332 __ str(R0, Address(SP, calling_convention.GetStackOffsetOf(argument_index + 1)));
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100333 }
334 } else {
335 DCHECK(destination.IsDoubleStackSlot());
336 if (source.IsRegister()) {
337 if (source.AsArm().AsRegisterPair() == R1_R2) {
338 __ str(R1, Address(SP, destination.GetStackIndex()));
339 __ str(R2, Address(SP, destination.GetHighStackIndex(kArmWordSize)));
340 } else {
341 __ StoreToOffset(kStoreWordPair, source.AsArm().AsRegisterPairLow(),
342 SP, destination.GetStackIndex());
343 }
344 } else if (source.IsQuickParameter()) {
345 InvokeDexCallingConvention calling_convention;
346 uint32_t argument_index = source.GetQuickParameterIndex();
347 __ str(calling_convention.GetRegisterAt(argument_index),
348 Address(SP, destination.GetStackIndex()));
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100349 __ ldr(R0,
350 Address(SP, calling_convention.GetStackOffsetOf(argument_index + 1) + GetFrameSize()));
351 __ str(R0, Address(SP, destination.GetHighStackIndex(kArmWordSize)));
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100352 } else {
353 DCHECK(source.IsDoubleStackSlot());
Nicolas Geoffraye27f31a2014-06-12 17:53:14 +0100354 __ ldr(IP, Address(SP, source.GetStackIndex()));
355 __ str(IP, Address(SP, destination.GetStackIndex()));
356 __ ldr(IP, Address(SP, source.GetHighStackIndex(kArmWordSize)));
357 __ str(IP, Address(SP, destination.GetHighStackIndex(kArmWordSize)));
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100358 }
359 }
360}
361
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100362void CodeGeneratorARM::Move(HInstruction* instruction, Location location, HInstruction* move_for) {
363 if (instruction->AsIntConstant() != nullptr) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100364 int32_t value = instruction->AsIntConstant()->GetValue();
365 if (location.IsRegister()) {
366 __ LoadImmediate(location.AsArm().AsCoreRegister(), value);
367 } else {
Nicolas Geoffraye27f31a2014-06-12 17:53:14 +0100368 __ LoadImmediate(IP, value);
369 __ str(IP, Address(SP, location.GetStackIndex()));
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100370 }
371 } else if (instruction->AsLongConstant() != nullptr) {
372 int64_t value = instruction->AsLongConstant()->GetValue();
373 if (location.IsRegister()) {
374 __ LoadImmediate(location.AsArm().AsRegisterPairLow(), Low32Bits(value));
375 __ LoadImmediate(location.AsArm().AsRegisterPairHigh(), High32Bits(value));
376 } else {
Nicolas Geoffraye27f31a2014-06-12 17:53:14 +0100377 __ LoadImmediate(IP, Low32Bits(value));
378 __ str(IP, Address(SP, location.GetStackIndex()));
379 __ LoadImmediate(IP, High32Bits(value));
380 __ str(IP, Address(SP, location.GetHighStackIndex(kArmWordSize)));
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100381 }
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100382 } else if (instruction->AsLoadLocal() != nullptr) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100383 uint32_t stack_slot = GetStackSlot(instruction->AsLoadLocal()->GetLocal());
384 switch (instruction->GetType()) {
385 case Primitive::kPrimBoolean:
386 case Primitive::kPrimByte:
387 case Primitive::kPrimChar:
388 case Primitive::kPrimShort:
389 case Primitive::kPrimInt:
390 case Primitive::kPrimNot:
391 Move32(location, Location::StackSlot(stack_slot));
392 break;
393
394 case Primitive::kPrimLong:
395 Move64(location, Location::DoubleStackSlot(stack_slot));
396 break;
397
398 default:
399 LOG(FATAL) << "Unimplemented type " << instruction->GetType();
400 }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000401 } else {
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100402 // This can currently only happen when the instruction that requests the move
403 // is the next to be compiled.
404 DCHECK_EQ(instruction->GetNext(), move_for);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100405 switch (instruction->GetType()) {
406 case Primitive::kPrimBoolean:
407 case Primitive::kPrimByte:
408 case Primitive::kPrimChar:
409 case Primitive::kPrimShort:
410 case Primitive::kPrimNot:
411 case Primitive::kPrimInt:
412 Move32(location, instruction->GetLocations()->Out());
413 break;
414
415 case Primitive::kPrimLong:
416 Move64(location, instruction->GetLocations()->Out());
417 break;
418
419 default:
420 LOG(FATAL) << "Unimplemented type " << instruction->GetType();
421 }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000422 }
423}
424
425void LocationsBuilderARM::VisitGoto(HGoto* got) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000426 got->SetLocations(nullptr);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000427}
428
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000429void InstructionCodeGeneratorARM::VisitGoto(HGoto* got) {
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000430 HBasicBlock* successor = got->GetSuccessor();
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000431 if (GetGraph()->GetExitBlock() == successor) {
432 codegen_->GenerateFrameExit();
433 } else if (!codegen_->GoesToNextBlock(got->GetBlock(), successor)) {
434 __ b(codegen_->GetLabelOf(successor));
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000435 }
436}
437
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000438void LocationsBuilderARM::VisitExit(HExit* exit) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000439 exit->SetLocations(nullptr);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000440}
441
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000442void InstructionCodeGeneratorARM::VisitExit(HExit* exit) {
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000443 if (kIsDebugBuild) {
444 __ Comment("Unreachable");
445 __ bkpt(0);
446 }
447}
448
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000449void LocationsBuilderARM::VisitIf(HIf* if_instr) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000450 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(if_instr);
Dave Allison20dfc792014-06-16 20:44:29 -0700451 locations->SetInAt(0, Location::Any());
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000452 if_instr->SetLocations(locations);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000453}
454
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000455void InstructionCodeGeneratorARM::VisitIf(HIf* if_instr) {
Dave Allison20dfc792014-06-16 20:44:29 -0700456 HInstruction* cond = if_instr->InputAt(0);
457 DCHECK(cond->IsCondition());
458 HCondition* condition = cond->AsCondition();
459 if (condition->NeedsMaterialization()) {
460 // Condition has been materialized, compare the output to 0
461 if (!if_instr->GetLocations()->InAt(0).IsRegister()) {
462 LOG(FATAL) << "Materialized condition is not in an ARM register";
463 }
464 __ cmp(if_instr->GetLocations()->InAt(0).AsArm().AsCoreRegister(),
465 ShifterOperand(0));
466 __ b(codegen_->GetLabelOf(if_instr->IfTrueSuccessor()), EQ);
467 } else {
468 // Condition has not been materialized, use its inputs as the comparison and its
469 // condition as the branch condition.
470 __ cmp(condition->GetLocations()->InAt(0).AsArm().AsCoreRegister(),
471 ShifterOperand(condition->GetLocations()->InAt(1).AsArm().AsCoreRegister()));
472 __ b(codegen_->GetLabelOf(if_instr->IfTrueSuccessor()),
473 ARMCondition(condition->GetCondition()));
474 }
475 if (!codegen_->GoesToNextBlock(if_instr->GetBlock(), if_instr->IfFalseSuccessor())) {
476 __ b(codegen_->GetLabelOf(if_instr->IfFalseSuccessor()));
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000477 }
478}
479
Dave Allison20dfc792014-06-16 20:44:29 -0700480
481void LocationsBuilderARM::VisitCondition(HCondition* comp) {
482 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(comp);
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100483 locations->SetInAt(0, Location::RequiresRegister());
484 locations->SetInAt(1, Location::RequiresRegister());
485 locations->SetOut(Location::RequiresRegister());
Dave Allison20dfc792014-06-16 20:44:29 -0700486 comp->SetLocations(locations);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000487}
488
Dave Allison20dfc792014-06-16 20:44:29 -0700489void InstructionCodeGeneratorARM::VisitCondition(HCondition* comp) {
490 if (comp->NeedsMaterialization()) {
491 LocationSummary* locations = comp->GetLocations();
492 __ cmp(locations->InAt(0).AsArm().AsCoreRegister(),
493 ShifterOperand(locations->InAt(1).AsArm().AsCoreRegister()));
494 __ it(ARMCondition(comp->GetCondition()), kItElse);
495 __ mov(locations->Out().AsArm().AsCoreRegister(), ShifterOperand(1),
496 ARMCondition(comp->GetCondition()));
497 __ mov(locations->Out().AsArm().AsCoreRegister(), ShifterOperand(0),
498 ARMOppositeCondition(comp->GetCondition()));
499 }
500}
501
502void LocationsBuilderARM::VisitEqual(HEqual* comp) {
503 VisitCondition(comp);
504}
505
506void InstructionCodeGeneratorARM::VisitEqual(HEqual* comp) {
507 VisitCondition(comp);
508}
509
510void LocationsBuilderARM::VisitNotEqual(HNotEqual* comp) {
511 VisitCondition(comp);
512}
513
514void InstructionCodeGeneratorARM::VisitNotEqual(HNotEqual* comp) {
515 VisitCondition(comp);
516}
517
518void LocationsBuilderARM::VisitLessThan(HLessThan* comp) {
519 VisitCondition(comp);
520}
521
522void InstructionCodeGeneratorARM::VisitLessThan(HLessThan* comp) {
523 VisitCondition(comp);
524}
525
526void LocationsBuilderARM::VisitLessThanOrEqual(HLessThanOrEqual* comp) {
527 VisitCondition(comp);
528}
529
530void InstructionCodeGeneratorARM::VisitLessThanOrEqual(HLessThanOrEqual* comp) {
531 VisitCondition(comp);
532}
533
534void LocationsBuilderARM::VisitGreaterThan(HGreaterThan* comp) {
535 VisitCondition(comp);
536}
537
538void InstructionCodeGeneratorARM::VisitGreaterThan(HGreaterThan* comp) {
539 VisitCondition(comp);
540}
541
542void LocationsBuilderARM::VisitGreaterThanOrEqual(HGreaterThanOrEqual* comp) {
543 VisitCondition(comp);
544}
545
546void InstructionCodeGeneratorARM::VisitGreaterThanOrEqual(HGreaterThanOrEqual* comp) {
547 VisitCondition(comp);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000548}
549
550void LocationsBuilderARM::VisitLocal(HLocal* local) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000551 local->SetLocations(nullptr);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000552}
553
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000554void InstructionCodeGeneratorARM::VisitLocal(HLocal* local) {
555 DCHECK_EQ(local->GetBlock(), GetGraph()->GetEntryBlock());
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000556}
557
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000558void LocationsBuilderARM::VisitLoadLocal(HLoadLocal* load) {
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100559 load->SetLocations(nullptr);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000560}
561
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000562void InstructionCodeGeneratorARM::VisitLoadLocal(HLoadLocal* load) {
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100563 // Nothing to do, this is driven by the code generator.
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000564}
565
566void LocationsBuilderARM::VisitStoreLocal(HStoreLocal* store) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000567 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(store);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100568 switch (store->InputAt(1)->GetType()) {
569 case Primitive::kPrimBoolean:
570 case Primitive::kPrimByte:
571 case Primitive::kPrimChar:
572 case Primitive::kPrimShort:
573 case Primitive::kPrimInt:
574 case Primitive::kPrimNot:
575 locations->SetInAt(1, Location::StackSlot(codegen_->GetStackSlot(store->GetLocal())));
576 break;
577
578 case Primitive::kPrimLong:
579 locations->SetInAt(1, Location::DoubleStackSlot(codegen_->GetStackSlot(store->GetLocal())));
580 break;
581
582 default:
583 LOG(FATAL) << "Unimplemented local type " << store->InputAt(1)->GetType();
584 }
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000585 store->SetLocations(locations);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000586}
587
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000588void InstructionCodeGeneratorARM::VisitStoreLocal(HStoreLocal* store) {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000589}
590
591void LocationsBuilderARM::VisitIntConstant(HIntConstant* constant) {
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100592 // TODO: Support constant locations.
593 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(constant);
594 locations->SetOut(Location::RequiresRegister());
595 constant->SetLocations(locations);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000596}
597
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000598void InstructionCodeGeneratorARM::VisitIntConstant(HIntConstant* constant) {
Nicolas Geoffraye27f31a2014-06-12 17:53:14 +0100599 codegen_->Move(constant, constant->GetLocations()->Out(), nullptr);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000600}
601
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100602void LocationsBuilderARM::VisitLongConstant(HLongConstant* constant) {
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100603 // TODO: Support constant locations.
604 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(constant);
605 locations->SetOut(Location::RequiresRegister());
606 constant->SetLocations(locations);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100607}
608
609void InstructionCodeGeneratorARM::VisitLongConstant(HLongConstant* constant) {
610 // Will be generated at use site.
611}
612
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000613void LocationsBuilderARM::VisitReturnVoid(HReturnVoid* ret) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000614 ret->SetLocations(nullptr);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000615}
616
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000617void InstructionCodeGeneratorARM::VisitReturnVoid(HReturnVoid* ret) {
618 codegen_->GenerateFrameExit();
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000619}
620
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000621void LocationsBuilderARM::VisitReturn(HReturn* ret) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000622 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(ret);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100623 switch (ret->InputAt(0)->GetType()) {
624 case Primitive::kPrimBoolean:
625 case Primitive::kPrimByte:
626 case Primitive::kPrimChar:
627 case Primitive::kPrimShort:
628 case Primitive::kPrimInt:
629 case Primitive::kPrimNot:
630 locations->SetInAt(0, ArmCoreLocation(R0));
631 break;
632
633 case Primitive::kPrimLong:
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100634 locations->SetInAt(
635 0, Location::RegisterLocation(ArmManagedRegister::FromRegisterPair(R0_R1)));
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100636 break;
637
638 default:
639 LOG(FATAL) << "Unimplemented return type " << ret->InputAt(0)->GetType();
640 }
641
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000642 ret->SetLocations(locations);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000643}
644
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000645void InstructionCodeGeneratorARM::VisitReturn(HReturn* ret) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100646 if (kIsDebugBuild) {
647 switch (ret->InputAt(0)->GetType()) {
648 case Primitive::kPrimBoolean:
649 case Primitive::kPrimByte:
650 case Primitive::kPrimChar:
651 case Primitive::kPrimShort:
652 case Primitive::kPrimInt:
653 case Primitive::kPrimNot:
654 DCHECK_EQ(ret->GetLocations()->InAt(0).AsArm().AsCoreRegister(), R0);
655 break;
656
657 case Primitive::kPrimLong:
658 DCHECK_EQ(ret->GetLocations()->InAt(0).AsArm().AsRegisterPair(), R0_R1);
659 break;
660
661 default:
662 LOG(FATAL) << "Unimplemented return type " << ret->InputAt(0)->GetType();
663 }
664 }
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000665 codegen_->GenerateFrameExit();
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000666}
667
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000668void LocationsBuilderARM::VisitInvokeStatic(HInvokeStatic* invoke) {
669 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(invoke);
Nicolas Geoffraye27f31a2014-06-12 17:53:14 +0100670 locations->AddTemp(ArmCoreLocation(R0));
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100671
672 InvokeDexCallingConventionVisitor calling_convention_visitor;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100673 for (size_t i = 0; i < invoke->InputCount(); i++) {
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100674 HInstruction* input = invoke->InputAt(i);
675 locations->SetInAt(i, calling_convention_visitor.GetNextLocation(input->GetType()));
676 }
677
678 switch (invoke->GetType()) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100679 case Primitive::kPrimBoolean:
680 case Primitive::kPrimByte:
681 case Primitive::kPrimChar:
682 case Primitive::kPrimShort:
683 case Primitive::kPrimInt:
684 case Primitive::kPrimNot:
685 locations->SetOut(ArmCoreLocation(R0));
686 break;
687
688 case Primitive::kPrimLong:
689 locations->SetOut(Location::RegisterLocation(ArmManagedRegister::FromRegisterPair(R0_R1)));
690 break;
691
692 case Primitive::kPrimVoid:
693 break;
694
695 case Primitive::kPrimDouble:
696 case Primitive::kPrimFloat:
697 LOG(FATAL) << "Unimplemented return type " << invoke->GetType();
698 break;
699 }
700
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000701 invoke->SetLocations(locations);
702}
703
704void InstructionCodeGeneratorARM::LoadCurrentMethod(Register reg) {
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100705 __ ldr(reg, Address(SP, kCurrentMethodStackOffset));
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000706}
707
708void InstructionCodeGeneratorARM::VisitInvokeStatic(HInvokeStatic* invoke) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100709 Register temp = invoke->GetLocations()->GetTemp(0).AsArm().AsCoreRegister();
Nicolas Geoffrayf61b5372014-06-25 14:35:34 +0100710 uint32_t heap_reference_size = sizeof(mirror::HeapReference<mirror::Object>);
711 size_t index_in_cache = mirror::Array::DataOffset(heap_reference_size).Int32Value() +
Nicolas Geoffray707c8092014-04-04 10:50:14 +0100712 invoke->GetIndexInDexCache() * kArmWordSize;
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000713
714 // TODO: Implement all kinds of calls:
715 // 1) boot -> boot
716 // 2) app -> boot
717 // 3) app -> app
718 //
719 // Currently we implement the app -> app logic, which looks up in the resolve cache.
720
721 // temp = method;
722 LoadCurrentMethod(temp);
723 // temp = temp->dex_cache_resolved_methods_;
724 __ ldr(temp, Address(temp, mirror::ArtMethod::DexCacheResolvedMethodsOffset().Int32Value()));
725 // temp = temp[index_in_cache]
726 __ ldr(temp, Address(temp, index_in_cache));
727 // LR = temp[offset_of_quick_compiled_code]
728 __ ldr(LR, Address(temp,
729 mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset().Int32Value()));
730 // LR()
731 __ blx(LR);
732
733 codegen_->RecordPcInfo(invoke->GetDexPc());
734}
735
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000736void LocationsBuilderARM::VisitAdd(HAdd* add) {
737 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(add);
738 switch (add->GetResultType()) {
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100739 case Primitive::kPrimInt:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100740 case Primitive::kPrimLong: {
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100741 locations->SetInAt(0, Location::RequiresRegister());
742 locations->SetInAt(1, Location::RequiresRegister());
743 locations->SetOut(Location::RequiresRegister());
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100744 break;
745 }
746
747 case Primitive::kPrimBoolean:
748 case Primitive::kPrimByte:
749 case Primitive::kPrimChar:
750 case Primitive::kPrimShort:
751 LOG(FATAL) << "Unexpected add type " << add->GetResultType();
752 break;
753
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000754 default:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100755 LOG(FATAL) << "Unimplemented add type " << add->GetResultType();
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000756 }
757 add->SetLocations(locations);
758}
759
760void InstructionCodeGeneratorARM::VisitAdd(HAdd* add) {
761 LocationSummary* locations = add->GetLocations();
762 switch (add->GetResultType()) {
763 case Primitive::kPrimInt:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100764 __ add(locations->Out().AsArm().AsCoreRegister(),
765 locations->InAt(0).AsArm().AsCoreRegister(),
766 ShifterOperand(locations->InAt(1).AsArm().AsCoreRegister()));
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000767 break;
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100768
769 case Primitive::kPrimLong:
770 __ adds(locations->Out().AsArm().AsRegisterPairLow(),
771 locations->InAt(0).AsArm().AsRegisterPairLow(),
772 ShifterOperand(locations->InAt(1).AsArm().AsRegisterPairLow()));
773 __ adc(locations->Out().AsArm().AsRegisterPairHigh(),
774 locations->InAt(0).AsArm().AsRegisterPairHigh(),
775 ShifterOperand(locations->InAt(1).AsArm().AsRegisterPairHigh()));
776 break;
777
778 case Primitive::kPrimBoolean:
779 case Primitive::kPrimByte:
780 case Primitive::kPrimChar:
781 case Primitive::kPrimShort:
782 LOG(FATAL) << "Unexpected add type " << add->GetResultType();
783 break;
784
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000785 default:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100786 LOG(FATAL) << "Unimplemented add type " << add->GetResultType();
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000787 }
788}
789
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100790void LocationsBuilderARM::VisitSub(HSub* sub) {
791 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(sub);
792 switch (sub->GetResultType()) {
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100793 case Primitive::kPrimInt:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100794 case Primitive::kPrimLong: {
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100795 locations->SetInAt(0, Location::RequiresRegister());
796 locations->SetInAt(1, Location::RequiresRegister());
797 locations->SetOut(Location::RequiresRegister());
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100798 break;
799 }
800
801 case Primitive::kPrimBoolean:
802 case Primitive::kPrimByte:
803 case Primitive::kPrimChar:
804 case Primitive::kPrimShort:
805 LOG(FATAL) << "Unexpected sub type " << sub->GetResultType();
806 break;
807
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100808 default:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100809 LOG(FATAL) << "Unimplemented sub type " << sub->GetResultType();
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100810 }
811 sub->SetLocations(locations);
812}
813
814void InstructionCodeGeneratorARM::VisitSub(HSub* sub) {
815 LocationSummary* locations = sub->GetLocations();
816 switch (sub->GetResultType()) {
817 case Primitive::kPrimInt:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100818 __ sub(locations->Out().AsArm().AsCoreRegister(),
819 locations->InAt(0).AsArm().AsCoreRegister(),
820 ShifterOperand(locations->InAt(1).AsArm().AsCoreRegister()));
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100821 break;
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100822
823 case Primitive::kPrimLong:
824 __ subs(locations->Out().AsArm().AsRegisterPairLow(),
825 locations->InAt(0).AsArm().AsRegisterPairLow(),
826 ShifterOperand(locations->InAt(1).AsArm().AsRegisterPairLow()));
827 __ sbc(locations->Out().AsArm().AsRegisterPairHigh(),
828 locations->InAt(0).AsArm().AsRegisterPairHigh(),
829 ShifterOperand(locations->InAt(1).AsArm().AsRegisterPairHigh()));
830 break;
831
832 case Primitive::kPrimBoolean:
833 case Primitive::kPrimByte:
834 case Primitive::kPrimChar:
835 case Primitive::kPrimShort:
836 LOG(FATAL) << "Unexpected sub type " << sub->GetResultType();
837 break;
838
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100839 default:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100840 LOG(FATAL) << "Unimplemented sub type " << sub->GetResultType();
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100841 }
842}
843
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100844static constexpr Register kRuntimeParameterCoreRegisters[] = { R0, R1 };
845static constexpr size_t kRuntimeParameterCoreRegistersLength =
846 arraysize(kRuntimeParameterCoreRegisters);
847
848class InvokeRuntimeCallingConvention : public CallingConvention<Register> {
849 public:
850 InvokeRuntimeCallingConvention()
851 : CallingConvention(kRuntimeParameterCoreRegisters,
852 kRuntimeParameterCoreRegistersLength) {}
853
854 private:
855 DISALLOW_COPY_AND_ASSIGN(InvokeRuntimeCallingConvention);
856};
857
858void LocationsBuilderARM::VisitNewInstance(HNewInstance* instruction) {
859 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100860 InvokeRuntimeCallingConvention calling_convention;
861 locations->AddTemp(ArmCoreLocation(calling_convention.GetRegisterAt(0)));
862 locations->AddTemp(ArmCoreLocation(calling_convention.GetRegisterAt(1)));
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100863 locations->SetOut(ArmCoreLocation(R0));
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100864 instruction->SetLocations(locations);
865}
866
867void InstructionCodeGeneratorARM::VisitNewInstance(HNewInstance* instruction) {
868 InvokeRuntimeCallingConvention calling_convention;
869 LoadCurrentMethod(calling_convention.GetRegisterAt(1));
870 __ LoadImmediate(calling_convention.GetRegisterAt(0), instruction->GetTypeIndex());
871
Nicolas Geoffray707c8092014-04-04 10:50:14 +0100872 int32_t offset = QUICK_ENTRYPOINT_OFFSET(kArmWordSize, pAllocObjectWithAccessCheck).Int32Value();
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100873 __ ldr(LR, Address(TR, offset));
874 __ blx(LR);
875
876 codegen_->RecordPcInfo(instruction->GetDexPc());
877}
878
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100879void LocationsBuilderARM::VisitParameterValue(HParameterValue* instruction) {
880 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100881 Location location = parameter_visitor_.GetNextLocation(instruction->GetType());
882 if (location.IsStackSlot()) {
883 location = Location::StackSlot(location.GetStackIndex() + codegen_->GetFrameSize());
884 } else if (location.IsDoubleStackSlot()) {
885 location = Location::DoubleStackSlot(location.GetStackIndex() + codegen_->GetFrameSize());
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100886 }
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100887 locations->SetOut(location);
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100888 instruction->SetLocations(locations);
889}
890
891void InstructionCodeGeneratorARM::VisitParameterValue(HParameterValue* instruction) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100892 // Nothing to do, the parameter is already at its location.
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100893}
894
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100895void LocationsBuilderARM::VisitNot(HNot* instruction) {
896 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100897 locations->SetInAt(0, Location::RequiresRegister());
898 locations->SetOut(Location::RequiresRegister());
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100899 instruction->SetLocations(locations);
900}
901
902void InstructionCodeGeneratorARM::VisitNot(HNot* instruction) {
903 LocationSummary* locations = instruction->GetLocations();
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100904 __ eor(locations->Out().AsArm().AsCoreRegister(),
905 locations->InAt(0).AsArm().AsCoreRegister(), ShifterOperand(1));
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100906}
907
Nicolas Geoffray412f10c2014-06-19 10:00:34 +0100908void LocationsBuilderARM::VisitCompare(HCompare* compare) {
909 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(compare);
910 locations->SetInAt(0, Location::RequiresRegister());
911 locations->SetInAt(1, Location::RequiresRegister());
912 locations->SetOut(Location::RequiresRegister());
913 compare->SetLocations(locations);
914}
915
916void InstructionCodeGeneratorARM::VisitCompare(HCompare* compare) {
917 Label greater, done;
918 LocationSummary* locations = compare->GetLocations();
919 switch (compare->InputAt(0)->GetType()) {
920 case Primitive::kPrimLong: {
921 Register output = locations->Out().AsArm().AsCoreRegister();
922 ArmManagedRegister left = locations->InAt(0).AsArm();
923 ArmManagedRegister right = locations->InAt(1).AsArm();
924 Label less, greater, done;
925 __ cmp(left.AsRegisterPairHigh(),
926 ShifterOperand(right.AsRegisterPairHigh())); // Signed compare.
927 __ b(&less, LT);
928 __ b(&greater, GT);
929 __ cmp(left.AsRegisterPairLow(),
930 ShifterOperand(right.AsRegisterPairLow())); // Unsigned compare.
931 __ LoadImmediate(output, 0);
932 __ b(&done, EQ);
933 __ b(&less, CC);
934
935 __ Bind(&greater);
936 __ LoadImmediate(output, 1);
937 __ b(&done);
938
939 __ Bind(&less);
940 __ LoadImmediate(output, -1);
941
942 __ Bind(&done);
943 break;
944 }
945 default:
946 LOG(FATAL) << "Unimplemented compare type " << compare->InputAt(0)->GetType();
947 }
948}
949
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100950void LocationsBuilderARM::VisitPhi(HPhi* instruction) {
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100951 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
952 for (size_t i = 0, e = instruction->InputCount(); i < e; ++i) {
953 locations->SetInAt(i, Location::Any());
954 }
955 locations->SetOut(Location::Any());
956 instruction->SetLocations(locations);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100957}
958
959void InstructionCodeGeneratorARM::VisitPhi(HPhi* instruction) {
Nicolas Geoffraye27f31a2014-06-12 17:53:14 +0100960 LOG(FATAL) << "Unreachable";
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100961}
962
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100963void LocationsBuilderARM::VisitParallelMove(HParallelMove* instruction) {
Nicolas Geoffraye27f31a2014-06-12 17:53:14 +0100964 LOG(FATAL) << "Unreachable";
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100965}
966
967void InstructionCodeGeneratorARM::VisitParallelMove(HParallelMove* instruction) {
Nicolas Geoffraye27f31a2014-06-12 17:53:14 +0100968 codegen_->GetMoveResolver()->EmitNativeCode(instruction);
969}
970
971ArmAssembler* ParallelMoveResolverARM::GetAssembler() const {
972 return codegen_->GetAssembler();
973}
974
975void ParallelMoveResolverARM::EmitMove(size_t index) {
976 MoveOperands* move = moves_.Get(index);
977 Location source = move->GetSource();
978 Location destination = move->GetDestination();
979
980 if (source.IsRegister()) {
981 if (destination.IsRegister()) {
982 __ Mov(destination.AsArm().AsCoreRegister(), source.AsArm().AsCoreRegister());
983 } else {
984 DCHECK(destination.IsStackSlot());
985 __ StoreToOffset(kStoreWord, source.AsArm().AsCoreRegister(),
986 SP, destination.GetStackIndex());
987 }
988 } else if (source.IsStackSlot()) {
989 if (destination.IsRegister()) {
990 __ LoadFromOffset(kLoadWord, destination.AsArm().AsCoreRegister(),
991 SP, source.GetStackIndex());
992 } else {
993 DCHECK(destination.IsStackSlot());
994 __ LoadFromOffset(kLoadWord, IP, SP, source.GetStackIndex());
995 __ StoreToOffset(kStoreWord, IP, SP, destination.GetStackIndex());
996 }
997 } else {
998 LOG(FATAL) << "Unimplemented";
999 }
1000}
1001
1002void ParallelMoveResolverARM::Exchange(Register reg, int mem) {
1003 __ Mov(IP, reg);
1004 __ LoadFromOffset(kLoadWord, reg, SP, mem);
1005 __ StoreToOffset(kStoreWord, IP, SP, mem);
1006}
1007
1008void ParallelMoveResolverARM::Exchange(int mem1, int mem2) {
1009 ScratchRegisterScope ensure_scratch(this, IP, R0, codegen_->GetNumberOfCoreRegisters());
1010 int stack_offset = ensure_scratch.IsSpilled() ? kArmWordSize : 0;
1011 __ LoadFromOffset(kLoadWord, static_cast<Register>(ensure_scratch.GetRegister()),
1012 SP, mem1 + stack_offset);
1013 __ LoadFromOffset(kLoadWord, IP, SP, mem2 + stack_offset);
1014 __ StoreToOffset(kStoreWord, static_cast<Register>(ensure_scratch.GetRegister()),
1015 SP, mem2 + stack_offset);
1016 __ StoreToOffset(kStoreWord, IP, SP, mem1 + stack_offset);
1017}
1018
1019void ParallelMoveResolverARM::EmitSwap(size_t index) {
1020 MoveOperands* move = moves_.Get(index);
1021 Location source = move->GetSource();
1022 Location destination = move->GetDestination();
1023
1024 if (source.IsRegister() && destination.IsRegister()) {
1025 DCHECK_NE(source.AsArm().AsCoreRegister(), IP);
1026 DCHECK_NE(destination.AsArm().AsCoreRegister(), IP);
1027 __ Mov(IP, source.AsArm().AsCoreRegister());
1028 __ Mov(source.AsArm().AsCoreRegister(), destination.AsArm().AsCoreRegister());
1029 __ Mov(destination.AsArm().AsCoreRegister(), IP);
1030 } else if (source.IsRegister() && destination.IsStackSlot()) {
1031 Exchange(source.AsArm().AsCoreRegister(), destination.GetStackIndex());
1032 } else if (source.IsStackSlot() && destination.IsRegister()) {
1033 Exchange(destination.AsArm().AsCoreRegister(), source.GetStackIndex());
1034 } else if (source.IsStackSlot() && destination.IsStackSlot()) {
1035 Exchange(source.GetStackIndex(), destination.GetStackIndex());
1036 } else {
1037 LOG(FATAL) << "Unimplemented";
1038 }
1039}
1040
1041void ParallelMoveResolverARM::SpillScratch(int reg) {
1042 __ Push(static_cast<Register>(reg));
1043}
1044
1045void ParallelMoveResolverARM::RestoreScratch(int reg) {
1046 __ Pop(static_cast<Register>(reg));
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01001047}
1048
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +00001049} // namespace arm
1050} // namespace art