blob: 641e8e178b859c78e60303a25bfc000a4ba41eaa [file] [log] [blame]
Nicolas Geoffray9cf35522014-06-09 18:40:10 +01001/*
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_x86_64.h"
18
19#include "entrypoints/quick/quick_entrypoints.h"
Nicolas Geoffray1a43dd72014-07-17 15:15:34 +010020#include "gc/accounting/card_table.h"
Nicolas Geoffray9cf35522014-06-09 18:40:10 +010021#include "mirror/array.h"
22#include "mirror/art_method.h"
23#include "mirror/object_reference.h"
24#include "thread.h"
25#include "utils/assembler.h"
Nicolas Geoffrayf12feb82014-07-17 18:32:41 +010026#include "utils/stack_checks.h"
Nicolas Geoffray9cf35522014-06-09 18:40:10 +010027#include "utils/x86_64/assembler_x86_64.h"
28#include "utils/x86_64/managed_register_x86_64.h"
29
Nicolas Geoffray9cf35522014-06-09 18:40:10 +010030namespace art {
31
32x86_64::X86_64ManagedRegister Location::AsX86_64() const {
33 return reg().AsX86_64();
34}
35
36namespace x86_64 {
37
Nicolas Geoffrayf12feb82014-07-17 18:32:41 +010038static constexpr bool kExplicitStackOverflowCheck = true;
39
40// Some x86_64 instructions require a register to be available as temp.
41static constexpr Register TMP = R11;
42
43static constexpr int kNumberOfPushedRegistersAtEntry = 1;
44static constexpr int kCurrentMethodStackOffset = 0;
45
46
Nicolas Geoffraye5038322014-07-04 09:41:32 +010047#define __ reinterpret_cast<X86_64Assembler*>(codegen->GetAssembler())->
48
49class NullCheckSlowPathX86_64 : public SlowPathCode {
50 public:
51 explicit NullCheckSlowPathX86_64(uint32_t dex_pc) : dex_pc_(dex_pc) {}
52
53 virtual void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
54 __ Bind(GetEntryLabel());
Nicolas Geoffrayf12feb82014-07-17 18:32:41 +010055 __ gs()->call(
56 Address::Absolute(QUICK_ENTRYPOINT_OFFSET(kX86_64WordSize, pThrowNullPointer), true));
Nicolas Geoffraye5038322014-07-04 09:41:32 +010057 codegen->RecordPcInfo(dex_pc_);
58 }
59
60 private:
61 const uint32_t dex_pc_;
62 DISALLOW_COPY_AND_ASSIGN(NullCheckSlowPathX86_64);
63};
64
Nicolas Geoffrayf12feb82014-07-17 18:32:41 +010065class StackOverflowCheckSlowPathX86_64 : public SlowPathCode {
66 public:
67 StackOverflowCheckSlowPathX86_64() {}
68
69 virtual void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
70 __ Bind(GetEntryLabel());
71 __ addq(CpuRegister(RSP),
72 Immediate(codegen->GetFrameSize() - kNumberOfPushedRegistersAtEntry * kX86_64WordSize));
73 __ gs()->jmp(
74 Address::Absolute(QUICK_ENTRYPOINT_OFFSET(kX86_64WordSize, pThrowStackOverflow), true));
75 }
76
77 private:
78 DISALLOW_COPY_AND_ASSIGN(StackOverflowCheckSlowPathX86_64);
79};
80
Nicolas Geoffraye5038322014-07-04 09:41:32 +010081#undef __
82#define __ reinterpret_cast<X86_64Assembler*>(GetAssembler())->
83
Dave Allison20dfc792014-06-16 20:44:29 -070084inline Condition X86_64Condition(IfCondition cond) {
85 switch (cond) {
86 case kCondEQ: return kEqual;
87 case kCondNE: return kNotEqual;
88 case kCondLT: return kLess;
89 case kCondLE: return kLessEqual;
90 case kCondGT: return kGreater;
91 case kCondGE: return kGreaterEqual;
92 default:
93 LOG(FATAL) << "Unknown if condition";
94 }
95 return kEqual;
96}
97
Nicolas Geoffray9cf35522014-06-09 18:40:10 +010098void CodeGeneratorX86_64::DumpCoreRegister(std::ostream& stream, int reg) const {
99 stream << X86_64ManagedRegister::FromCpuRegister(Register(reg));
100}
101
102void CodeGeneratorX86_64::DumpFloatingPointRegister(std::ostream& stream, int reg) const {
103 stream << X86_64ManagedRegister::FromXmmRegister(FloatRegister(reg));
104}
105
106static Location X86_64CpuLocation(Register reg) {
107 return Location::RegisterLocation(X86_64ManagedRegister::FromCpuRegister(reg));
108}
109
110CodeGeneratorX86_64::CodeGeneratorX86_64(HGraph* graph)
111 : CodeGenerator(graph, kNumberOfRegIds),
112 location_builder_(graph, this),
Nicolas Geoffrayecb2f9b2014-06-13 08:59:59 +0000113 instruction_visitor_(graph, this),
114 move_resolver_(graph->GetArena(), this) {}
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100115
Nicolas Geoffrayab032bc2014-07-15 12:55:21 +0100116size_t CodeGeneratorX86_64::FrameEntrySpillSize() const {
117 return kNumberOfPushedRegistersAtEntry * kX86_64WordSize;
118}
119
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100120InstructionCodeGeneratorX86_64::InstructionCodeGeneratorX86_64(HGraph* graph, CodeGeneratorX86_64* codegen)
121 : HGraphVisitor(graph),
122 assembler_(codegen->GetAssembler()),
123 codegen_(codegen) {}
124
125ManagedRegister CodeGeneratorX86_64::AllocateFreeRegister(Primitive::Type type,
126 bool* blocked_registers) const {
127 switch (type) {
128 case Primitive::kPrimLong:
129 case Primitive::kPrimByte:
130 case Primitive::kPrimBoolean:
131 case Primitive::kPrimChar:
132 case Primitive::kPrimShort:
133 case Primitive::kPrimInt:
134 case Primitive::kPrimNot: {
135 size_t reg = AllocateFreeRegisterInternal(blocked_registers, kNumberOfCpuRegisters);
136 return X86_64ManagedRegister::FromCpuRegister(static_cast<Register>(reg));
137 }
138
139 case Primitive::kPrimFloat:
140 case Primitive::kPrimDouble:
141 LOG(FATAL) << "Unimplemented register type " << type;
142
143 case Primitive::kPrimVoid:
144 LOG(FATAL) << "Unreachable type " << type;
145 }
146
147 return ManagedRegister::NoRegister();
148}
149
150void CodeGeneratorX86_64::SetupBlockedRegisters(bool* blocked_registers) const {
151 // Stack register is always reserved.
152 blocked_registers[RSP] = true;
153
Nicolas Geoffrayecb2f9b2014-06-13 08:59:59 +0000154 // Block the register used as TMP.
155 blocked_registers[TMP] = true;
156
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100157 // TODO: We currently don't use Quick's callee saved registers.
158 blocked_registers[RBX] = true;
159 blocked_registers[RBP] = true;
160 blocked_registers[R12] = true;
161 blocked_registers[R13] = true;
162 blocked_registers[R14] = true;
163 blocked_registers[R15] = true;
164}
165
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100166void CodeGeneratorX86_64::GenerateFrameEntry() {
167 // Create a fake register to mimic Quick.
168 static const int kFakeReturnRegister = 16;
169 core_spill_mask_ |= (1 << kFakeReturnRegister);
170
171 // The return PC has already been pushed on the stack.
Nicolas Geoffrayf12feb82014-07-17 18:32:41 +0100172 __ subq(CpuRegister(RSP),
173 Immediate(GetFrameSize() - kNumberOfPushedRegistersAtEntry * kX86_64WordSize));
174
175 bool skip_overflow_check = IsLeafMethod()
176 && !IsLargeFrame(GetFrameSize(), InstructionSet::kX86_64);
177
178 if (!skip_overflow_check) {
179 if (kExplicitStackOverflowCheck) {
180 SlowPathCode* slow_path = new (GetGraph()->GetArena()) StackOverflowCheckSlowPathX86_64();
181 AddSlowPath(slow_path);
182
183 __ gs()->cmpq(CpuRegister(RSP),
184 Address::Absolute(Thread::StackEndOffset<kX86_64WordSize>(), true));
185 __ j(kLess, slow_path->GetEntryLabel());
186 } else {
187 __ testq(CpuRegister(RAX), Address(
188 CpuRegister(RSP), -static_cast<int32_t>(GetStackOverflowReservedBytes(kX86_64))));
189 }
190 }
191
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100192 __ movl(Address(CpuRegister(RSP), kCurrentMethodStackOffset), CpuRegister(RDI));
193}
194
195void CodeGeneratorX86_64::GenerateFrameExit() {
196 __ addq(CpuRegister(RSP),
197 Immediate(GetFrameSize() - kNumberOfPushedRegistersAtEntry * kX86_64WordSize));
198}
199
200void CodeGeneratorX86_64::Bind(Label* label) {
201 __ Bind(label);
202}
203
204void InstructionCodeGeneratorX86_64::LoadCurrentMethod(CpuRegister reg) {
205 __ movl(reg, Address(CpuRegister(RSP), kCurrentMethodStackOffset));
206}
207
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100208Location CodeGeneratorX86_64::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
234void CodeGeneratorX86_64::Move(Location destination, Location source) {
235 if (source.Equals(destination)) {
236 return;
237 }
238 if (destination.IsRegister()) {
239 if (source.IsRegister()) {
240 __ movq(destination.AsX86_64().AsCpuRegister(), source.AsX86_64().AsCpuRegister());
241 } else if (source.IsStackSlot()) {
242 __ movl(destination.AsX86_64().AsCpuRegister(), Address(CpuRegister(RSP), source.GetStackIndex()));
243 } else {
244 DCHECK(source.IsDoubleStackSlot());
245 __ movq(destination.AsX86_64().AsCpuRegister(), Address(CpuRegister(RSP), source.GetStackIndex()));
246 }
247 } else if (destination.IsStackSlot()) {
248 if (source.IsRegister()) {
249 __ movl(Address(CpuRegister(RSP), destination.GetStackIndex()), source.AsX86_64().AsCpuRegister());
250 } else {
251 DCHECK(source.IsStackSlot());
Nicolas Geoffrayecb2f9b2014-06-13 08:59:59 +0000252 __ movl(CpuRegister(TMP), Address(CpuRegister(RSP), source.GetStackIndex()));
253 __ movl(Address(CpuRegister(RSP), destination.GetStackIndex()), CpuRegister(TMP));
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100254 }
255 } else {
256 DCHECK(destination.IsDoubleStackSlot());
257 if (source.IsRegister()) {
258 __ movq(Address(CpuRegister(RSP), destination.GetStackIndex()), source.AsX86_64().AsCpuRegister());
259 } else {
260 DCHECK(source.IsDoubleStackSlot());
Nicolas Geoffrayecb2f9b2014-06-13 08:59:59 +0000261 __ movq(CpuRegister(TMP), Address(CpuRegister(RSP), source.GetStackIndex()));
262 __ movq(Address(CpuRegister(RSP), destination.GetStackIndex()), CpuRegister(TMP));
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100263 }
264 }
265}
266
Nicolas Geoffray412f10c2014-06-19 10:00:34 +0100267void CodeGeneratorX86_64::Move(HInstruction* instruction,
268 Location location,
269 HInstruction* move_for) {
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100270 if (instruction->AsIntConstant() != nullptr) {
271 Immediate imm(instruction->AsIntConstant()->GetValue());
272 if (location.IsRegister()) {
Nicolas Geoffrayecb2f9b2014-06-13 08:59:59 +0000273 __ movl(location.AsX86_64().AsCpuRegister(), imm);
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100274 } else {
275 __ movl(Address(CpuRegister(RSP), location.GetStackIndex()), imm);
276 }
277 } else if (instruction->AsLongConstant() != nullptr) {
278 int64_t value = instruction->AsLongConstant()->GetValue();
279 if (location.IsRegister()) {
280 __ movq(location.AsX86_64().AsCpuRegister(), Immediate(value));
281 } else {
Nicolas Geoffrayecb2f9b2014-06-13 08:59:59 +0000282 __ movq(CpuRegister(TMP), Immediate(value));
283 __ movq(Address(CpuRegister(RSP), location.GetStackIndex()), CpuRegister(TMP));
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100284 }
285 } else if (instruction->AsLoadLocal() != nullptr) {
286 switch (instruction->GetType()) {
287 case Primitive::kPrimBoolean:
288 case Primitive::kPrimByte:
289 case Primitive::kPrimChar:
290 case Primitive::kPrimShort:
291 case Primitive::kPrimInt:
292 case Primitive::kPrimNot:
293 Move(location, Location::StackSlot(GetStackSlot(instruction->AsLoadLocal()->GetLocal())));
294 break;
295
296 case Primitive::kPrimLong:
297 Move(location, Location::DoubleStackSlot(GetStackSlot(instruction->AsLoadLocal()->GetLocal())));
298 break;
299
300 default:
301 LOG(FATAL) << "Unimplemented local type " << instruction->GetType();
302 }
303 } else {
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100304 DCHECK((instruction->GetNext() == move_for) || instruction->GetNext()->IsTemporary());
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100305 switch (instruction->GetType()) {
306 case Primitive::kPrimBoolean:
307 case Primitive::kPrimByte:
308 case Primitive::kPrimChar:
309 case Primitive::kPrimShort:
310 case Primitive::kPrimInt:
311 case Primitive::kPrimNot:
312 case Primitive::kPrimLong:
313 Move(location, instruction->GetLocations()->Out());
314 break;
315
316 default:
317 LOG(FATAL) << "Unimplemented type " << instruction->GetType();
318 }
319 }
320}
321
322void LocationsBuilderX86_64::VisitGoto(HGoto* got) {
323 got->SetLocations(nullptr);
324}
325
326void InstructionCodeGeneratorX86_64::VisitGoto(HGoto* got) {
327 HBasicBlock* successor = got->GetSuccessor();
328 if (GetGraph()->GetExitBlock() == successor) {
329 codegen_->GenerateFrameExit();
330 } else if (!codegen_->GoesToNextBlock(got->GetBlock(), successor)) {
331 __ jmp(codegen_->GetLabelOf(successor));
332 }
333}
334
335void LocationsBuilderX86_64::VisitExit(HExit* exit) {
336 exit->SetLocations(nullptr);
337}
338
339void InstructionCodeGeneratorX86_64::VisitExit(HExit* exit) {
340 if (kIsDebugBuild) {
341 __ Comment("Unreachable");
342 __ int3();
343 }
344}
345
346void LocationsBuilderX86_64::VisitIf(HIf* if_instr) {
347 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(if_instr);
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100348 HInstruction* cond = if_instr->InputAt(0);
349 DCHECK(cond->IsCondition());
350 HCondition* condition = cond->AsCondition();
351 if (condition->NeedsMaterialization()) {
352 locations->SetInAt(0, Location::Any());
353 }
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100354 if_instr->SetLocations(locations);
355}
356
357void InstructionCodeGeneratorX86_64::VisitIf(HIf* if_instr) {
Dave Allison20dfc792014-06-16 20:44:29 -0700358 HInstruction* cond = if_instr->InputAt(0);
359 DCHECK(cond->IsCondition());
360 HCondition* condition = cond->AsCondition();
361 if (condition->NeedsMaterialization()) {
362 // Materialized condition, compare against 0.
363 Location lhs = if_instr->GetLocations()->InAt(0);
364 if (lhs.IsRegister()) {
365 __ cmpl(lhs.AsX86_64().AsCpuRegister(), Immediate(0));
366 } else {
367 __ cmpl(Address(CpuRegister(RSP), lhs.GetStackIndex()), Immediate(0));
368 }
369 __ j(kEqual, codegen_->GetLabelOf(if_instr->IfTrueSuccessor()));
370 } else {
371 Location lhs = condition->GetLocations()->InAt(0);
372 Location rhs = condition->GetLocations()->InAt(1);
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100373 if (rhs.IsRegister()) {
374 __ cmpl(lhs.AsX86_64().AsCpuRegister(), rhs.AsX86_64().AsCpuRegister());
375 } else if (rhs.IsConstant()) {
376 __ cmpl(lhs.AsX86_64().AsCpuRegister(),
377 Immediate(rhs.GetConstant()->AsIntConstant()->GetValue()));
378 } else {
379 __ cmpl(lhs.AsX86_64().AsCpuRegister(), Address(CpuRegister(RSP), rhs.GetStackIndex()));
380 }
Dave Allison20dfc792014-06-16 20:44:29 -0700381 __ j(X86_64Condition(condition->GetCondition()),
382 codegen_->GetLabelOf(if_instr->IfTrueSuccessor()));
383 }
384 if (!codegen_->GoesToNextBlock(if_instr->GetBlock(), if_instr->IfFalseSuccessor())) {
385 __ jmp(codegen_->GetLabelOf(if_instr->IfFalseSuccessor()));
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100386 }
387}
388
389void LocationsBuilderX86_64::VisitLocal(HLocal* local) {
390 local->SetLocations(nullptr);
391}
392
393void InstructionCodeGeneratorX86_64::VisitLocal(HLocal* local) {
394 DCHECK_EQ(local->GetBlock(), GetGraph()->GetEntryBlock());
395}
396
397void LocationsBuilderX86_64::VisitLoadLocal(HLoadLocal* local) {
398 local->SetLocations(nullptr);
399}
400
401void InstructionCodeGeneratorX86_64::VisitLoadLocal(HLoadLocal* load) {
402 // Nothing to do, this is driven by the code generator.
403}
404
405void LocationsBuilderX86_64::VisitStoreLocal(HStoreLocal* store) {
406 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(store);
407 switch (store->InputAt(1)->GetType()) {
408 case Primitive::kPrimBoolean:
409 case Primitive::kPrimByte:
410 case Primitive::kPrimChar:
411 case Primitive::kPrimShort:
412 case Primitive::kPrimInt:
413 case Primitive::kPrimNot:
414 locations->SetInAt(1, Location::StackSlot(codegen_->GetStackSlot(store->GetLocal())));
415 break;
416
417 case Primitive::kPrimLong:
418 locations->SetInAt(1, Location::DoubleStackSlot(codegen_->GetStackSlot(store->GetLocal())));
419 break;
420
421 default:
422 LOG(FATAL) << "Unimplemented local type " << store->InputAt(1)->GetType();
423 }
424 store->SetLocations(locations);
425}
426
427void InstructionCodeGeneratorX86_64::VisitStoreLocal(HStoreLocal* store) {
428}
429
Dave Allison20dfc792014-06-16 20:44:29 -0700430void LocationsBuilderX86_64::VisitCondition(HCondition* comp) {
431 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(comp);
Nicolas Geoffrayecb2f9b2014-06-13 08:59:59 +0000432 locations->SetInAt(0, Location::RequiresRegister());
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100433 locations->SetInAt(1, Location::Any());
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100434 if (comp->NeedsMaterialization()) {
435 locations->SetOut(Location::RequiresRegister());
436 }
Dave Allison20dfc792014-06-16 20:44:29 -0700437 comp->SetLocations(locations);
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100438}
439
Dave Allison20dfc792014-06-16 20:44:29 -0700440void InstructionCodeGeneratorX86_64::VisitCondition(HCondition* comp) {
441 if (comp->NeedsMaterialization()) {
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100442 LocationSummary* locations = comp->GetLocations();
443 if (locations->InAt(1).IsRegister()) {
444 __ cmpq(locations->InAt(0).AsX86_64().AsCpuRegister(),
445 locations->InAt(1).AsX86_64().AsCpuRegister());
446 } else if (locations->InAt(1).IsConstant()) {
447 __ cmpq(locations->InAt(0).AsX86_64().AsCpuRegister(),
448 Immediate(locations->InAt(1).GetConstant()->AsIntConstant()->GetValue()));
449 } else {
450 __ cmpq(locations->InAt(0).AsX86_64().AsCpuRegister(),
451 Address(CpuRegister(RSP), locations->InAt(1).GetStackIndex()));
452 }
Dave Allison20dfc792014-06-16 20:44:29 -0700453 __ setcc(X86_64Condition(comp->GetCondition()),
454 comp->GetLocations()->Out().AsX86_64().AsCpuRegister());
455 }
456}
457
458void LocationsBuilderX86_64::VisitEqual(HEqual* comp) {
459 VisitCondition(comp);
460}
461
462void InstructionCodeGeneratorX86_64::VisitEqual(HEqual* comp) {
463 VisitCondition(comp);
464}
465
466void LocationsBuilderX86_64::VisitNotEqual(HNotEqual* comp) {
467 VisitCondition(comp);
468}
469
470void InstructionCodeGeneratorX86_64::VisitNotEqual(HNotEqual* comp) {
471 VisitCondition(comp);
472}
473
474void LocationsBuilderX86_64::VisitLessThan(HLessThan* comp) {
475 VisitCondition(comp);
476}
477
478void InstructionCodeGeneratorX86_64::VisitLessThan(HLessThan* comp) {
479 VisitCondition(comp);
480}
481
482void LocationsBuilderX86_64::VisitLessThanOrEqual(HLessThanOrEqual* comp) {
483 VisitCondition(comp);
484}
485
486void InstructionCodeGeneratorX86_64::VisitLessThanOrEqual(HLessThanOrEqual* comp) {
487 VisitCondition(comp);
488}
489
490void LocationsBuilderX86_64::VisitGreaterThan(HGreaterThan* comp) {
491 VisitCondition(comp);
492}
493
494void InstructionCodeGeneratorX86_64::VisitGreaterThan(HGreaterThan* comp) {
495 VisitCondition(comp);
496}
497
498void LocationsBuilderX86_64::VisitGreaterThanOrEqual(HGreaterThanOrEqual* comp) {
499 VisitCondition(comp);
500}
501
502void InstructionCodeGeneratorX86_64::VisitGreaterThanOrEqual(HGreaterThanOrEqual* comp) {
503 VisitCondition(comp);
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100504}
505
Nicolas Geoffray412f10c2014-06-19 10:00:34 +0100506void LocationsBuilderX86_64::VisitCompare(HCompare* compare) {
507 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(compare);
508 locations->SetInAt(0, Location::RequiresRegister());
509 locations->SetInAt(1, Location::RequiresRegister());
510 locations->SetOut(Location::RequiresRegister());
511 compare->SetLocations(locations);
512}
513
514void InstructionCodeGeneratorX86_64::VisitCompare(HCompare* compare) {
515 Label greater, done;
516 LocationSummary* locations = compare->GetLocations();
517 switch (compare->InputAt(0)->GetType()) {
518 case Primitive::kPrimLong:
519 __ cmpq(locations->InAt(0).AsX86_64().AsCpuRegister(),
520 locations->InAt(1).AsX86_64().AsCpuRegister());
521 break;
522 default:
523 LOG(FATAL) << "Unimplemented compare type " << compare->InputAt(0)->GetType();
524 }
525
526 __ movl(locations->Out().AsX86_64().AsCpuRegister(), Immediate(0));
527 __ j(kEqual, &done);
528 __ j(kGreater, &greater);
529
530 __ movl(locations->Out().AsX86_64().AsCpuRegister(), Immediate(-1));
531 __ jmp(&done);
532
533 __ Bind(&greater);
534 __ movl(locations->Out().AsX86_64().AsCpuRegister(), Immediate(1));
535
536 __ Bind(&done);
537}
538
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100539void LocationsBuilderX86_64::VisitIntConstant(HIntConstant* constant) {
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100540 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(constant);
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100541 locations->SetOut(Location::ConstantLocation(constant));
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100542 constant->SetLocations(locations);
543}
544
545void InstructionCodeGeneratorX86_64::VisitIntConstant(HIntConstant* constant) {
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100546}
547
548void LocationsBuilderX86_64::VisitLongConstant(HLongConstant* constant) {
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100549 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(constant);
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100550 locations->SetOut(Location::ConstantLocation(constant));
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100551 constant->SetLocations(locations);
552}
553
554void InstructionCodeGeneratorX86_64::VisitLongConstant(HLongConstant* constant) {
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100555}
556
557void LocationsBuilderX86_64::VisitReturnVoid(HReturnVoid* ret) {
558 ret->SetLocations(nullptr);
559}
560
561void InstructionCodeGeneratorX86_64::VisitReturnVoid(HReturnVoid* ret) {
562 codegen_->GenerateFrameExit();
563 __ ret();
564}
565
566void LocationsBuilderX86_64::VisitReturn(HReturn* ret) {
567 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(ret);
568 switch (ret->InputAt(0)->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 case Primitive::kPrimLong:
576 locations->SetInAt(0, X86_64CpuLocation(RAX));
577 break;
578
579 default:
580 LOG(FATAL) << "Unimplemented return type " << ret->InputAt(0)->GetType();
581 }
582 ret->SetLocations(locations);
583}
584
585void InstructionCodeGeneratorX86_64::VisitReturn(HReturn* ret) {
586 if (kIsDebugBuild) {
587 switch (ret->InputAt(0)->GetType()) {
588 case Primitive::kPrimBoolean:
589 case Primitive::kPrimByte:
590 case Primitive::kPrimChar:
591 case Primitive::kPrimShort:
592 case Primitive::kPrimInt:
593 case Primitive::kPrimNot:
594 case Primitive::kPrimLong:
595 DCHECK_EQ(ret->GetLocations()->InAt(0).AsX86_64().AsCpuRegister().AsRegister(), RAX);
596 break;
597
598 default:
599 LOG(FATAL) << "Unimplemented return type " << ret->InputAt(0)->GetType();
600 }
601 }
602 codegen_->GenerateFrameExit();
603 __ ret();
604}
605
606static constexpr Register kRuntimeParameterCoreRegisters[] = { RDI, RSI, RDX };
607static constexpr size_t kRuntimeParameterCoreRegistersLength =
608 arraysize(kRuntimeParameterCoreRegisters);
609
610class InvokeRuntimeCallingConvention : public CallingConvention<Register> {
611 public:
612 InvokeRuntimeCallingConvention()
613 : CallingConvention(kRuntimeParameterCoreRegisters,
614 kRuntimeParameterCoreRegistersLength) {}
615
616 private:
617 DISALLOW_COPY_AND_ASSIGN(InvokeRuntimeCallingConvention);
618};
619
620Location InvokeDexCallingConventionVisitor::GetNextLocation(Primitive::Type type) {
621 switch (type) {
622 case Primitive::kPrimBoolean:
623 case Primitive::kPrimByte:
624 case Primitive::kPrimChar:
625 case Primitive::kPrimShort:
626 case Primitive::kPrimInt:
627 case Primitive::kPrimNot: {
628 uint32_t index = gp_index_++;
629 stack_index_++;
630 if (index < calling_convention.GetNumberOfRegisters()) {
631 return X86_64CpuLocation(calling_convention.GetRegisterAt(index));
632 } else {
633 return Location::StackSlot(calling_convention.GetStackOffsetOf(stack_index_ - 1));
634 }
635 }
636
637 case Primitive::kPrimLong: {
638 uint32_t index = gp_index_;
639 stack_index_ += 2;
640 if (index < calling_convention.GetNumberOfRegisters()) {
641 gp_index_ += 1;
642 return X86_64CpuLocation(calling_convention.GetRegisterAt(index));
643 } else {
644 gp_index_ += 2;
645 return Location::DoubleStackSlot(calling_convention.GetStackOffsetOf(stack_index_ - 2));
646 }
647 }
648
649 case Primitive::kPrimDouble:
650 case Primitive::kPrimFloat:
651 LOG(FATAL) << "Unimplemented parameter type " << type;
652 break;
653
654 case Primitive::kPrimVoid:
655 LOG(FATAL) << "Unexpected parameter type " << type;
656 break;
657 }
658 return Location();
659}
660
661void LocationsBuilderX86_64::VisitInvokeStatic(HInvokeStatic* invoke) {
Nicolas Geoffrayf12feb82014-07-17 18:32:41 +0100662 codegen_->MarkNotLeaf();
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100663 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(invoke);
664 locations->AddTemp(X86_64CpuLocation(RDI));
665
666 InvokeDexCallingConventionVisitor calling_convention_visitor;
667 for (size_t i = 0; i < invoke->InputCount(); ++i) {
668 HInstruction* input = invoke->InputAt(i);
669 locations->SetInAt(i, calling_convention_visitor.GetNextLocation(input->GetType()));
670 }
671
672 switch (invoke->GetType()) {
673 case Primitive::kPrimBoolean:
674 case Primitive::kPrimByte:
675 case Primitive::kPrimChar:
676 case Primitive::kPrimShort:
677 case Primitive::kPrimInt:
678 case Primitive::kPrimNot:
679 case Primitive::kPrimLong:
680 locations->SetOut(X86_64CpuLocation(RAX));
681 break;
682
683 case Primitive::kPrimVoid:
684 break;
685
686 case Primitive::kPrimDouble:
687 case Primitive::kPrimFloat:
688 LOG(FATAL) << "Unimplemented return type " << invoke->GetType();
689 break;
690 }
691
692 invoke->SetLocations(locations);
693}
694
695void InstructionCodeGeneratorX86_64::VisitInvokeStatic(HInvokeStatic* invoke) {
696 CpuRegister temp = invoke->GetLocations()->GetTemp(0).AsX86_64().AsCpuRegister();
697 uint32_t heap_reference_size = sizeof(mirror::HeapReference<mirror::Object>);
698 size_t index_in_cache = mirror::Array::DataOffset(heap_reference_size).SizeValue() +
699 invoke->GetIndexInDexCache() * heap_reference_size;
700
701 // TODO: Implement all kinds of calls:
702 // 1) boot -> boot
703 // 2) app -> boot
704 // 3) app -> app
705 //
706 // Currently we implement the app -> app logic, which looks up in the resolve cache.
707
708 // temp = method;
709 LoadCurrentMethod(temp);
710 // temp = temp->dex_cache_resolved_methods_;
711 __ movl(temp, Address(temp, mirror::ArtMethod::DexCacheResolvedMethodsOffset().SizeValue()));
712 // temp = temp[index_in_cache]
713 __ movl(temp, Address(temp, index_in_cache));
714 // (temp + offset_of_quick_compiled_code)()
715 __ call(Address(temp, mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset().SizeValue()));
716
Nicolas Geoffrayf12feb82014-07-17 18:32:41 +0100717 DCHECK(!codegen_->IsLeafMethod());
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100718 codegen_->RecordPcInfo(invoke->GetDexPc());
719}
720
721void LocationsBuilderX86_64::VisitAdd(HAdd* add) {
722 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(add);
723 switch (add->GetResultType()) {
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100724 case Primitive::kPrimInt: {
725 locations->SetInAt(0, Location::RequiresRegister());
726 locations->SetInAt(1, Location::Any());
727 locations->SetOut(Location::SameAsFirstInput());
728 break;
729 }
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100730 case Primitive::kPrimLong: {
Nicolas Geoffrayecb2f9b2014-06-13 08:59:59 +0000731 locations->SetInAt(0, Location::RequiresRegister());
732 locations->SetInAt(1, Location::RequiresRegister());
733 locations->SetOut(Location::SameAsFirstInput());
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100734 break;
735 }
736
737 case Primitive::kPrimBoolean:
738 case Primitive::kPrimByte:
739 case Primitive::kPrimChar:
740 case Primitive::kPrimShort:
741 LOG(FATAL) << "Unexpected add type " << add->GetResultType();
742 break;
743
744 default:
745 LOG(FATAL) << "Unimplemented add type " << add->GetResultType();
746 }
747 add->SetLocations(locations);
748}
749
750void InstructionCodeGeneratorX86_64::VisitAdd(HAdd* add) {
751 LocationSummary* locations = add->GetLocations();
Nicolas Geoffrayecb2f9b2014-06-13 08:59:59 +0000752 DCHECK_EQ(locations->InAt(0).AsX86_64().AsCpuRegister().AsRegister(),
753 locations->Out().AsX86_64().AsCpuRegister().AsRegister());
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100754 switch (add->GetResultType()) {
Nicolas Geoffrayecb2f9b2014-06-13 08:59:59 +0000755 case Primitive::kPrimInt: {
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100756 if (locations->InAt(1).IsRegister()) {
757 __ addl(locations->InAt(0).AsX86_64().AsCpuRegister(),
758 locations->InAt(1).AsX86_64().AsCpuRegister());
759 } else if (locations->InAt(1).IsConstant()) {
760 HConstant* instruction = locations->InAt(1).GetConstant();
761 Immediate imm(instruction->AsIntConstant()->GetValue());
762 __ addl(locations->InAt(0).AsX86_64().AsCpuRegister(), imm);
763 } else {
764 __ addl(locations->InAt(0).AsX86_64().AsCpuRegister(),
765 Address(CpuRegister(RSP), locations->InAt(1).GetStackIndex()));
766 }
Nicolas Geoffrayecb2f9b2014-06-13 08:59:59 +0000767 break;
768 }
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100769 case Primitive::kPrimLong: {
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100770 __ addq(locations->InAt(0).AsX86_64().AsCpuRegister(),
771 locations->InAt(1).AsX86_64().AsCpuRegister());
772 break;
773 }
774
775 case Primitive::kPrimBoolean:
776 case Primitive::kPrimByte:
777 case Primitive::kPrimChar:
778 case Primitive::kPrimShort:
779 LOG(FATAL) << "Unexpected add type " << add->GetResultType();
780 break;
781
782 default:
783 LOG(FATAL) << "Unimplemented add type " << add->GetResultType();
784 }
785}
786
787void LocationsBuilderX86_64::VisitSub(HSub* sub) {
788 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(sub);
789 switch (sub->GetResultType()) {
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100790 case Primitive::kPrimInt: {
791 locations->SetInAt(0, Location::RequiresRegister());
792 locations->SetInAt(1, Location::Any());
793 locations->SetOut(Location::SameAsFirstInput());
794 break;
795 }
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100796 case Primitive::kPrimLong: {
Nicolas Geoffrayecb2f9b2014-06-13 08:59:59 +0000797 locations->SetInAt(0, Location::RequiresRegister());
798 locations->SetInAt(1, Location::RequiresRegister());
799 locations->SetOut(Location::SameAsFirstInput());
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100800 break;
801 }
802
803 case Primitive::kPrimBoolean:
804 case Primitive::kPrimByte:
805 case Primitive::kPrimChar:
806 case Primitive::kPrimShort:
807 LOG(FATAL) << "Unexpected sub type " << sub->GetResultType();
808 break;
809
810 default:
811 LOG(FATAL) << "Unimplemented sub type " << sub->GetResultType();
812 }
813 sub->SetLocations(locations);
814}
815
816void InstructionCodeGeneratorX86_64::VisitSub(HSub* sub) {
817 LocationSummary* locations = sub->GetLocations();
Nicolas Geoffrayecb2f9b2014-06-13 08:59:59 +0000818 DCHECK_EQ(locations->InAt(0).AsX86_64().AsCpuRegister().AsRegister(),
819 locations->Out().AsX86_64().AsCpuRegister().AsRegister());
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100820 switch (sub->GetResultType()) {
Nicolas Geoffrayecb2f9b2014-06-13 08:59:59 +0000821 case Primitive::kPrimInt: {
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100822 if (locations->InAt(1).IsRegister()) {
823 __ subl(locations->InAt(0).AsX86_64().AsCpuRegister(),
824 locations->InAt(1).AsX86_64().AsCpuRegister());
825 } else if (locations->InAt(1).IsConstant()) {
826 HConstant* instruction = locations->InAt(1).GetConstant();
827 Immediate imm(instruction->AsIntConstant()->GetValue());
828 __ subl(locations->InAt(0).AsX86_64().AsCpuRegister(), imm);
829 } else {
830 __ subl(locations->InAt(0).AsX86_64().AsCpuRegister(),
831 Address(CpuRegister(RSP), locations->InAt(1).GetStackIndex()));
832 }
Nicolas Geoffrayecb2f9b2014-06-13 08:59:59 +0000833 break;
834 }
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100835 case Primitive::kPrimLong: {
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100836 __ subq(locations->InAt(0).AsX86_64().AsCpuRegister(),
837 locations->InAt(1).AsX86_64().AsCpuRegister());
838 break;
839 }
840
841 case Primitive::kPrimBoolean:
842 case Primitive::kPrimByte:
843 case Primitive::kPrimChar:
844 case Primitive::kPrimShort:
845 LOG(FATAL) << "Unexpected sub type " << sub->GetResultType();
846 break;
847
848 default:
849 LOG(FATAL) << "Unimplemented sub type " << sub->GetResultType();
850 }
851}
852
853void LocationsBuilderX86_64::VisitNewInstance(HNewInstance* instruction) {
Nicolas Geoffrayf12feb82014-07-17 18:32:41 +0100854 codegen_->MarkNotLeaf();
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100855 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
856 locations->SetOut(X86_64CpuLocation(RAX));
857 instruction->SetLocations(locations);
858}
859
860void InstructionCodeGeneratorX86_64::VisitNewInstance(HNewInstance* instruction) {
861 InvokeRuntimeCallingConvention calling_convention;
862 LoadCurrentMethod(CpuRegister(calling_convention.GetRegisterAt(1)));
863 __ movq(CpuRegister(calling_convention.GetRegisterAt(0)), Immediate(instruction->GetTypeIndex()));
864
865 __ gs()->call(Address::Absolute(
866 QUICK_ENTRYPOINT_OFFSET(kX86_64WordSize, pAllocObjectWithAccessCheck), true));
867
Nicolas Geoffrayf12feb82014-07-17 18:32:41 +0100868 DCHECK(!codegen_->IsLeafMethod());
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100869 codegen_->RecordPcInfo(instruction->GetDexPc());
870}
871
872void LocationsBuilderX86_64::VisitParameterValue(HParameterValue* instruction) {
873 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
874 Location location = parameter_visitor_.GetNextLocation(instruction->GetType());
875 if (location.IsStackSlot()) {
876 location = Location::StackSlot(location.GetStackIndex() + codegen_->GetFrameSize());
877 } else if (location.IsDoubleStackSlot()) {
878 location = Location::DoubleStackSlot(location.GetStackIndex() + codegen_->GetFrameSize());
879 }
880 locations->SetOut(location);
881 instruction->SetLocations(locations);
882}
883
884void InstructionCodeGeneratorX86_64::VisitParameterValue(HParameterValue* instruction) {
885 // Nothing to do, the parameter is already at its location.
886}
887
888void LocationsBuilderX86_64::VisitNot(HNot* instruction) {
889 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
Nicolas Geoffrayecb2f9b2014-06-13 08:59:59 +0000890 locations->SetInAt(0, Location::RequiresRegister());
891 locations->SetOut(Location::SameAsFirstInput());
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100892 instruction->SetLocations(locations);
893}
894
895void InstructionCodeGeneratorX86_64::VisitNot(HNot* instruction) {
896 LocationSummary* locations = instruction->GetLocations();
897 DCHECK_EQ(locations->InAt(0).AsX86_64().AsCpuRegister().AsRegister(),
898 locations->Out().AsX86_64().AsCpuRegister().AsRegister());
899 __ xorq(locations->Out().AsX86_64().AsCpuRegister(), Immediate(1));
900}
901
902void LocationsBuilderX86_64::VisitPhi(HPhi* instruction) {
903 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
904 for (size_t i = 0, e = instruction->InputCount(); i < e; ++i) {
905 locations->SetInAt(i, Location::Any());
906 }
907 locations->SetOut(Location::Any());
908 instruction->SetLocations(locations);
909}
910
911void InstructionCodeGeneratorX86_64::VisitPhi(HPhi* instruction) {
912 LOG(FATAL) << "Unimplemented";
913}
914
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100915void LocationsBuilderX86_64::VisitInstanceFieldSet(HInstanceFieldSet* instruction) {
916 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
917 locations->SetInAt(0, Location::RequiresRegister());
918 locations->SetInAt(1, Location::RequiresRegister());
Nicolas Geoffray1a43dd72014-07-17 15:15:34 +0100919 // Temporary registers for the write barrier.
920 if (instruction->InputAt(1)->GetType() == Primitive::kPrimNot) {
921 locations->AddTemp(Location::RequiresRegister());
922 locations->AddTemp(Location::RequiresRegister());
923 }
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100924 instruction->SetLocations(locations);
925}
926
927void InstructionCodeGeneratorX86_64::VisitInstanceFieldSet(HInstanceFieldSet* instruction) {
928 LocationSummary* locations = instruction->GetLocations();
929 CpuRegister obj = locations->InAt(0).AsX86_64().AsCpuRegister();
930 CpuRegister value = locations->InAt(1).AsX86_64().AsCpuRegister();
931 size_t offset = instruction->GetFieldOffset().SizeValue();
932 Primitive::Type field_type = instruction->InputAt(1)->GetType();
933
934 switch (field_type) {
935 case Primitive::kPrimBoolean:
936 case Primitive::kPrimByte: {
937 __ movb(Address(obj, offset), value);
938 break;
939 }
940
941 case Primitive::kPrimShort:
942 case Primitive::kPrimChar: {
943 __ movw(Address(obj, offset), value);
944 break;
945 }
946
Nicolas Geoffray1a43dd72014-07-17 15:15:34 +0100947 case Primitive::kPrimInt: {
948 __ movl(Address(obj, offset), value);
949 break;
950 }
951
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100952 case Primitive::kPrimNot: {
953 __ movl(Address(obj, offset), value);
Nicolas Geoffray1a43dd72014-07-17 15:15:34 +0100954 Label is_null;
955 CpuRegister temp = locations->GetTemp(0).AsX86_64().AsCpuRegister();
956 CpuRegister card = locations->GetTemp(1).AsX86_64().AsCpuRegister();
957 __ testl(value, value);
958 __ j(kEqual, &is_null);
959 __ gs()->movq(card, Address::Absolute(
960 Thread::CardTableOffset<kX86_64WordSize>().Int32Value(), true));
961 __ movq(temp, obj);
962 __ shrq(temp, Immediate(gc::accounting::CardTable::kCardShift));
963 __ movb(Address(temp, card, TIMES_1, 0), card);
964 __ Bind(&is_null);
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100965 break;
966 }
967
968 case Primitive::kPrimLong: {
969 __ movq(Address(obj, offset), value);
970 break;
971 }
972
973 case Primitive::kPrimFloat:
974 case Primitive::kPrimDouble:
975 LOG(FATAL) << "Unimplemented register type " << field_type;
976
977 case Primitive::kPrimVoid:
978 LOG(FATAL) << "Unreachable type " << field_type;
979 }
980}
981
982void LocationsBuilderX86_64::VisitInstanceFieldGet(HInstanceFieldGet* instruction) {
983 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
984 locations->SetInAt(0, Location::RequiresRegister());
985 locations->SetOut(Location::RequiresRegister());
986 instruction->SetLocations(locations);
987}
988
989void InstructionCodeGeneratorX86_64::VisitInstanceFieldGet(HInstanceFieldGet* instruction) {
990 LocationSummary* locations = instruction->GetLocations();
991 CpuRegister obj = locations->InAt(0).AsX86_64().AsCpuRegister();
992 CpuRegister out = locations->Out().AsX86_64().AsCpuRegister();
993 size_t offset = instruction->GetFieldOffset().SizeValue();
994
995 switch (instruction->GetType()) {
996 case Primitive::kPrimBoolean: {
997 __ movzxb(out, Address(obj, offset));
998 break;
999 }
1000
1001 case Primitive::kPrimByte: {
1002 __ movsxb(out, Address(obj, offset));
1003 break;
1004 }
1005
1006 case Primitive::kPrimShort: {
1007 __ movsxw(out, Address(obj, offset));
1008 break;
1009 }
1010
1011 case Primitive::kPrimChar: {
1012 __ movzxw(out, Address(obj, offset));
1013 break;
1014 }
1015
1016 case Primitive::kPrimInt:
1017 case Primitive::kPrimNot: {
1018 __ movl(out, Address(obj, offset));
1019 break;
1020 }
1021
1022 case Primitive::kPrimLong: {
1023 __ movq(out, Address(obj, offset));
1024 break;
1025 }
1026
1027 case Primitive::kPrimFloat:
1028 case Primitive::kPrimDouble:
1029 LOG(FATAL) << "Unimplemented register type " << instruction->GetType();
1030
1031 case Primitive::kPrimVoid:
1032 LOG(FATAL) << "Unreachable type " << instruction->GetType();
1033 }
1034}
1035
1036void LocationsBuilderX86_64::VisitNullCheck(HNullCheck* instruction) {
1037 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
1038 locations->SetInAt(0, Location::Any());
1039 // TODO: Have a normalization phase that makes this instruction never used.
1040 locations->SetOut(Location::SameAsFirstInput());
1041 instruction->SetLocations(locations);
1042}
1043
1044void InstructionCodeGeneratorX86_64::VisitNullCheck(HNullCheck* instruction) {
1045 SlowPathCode* slow_path =
1046 new (GetGraph()->GetArena()) NullCheckSlowPathX86_64(instruction->GetDexPc());
1047 codegen_->AddSlowPath(slow_path);
1048
1049 LocationSummary* locations = instruction->GetLocations();
1050 Location obj = locations->InAt(0);
1051 DCHECK(obj.Equals(locations->Out()));
1052
1053 if (obj.IsRegister()) {
1054 __ cmpl(obj.AsX86_64().AsCpuRegister(), Immediate(0));
1055 } else {
1056 DCHECK(locations->InAt(0).IsStackSlot());
1057 __ cmpl(Address(CpuRegister(RSP), obj.GetStackIndex()), Immediate(0));
1058 }
1059 __ j(kEqual, slow_path->GetEntryLabel());
1060}
1061
1062void LocationsBuilderX86_64::VisitTemporary(HTemporary* temp) {
1063 temp->SetLocations(nullptr);
1064}
1065
1066void InstructionCodeGeneratorX86_64::VisitTemporary(HTemporary* temp) {
1067 // Nothing to do, this is driven by the code generator.
1068}
1069
Nicolas Geoffray9cf35522014-06-09 18:40:10 +01001070void LocationsBuilderX86_64::VisitParallelMove(HParallelMove* instruction) {
1071 LOG(FATAL) << "Unimplemented";
1072}
1073
1074void InstructionCodeGeneratorX86_64::VisitParallelMove(HParallelMove* instruction) {
Nicolas Geoffrayecb2f9b2014-06-13 08:59:59 +00001075 codegen_->GetMoveResolver()->EmitNativeCode(instruction);
1076}
1077
1078X86_64Assembler* ParallelMoveResolverX86_64::GetAssembler() const {
1079 return codegen_->GetAssembler();
1080}
1081
1082void ParallelMoveResolverX86_64::EmitMove(size_t index) {
1083 MoveOperands* move = moves_.Get(index);
1084 Location source = move->GetSource();
1085 Location destination = move->GetDestination();
1086
1087 if (source.IsRegister()) {
1088 if (destination.IsRegister()) {
1089 __ movq(destination.AsX86_64().AsCpuRegister(), source.AsX86_64().AsCpuRegister());
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01001090 } else if (destination.IsStackSlot()) {
Nicolas Geoffrayecb2f9b2014-06-13 08:59:59 +00001091 __ movl(Address(CpuRegister(RSP), destination.GetStackIndex()),
1092 source.AsX86_64().AsCpuRegister());
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01001093 } else {
1094 DCHECK(destination.IsDoubleStackSlot());
1095 __ movq(Address(CpuRegister(RSP), destination.GetStackIndex()),
1096 source.AsX86_64().AsCpuRegister());
Nicolas Geoffrayecb2f9b2014-06-13 08:59:59 +00001097 }
1098 } else if (source.IsStackSlot()) {
1099 if (destination.IsRegister()) {
1100 __ movl(destination.AsX86_64().AsX86_64().AsCpuRegister(),
1101 Address(CpuRegister(RSP), source.GetStackIndex()));
1102 } else {
1103 DCHECK(destination.IsStackSlot());
1104 __ movl(CpuRegister(TMP), Address(CpuRegister(RSP), source.GetStackIndex()));
1105 __ movl(Address(CpuRegister(RSP), destination.GetStackIndex()), CpuRegister(TMP));
1106 }
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01001107 } else if (source.IsDoubleStackSlot()) {
1108 if (destination.IsRegister()) {
1109 __ movq(destination.AsX86_64().AsX86_64().AsCpuRegister(),
1110 Address(CpuRegister(RSP), source.GetStackIndex()));
1111 } else {
1112 DCHECK(destination.IsDoubleStackSlot());
1113 __ movq(CpuRegister(TMP), Address(CpuRegister(RSP), source.GetStackIndex()));
1114 __ movq(Address(CpuRegister(RSP), destination.GetStackIndex()), CpuRegister(TMP));
1115 }
Nicolas Geoffray96f89a22014-07-11 10:57:49 +01001116 } else if (source.IsConstant()) {
1117 HConstant* constant = source.GetConstant();
1118 if (constant->IsIntConstant()) {
1119 Immediate imm(constant->AsIntConstant()->GetValue());
1120 if (destination.IsRegister()) {
1121 __ movl(destination.AsX86_64().AsCpuRegister(), imm);
1122 } else {
1123 __ movl(Address(CpuRegister(RSP), destination.GetStackIndex()), imm);
1124 }
1125 } else if (constant->IsLongConstant()) {
1126 int64_t value = constant->AsLongConstant()->GetValue();
1127 if (destination.IsRegister()) {
1128 __ movq(destination.AsX86_64().AsCpuRegister(), Immediate(value));
1129 } else {
1130 __ movq(CpuRegister(TMP), Immediate(value));
1131 __ movq(Address(CpuRegister(RSP), destination.GetStackIndex()), CpuRegister(TMP));
1132 }
1133 } else {
1134 LOG(FATAL) << "Unimplemented constant type";
1135 }
Nicolas Geoffrayecb2f9b2014-06-13 08:59:59 +00001136 } else {
1137 LOG(FATAL) << "Unimplemented";
1138 }
1139}
1140
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01001141void ParallelMoveResolverX86_64::Exchange32(CpuRegister reg, int mem) {
Nicolas Geoffrayecb2f9b2014-06-13 08:59:59 +00001142 __ movl(CpuRegister(TMP), Address(CpuRegister(RSP), mem));
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01001143 __ movl(Address(CpuRegister(RSP), mem), reg);
1144 __ movl(reg, CpuRegister(TMP));
Nicolas Geoffrayecb2f9b2014-06-13 08:59:59 +00001145}
1146
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01001147void ParallelMoveResolverX86_64::Exchange32(int mem1, int mem2) {
Nicolas Geoffrayecb2f9b2014-06-13 08:59:59 +00001148 ScratchRegisterScope ensure_scratch(
1149 this, TMP, RAX, codegen_->GetNumberOfCoreRegisters());
1150
1151 int stack_offset = ensure_scratch.IsSpilled() ? kX86_64WordSize : 0;
1152 __ movl(CpuRegister(TMP), Address(CpuRegister(RSP), mem1 + stack_offset));
1153 __ movl(CpuRegister(ensure_scratch.GetRegister()),
1154 Address(CpuRegister(RSP), mem2 + stack_offset));
1155 __ movl(Address(CpuRegister(RSP), mem2 + stack_offset), CpuRegister(TMP));
1156 __ movl(Address(CpuRegister(RSP), mem1 + stack_offset),
1157 CpuRegister(ensure_scratch.GetRegister()));
1158}
1159
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01001160void ParallelMoveResolverX86_64::Exchange64(CpuRegister reg, int mem) {
1161 __ movq(CpuRegister(TMP), Address(CpuRegister(RSP), mem));
1162 __ movq(Address(CpuRegister(RSP), mem), reg);
1163 __ movq(reg, CpuRegister(TMP));
1164}
1165
1166void ParallelMoveResolverX86_64::Exchange64(int mem1, int mem2) {
1167 ScratchRegisterScope ensure_scratch(
1168 this, TMP, RAX, codegen_->GetNumberOfCoreRegisters());
1169
1170 int stack_offset = ensure_scratch.IsSpilled() ? kX86_64WordSize : 0;
1171 __ movq(CpuRegister(TMP), Address(CpuRegister(RSP), mem1 + stack_offset));
1172 __ movq(CpuRegister(ensure_scratch.GetRegister()),
1173 Address(CpuRegister(RSP), mem2 + stack_offset));
1174 __ movq(Address(CpuRegister(RSP), mem2 + stack_offset), CpuRegister(TMP));
1175 __ movq(Address(CpuRegister(RSP), mem1 + stack_offset),
1176 CpuRegister(ensure_scratch.GetRegister()));
1177}
1178
Nicolas Geoffrayecb2f9b2014-06-13 08:59:59 +00001179void ParallelMoveResolverX86_64::EmitSwap(size_t index) {
1180 MoveOperands* move = moves_.Get(index);
1181 Location source = move->GetSource();
1182 Location destination = move->GetDestination();
1183
1184 if (source.IsRegister() && destination.IsRegister()) {
1185 __ xchgq(destination.AsX86_64().AsCpuRegister(), source.AsX86_64().AsCpuRegister());
1186 } else if (source.IsRegister() && destination.IsStackSlot()) {
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01001187 Exchange32(source.AsX86_64().AsCpuRegister(), destination.GetStackIndex());
Nicolas Geoffrayecb2f9b2014-06-13 08:59:59 +00001188 } else if (source.IsStackSlot() && destination.IsRegister()) {
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01001189 Exchange32(destination.AsX86_64().AsCpuRegister(), source.GetStackIndex());
Nicolas Geoffrayecb2f9b2014-06-13 08:59:59 +00001190 } else if (source.IsStackSlot() && destination.IsStackSlot()) {
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01001191 Exchange32(destination.GetStackIndex(), source.GetStackIndex());
1192 } else if (source.IsRegister() && destination.IsDoubleStackSlot()) {
1193 Exchange64(source.AsX86_64().AsCpuRegister(), destination.GetStackIndex());
1194 } else if (source.IsDoubleStackSlot() && destination.IsRegister()) {
1195 Exchange64(destination.AsX86_64().AsCpuRegister(), source.GetStackIndex());
1196 } else if (source.IsDoubleStackSlot() && destination.IsDoubleStackSlot()) {
1197 Exchange64(destination.GetStackIndex(), source.GetStackIndex());
Nicolas Geoffrayecb2f9b2014-06-13 08:59:59 +00001198 } else {
1199 LOG(FATAL) << "Unimplemented";
1200 }
1201}
1202
1203
1204void ParallelMoveResolverX86_64::SpillScratch(int reg) {
1205 __ pushq(CpuRegister(reg));
1206}
1207
1208
1209void ParallelMoveResolverX86_64::RestoreScratch(int reg) {
1210 __ popq(CpuRegister(reg));
Nicolas Geoffray9cf35522014-06-09 18:40:10 +01001211}
1212
1213} // namespace x86_64
1214} // namespace art