blob: bda352070897b303c2f1b15d5b34b9fbffc00471 [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"
Ian Rogers7e70b002014-10-08 11:47:24 -070021#include "mirror/array-inl.h"
Nicolas Geoffray9cf35522014-06-09 18:40:10 +010022#include "mirror/art_method.h"
Nicolas Geoffraye982f0b2014-08-13 02:11:24 +010023#include "mirror/class.h"
Nicolas Geoffray9cf35522014-06-09 18:40:10 +010024#include "mirror/object_reference.h"
25#include "thread.h"
26#include "utils/assembler.h"
Nicolas Geoffrayf12feb82014-07-17 18:32:41 +010027#include "utils/stack_checks.h"
Nicolas Geoffray9cf35522014-06-09 18:40:10 +010028#include "utils/x86_64/assembler_x86_64.h"
29#include "utils/x86_64/managed_register_x86_64.h"
30
Nicolas Geoffray9cf35522014-06-09 18:40:10 +010031namespace art {
32
Nicolas Geoffray9cf35522014-06-09 18:40:10 +010033namespace x86_64 {
34
Nicolas Geoffrayf6e206c2014-08-07 20:25:41 +010035static constexpr bool kExplicitStackOverflowCheck = false;
Nicolas Geoffrayf12feb82014-07-17 18:32:41 +010036
37// Some x86_64 instructions require a register to be available as temp.
38static constexpr Register TMP = R11;
39
40static constexpr int kNumberOfPushedRegistersAtEntry = 1;
41static constexpr int kCurrentMethodStackOffset = 0;
42
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +010043static constexpr Register kRuntimeParameterCoreRegisters[] = { RDI, RSI, RDX };
44static constexpr size_t kRuntimeParameterCoreRegistersLength =
45 arraysize(kRuntimeParameterCoreRegisters);
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +010046static constexpr FloatRegister kRuntimeParameterFpuRegisters[] = { };
47static constexpr size_t kRuntimeParameterFpuRegistersLength = 0;
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +010048
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +010049class InvokeRuntimeCallingConvention : public CallingConvention<Register, FloatRegister> {
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +010050 public:
51 InvokeRuntimeCallingConvention()
52 : CallingConvention(kRuntimeParameterCoreRegisters,
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +010053 kRuntimeParameterCoreRegistersLength,
54 kRuntimeParameterFpuRegisters,
55 kRuntimeParameterFpuRegistersLength) {}
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +010056
57 private:
58 DISALLOW_COPY_AND_ASSIGN(InvokeRuntimeCallingConvention);
59};
Nicolas Geoffrayf12feb82014-07-17 18:32:41 +010060
Nicolas Geoffraye5038322014-07-04 09:41:32 +010061#define __ reinterpret_cast<X86_64Assembler*>(codegen->GetAssembler())->
62
Nicolas Geoffray92a73ae2014-10-16 11:12:52 +010063class SlowPathCodeX86_64 : public SlowPathCode {
64 public:
65 SlowPathCodeX86_64() : entry_label_(), exit_label_() {}
66
67 Label* GetEntryLabel() { return &entry_label_; }
68 Label* GetExitLabel() { return &exit_label_; }
69
70 private:
71 Label entry_label_;
72 Label exit_label_;
73
74 DISALLOW_COPY_AND_ASSIGN(SlowPathCodeX86_64);
75};
76
77class NullCheckSlowPathX86_64 : public SlowPathCodeX86_64 {
Nicolas Geoffraye5038322014-07-04 09:41:32 +010078 public:
Nicolas Geoffray39468442014-09-02 15:17:15 +010079 explicit NullCheckSlowPathX86_64(HNullCheck* instruction) : instruction_(instruction) {}
Nicolas Geoffraye5038322014-07-04 09:41:32 +010080
81 virtual void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
82 __ Bind(GetEntryLabel());
Nicolas Geoffrayf12feb82014-07-17 18:32:41 +010083 __ gs()->call(
84 Address::Absolute(QUICK_ENTRYPOINT_OFFSET(kX86_64WordSize, pThrowNullPointer), true));
Nicolas Geoffray39468442014-09-02 15:17:15 +010085 codegen->RecordPcInfo(instruction_, instruction_->GetDexPc());
Nicolas Geoffraye5038322014-07-04 09:41:32 +010086 }
87
88 private:
Nicolas Geoffray39468442014-09-02 15:17:15 +010089 HNullCheck* const instruction_;
Nicolas Geoffraye5038322014-07-04 09:41:32 +010090 DISALLOW_COPY_AND_ASSIGN(NullCheckSlowPathX86_64);
91};
92
Nicolas Geoffray92a73ae2014-10-16 11:12:52 +010093class StackOverflowCheckSlowPathX86_64 : public SlowPathCodeX86_64 {
Nicolas Geoffrayf12feb82014-07-17 18:32:41 +010094 public:
95 StackOverflowCheckSlowPathX86_64() {}
96
97 virtual void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
98 __ Bind(GetEntryLabel());
99 __ addq(CpuRegister(RSP),
100 Immediate(codegen->GetFrameSize() - kNumberOfPushedRegistersAtEntry * kX86_64WordSize));
101 __ gs()->jmp(
102 Address::Absolute(QUICK_ENTRYPOINT_OFFSET(kX86_64WordSize, pThrowStackOverflow), true));
103 }
104
105 private:
106 DISALLOW_COPY_AND_ASSIGN(StackOverflowCheckSlowPathX86_64);
107};
108
Nicolas Geoffray92a73ae2014-10-16 11:12:52 +0100109class SuspendCheckSlowPathX86_64 : public SlowPathCodeX86_64 {
Nicolas Geoffrayfbc695f2014-09-15 15:33:30 +0000110 public:
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100111 explicit SuspendCheckSlowPathX86_64(HSuspendCheck* instruction, HBasicBlock* successor)
112 : instruction_(instruction), successor_(successor) {}
Nicolas Geoffrayfbc695f2014-09-15 15:33:30 +0000113
114 virtual void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
Nicolas Geoffray92a73ae2014-10-16 11:12:52 +0100115 CodeGeneratorX86_64* x64_codegen = down_cast<CodeGeneratorX86_64*>(codegen);
Nicolas Geoffrayfbc695f2014-09-15 15:33:30 +0000116 __ Bind(GetEntryLabel());
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +0100117 codegen->SaveLiveRegisters(instruction_->GetLocations());
Nicolas Geoffrayfbc695f2014-09-15 15:33:30 +0000118 __ gs()->call(Address::Absolute(QUICK_ENTRYPOINT_OFFSET(kX86_64WordSize, pTestSuspend), true));
119 codegen->RecordPcInfo(instruction_, instruction_->GetDexPc());
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +0100120 codegen->RestoreLiveRegisters(instruction_->GetLocations());
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100121 if (successor_ == nullptr) {
122 __ jmp(GetReturnLabel());
123 } else {
Nicolas Geoffray92a73ae2014-10-16 11:12:52 +0100124 __ jmp(x64_codegen->GetLabelOf(successor_));
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100125 }
Nicolas Geoffrayfbc695f2014-09-15 15:33:30 +0000126 }
127
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100128 Label* GetReturnLabel() {
129 DCHECK(successor_ == nullptr);
130 return &return_label_;
131 }
Nicolas Geoffrayfbc695f2014-09-15 15:33:30 +0000132
133 private:
134 HSuspendCheck* const instruction_;
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100135 HBasicBlock* const successor_;
Nicolas Geoffrayfbc695f2014-09-15 15:33:30 +0000136 Label return_label_;
137
138 DISALLOW_COPY_AND_ASSIGN(SuspendCheckSlowPathX86_64);
139};
140
Nicolas Geoffray92a73ae2014-10-16 11:12:52 +0100141class BoundsCheckSlowPathX86_64 : public SlowPathCodeX86_64 {
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +0100142 public:
Roland Levillain5799fc02014-09-25 12:15:20 +0100143 BoundsCheckSlowPathX86_64(HBoundsCheck* instruction,
144 Location index_location,
145 Location length_location)
Nicolas Geoffray39468442014-09-02 15:17:15 +0100146 : instruction_(instruction),
147 index_location_(index_location),
148 length_location_(length_location) {}
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +0100149
150 virtual void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
Nicolas Geoffray92a73ae2014-10-16 11:12:52 +0100151 CodeGeneratorX86_64* x64_codegen = down_cast<CodeGeneratorX86_64*>(codegen);
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +0100152 __ Bind(GetEntryLabel());
153 InvokeRuntimeCallingConvention calling_convention;
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +0100154 x64_codegen->Move(
155 Location::RegisterLocation(calling_convention.GetRegisterAt(0)), index_location_);
156 x64_codegen->Move(
157 Location::RegisterLocation(calling_convention.GetRegisterAt(1)), length_location_);
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +0100158 __ gs()->call(Address::Absolute(
159 QUICK_ENTRYPOINT_OFFSET(kX86_64WordSize, pThrowArrayBounds), true));
Nicolas Geoffray39468442014-09-02 15:17:15 +0100160 codegen->RecordPcInfo(instruction_, instruction_->GetDexPc());
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +0100161 }
162
163 private:
Nicolas Geoffray39468442014-09-02 15:17:15 +0100164 HBoundsCheck* const instruction_;
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +0100165 const Location index_location_;
166 const Location length_location_;
167
168 DISALLOW_COPY_AND_ASSIGN(BoundsCheckSlowPathX86_64);
169};
170
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +0100171class ClinitCheckSlowPathX86_64 : public SlowPathCodeX86_64 {
172 public:
173 explicit ClinitCheckSlowPathX86_64(HClinitCheck* instruction) : instruction_(instruction) {}
174
175 virtual void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
176 CodeGeneratorX86_64* x64_codegen = down_cast<CodeGeneratorX86_64*>(codegen);
177 __ Bind(GetEntryLabel());
178 codegen->SaveLiveRegisters(instruction_->GetLocations());
179
180 HLoadClass* cls = instruction_->GetLoadClass();
181 InvokeRuntimeCallingConvention calling_convention;
182 __ movl(CpuRegister(calling_convention.GetRegisterAt(0)), Immediate(cls->GetTypeIndex()));
183 x64_codegen->LoadCurrentMethod(CpuRegister(calling_convention.GetRegisterAt(1)));
184 __ gs()->call(Address::Absolute(
185 QUICK_ENTRYPOINT_OFFSET(kX86_64WordSize, pInitializeStaticStorage), true));
186
187 codegen->RecordPcInfo(instruction_, instruction_->GetDexPc());
188 x64_codegen->Move(instruction_->GetLocations()->InAt(0), Location::RegisterLocation(RAX));
189 codegen->RestoreLiveRegisters(instruction_->GetLocations());
190 __ jmp(GetExitLabel());
191 }
192
193 private:
194 HClinitCheck* const instruction_;
195
196 DISALLOW_COPY_AND_ASSIGN(ClinitCheckSlowPathX86_64);
197};
198
Nicolas Geoffrayb5f62b32014-10-30 10:58:41 +0000199class LoadStringSlowPathX86_64 : public SlowPathCodeX86_64 {
200 public:
201 explicit LoadStringSlowPathX86_64(HLoadString* instruction) : instruction_(instruction) {}
202
203 virtual void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
204 LocationSummary* locations = instruction_->GetLocations();
205 DCHECK(!locations->GetLiveRegisters()->ContainsCoreRegister(locations->Out().reg()));
206
207 CodeGeneratorX86_64* x64_codegen = down_cast<CodeGeneratorX86_64*>(codegen);
208 __ Bind(GetEntryLabel());
209 codegen->SaveLiveRegisters(locations);
210
211 InvokeRuntimeCallingConvention calling_convention;
212 x64_codegen->LoadCurrentMethod(CpuRegister(calling_convention.GetRegisterAt(0)));
213 __ movl(CpuRegister(calling_convention.GetRegisterAt(1)),
214 Immediate(instruction_->GetStringIndex()));
215 __ gs()->call(Address::Absolute(
216 QUICK_ENTRYPOINT_OFFSET(kX86_64WordSize, pResolveString), true));
217 codegen->RecordPcInfo(instruction_, instruction_->GetDexPc());
218 x64_codegen->Move(locations->Out(), Location::RegisterLocation(RAX));
219 codegen->RestoreLiveRegisters(locations);
220 __ jmp(GetExitLabel());
221 }
222
223 private:
224 HLoadString* const instruction_;
225
226 DISALLOW_COPY_AND_ASSIGN(LoadStringSlowPathX86_64);
227};
228
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100229#undef __
230#define __ reinterpret_cast<X86_64Assembler*>(GetAssembler())->
231
Dave Allison20dfc792014-06-16 20:44:29 -0700232inline Condition X86_64Condition(IfCondition cond) {
233 switch (cond) {
234 case kCondEQ: return kEqual;
235 case kCondNE: return kNotEqual;
236 case kCondLT: return kLess;
237 case kCondLE: return kLessEqual;
238 case kCondGT: return kGreater;
239 case kCondGE: return kGreaterEqual;
240 default:
241 LOG(FATAL) << "Unknown if condition";
242 }
243 return kEqual;
244}
245
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100246void CodeGeneratorX86_64::DumpCoreRegister(std::ostream& stream, int reg) const {
247 stream << X86_64ManagedRegister::FromCpuRegister(Register(reg));
248}
249
250void CodeGeneratorX86_64::DumpFloatingPointRegister(std::ostream& stream, int reg) const {
251 stream << X86_64ManagedRegister::FromXmmRegister(FloatRegister(reg));
252}
253
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100254size_t CodeGeneratorX86_64::SaveCoreRegister(size_t stack_index, uint32_t reg_id) {
255 __ movq(Address(CpuRegister(RSP), stack_index), CpuRegister(reg_id));
256 return kX86_64WordSize;
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +0100257}
258
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100259size_t CodeGeneratorX86_64::RestoreCoreRegister(size_t stack_index, uint32_t reg_id) {
260 __ movq(CpuRegister(reg_id), Address(CpuRegister(RSP), stack_index));
261 return kX86_64WordSize;
262}
263
264size_t CodeGeneratorX86_64::SaveFloatingPointRegister(size_t stack_index, uint32_t reg_id) {
265 __ movsd(Address(CpuRegister(RSP), stack_index), XmmRegister(reg_id));
266 return kX86_64WordSize;
267}
268
269size_t CodeGeneratorX86_64::RestoreFloatingPointRegister(size_t stack_index, uint32_t reg_id) {
270 __ movsd(XmmRegister(reg_id), Address(CpuRegister(RSP), stack_index));
271 return kX86_64WordSize;
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +0100272}
273
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100274CodeGeneratorX86_64::CodeGeneratorX86_64(HGraph* graph)
Nicolas Geoffray71175b72014-10-09 22:13:55 +0100275 : CodeGenerator(graph, kNumberOfCpuRegisters, kNumberOfFloatRegisters, 0),
Nicolas Geoffray92a73ae2014-10-16 11:12:52 +0100276 block_labels_(graph->GetArena(), 0),
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100277 location_builder_(graph, this),
Nicolas Geoffrayecb2f9b2014-06-13 08:59:59 +0000278 instruction_visitor_(graph, this),
279 move_resolver_(graph->GetArena(), this) {}
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100280
Nicolas Geoffrayab032bc2014-07-15 12:55:21 +0100281size_t CodeGeneratorX86_64::FrameEntrySpillSize() const {
282 return kNumberOfPushedRegistersAtEntry * kX86_64WordSize;
283}
284
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +0100285InstructionCodeGeneratorX86_64::InstructionCodeGeneratorX86_64(HGraph* graph,
286 CodeGeneratorX86_64* codegen)
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100287 : HGraphVisitor(graph),
288 assembler_(codegen->GetAssembler()),
289 codegen_(codegen) {}
290
Nicolas Geoffray71175b72014-10-09 22:13:55 +0100291Location CodeGeneratorX86_64::AllocateFreeRegister(Primitive::Type type) const {
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100292 switch (type) {
293 case Primitive::kPrimLong:
294 case Primitive::kPrimByte:
295 case Primitive::kPrimBoolean:
296 case Primitive::kPrimChar:
297 case Primitive::kPrimShort:
298 case Primitive::kPrimInt:
299 case Primitive::kPrimNot: {
Nicolas Geoffray71175b72014-10-09 22:13:55 +0100300 size_t reg = FindFreeEntry(blocked_core_registers_, kNumberOfCpuRegisters);
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100301 return Location::RegisterLocation(reg);
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100302 }
303
304 case Primitive::kPrimFloat:
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100305 case Primitive::kPrimDouble: {
Nicolas Geoffray71175b72014-10-09 22:13:55 +0100306 size_t reg = FindFreeEntry(blocked_fpu_registers_, kNumberOfFloatRegisters);
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100307 return Location::FpuRegisterLocation(reg);
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100308 }
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100309
310 case Primitive::kPrimVoid:
311 LOG(FATAL) << "Unreachable type " << type;
312 }
313
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100314 return Location();
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100315}
316
Nicolas Geoffray71175b72014-10-09 22:13:55 +0100317void CodeGeneratorX86_64::SetupBlockedRegisters() const {
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100318 // Stack register is always reserved.
Nicolas Geoffray71175b72014-10-09 22:13:55 +0100319 blocked_core_registers_[RSP] = true;
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100320
Nicolas Geoffrayecb2f9b2014-06-13 08:59:59 +0000321 // Block the register used as TMP.
Nicolas Geoffray71175b72014-10-09 22:13:55 +0100322 blocked_core_registers_[TMP] = true;
Nicolas Geoffrayecb2f9b2014-06-13 08:59:59 +0000323
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100324 // TODO: We currently don't use Quick's callee saved registers.
Nicolas Geoffray71175b72014-10-09 22:13:55 +0100325 blocked_core_registers_[RBX] = true;
326 blocked_core_registers_[RBP] = true;
327 blocked_core_registers_[R12] = true;
328 blocked_core_registers_[R13] = true;
329 blocked_core_registers_[R14] = true;
330 blocked_core_registers_[R15] = true;
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100331
Nicolas Geoffray71175b72014-10-09 22:13:55 +0100332 blocked_fpu_registers_[XMM12] = true;
333 blocked_fpu_registers_[XMM13] = true;
334 blocked_fpu_registers_[XMM14] = true;
335 blocked_fpu_registers_[XMM15] = true;
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100336}
337
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100338void CodeGeneratorX86_64::GenerateFrameEntry() {
339 // Create a fake register to mimic Quick.
340 static const int kFakeReturnRegister = 16;
341 core_spill_mask_ |= (1 << kFakeReturnRegister);
342
Nicolas Geoffrayf6e206c2014-08-07 20:25:41 +0100343 bool skip_overflow_check = IsLeafMethod()
Dave Allison648d7112014-07-25 16:15:27 -0700344 && !FrameNeedsStackCheck(GetFrameSize(), InstructionSet::kX86_64);
Nicolas Geoffrayf6e206c2014-08-07 20:25:41 +0100345
346 if (!skip_overflow_check && !kExplicitStackOverflowCheck) {
347 __ testq(CpuRegister(RAX), Address(
348 CpuRegister(RSP), -static_cast<int32_t>(GetStackOverflowReservedBytes(kX86_64))));
Nicolas Geoffray39468442014-09-02 15:17:15 +0100349 RecordPcInfo(nullptr, 0);
Nicolas Geoffrayf6e206c2014-08-07 20:25:41 +0100350 }
351
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100352 // The return PC has already been pushed on the stack.
Nicolas Geoffrayf12feb82014-07-17 18:32:41 +0100353 __ subq(CpuRegister(RSP),
354 Immediate(GetFrameSize() - kNumberOfPushedRegistersAtEntry * kX86_64WordSize));
355
Nicolas Geoffrayf6e206c2014-08-07 20:25:41 +0100356 if (!skip_overflow_check && kExplicitStackOverflowCheck) {
Nicolas Geoffray92a73ae2014-10-16 11:12:52 +0100357 SlowPathCodeX86_64* slow_path = new (GetGraph()->GetArena()) StackOverflowCheckSlowPathX86_64();
Nicolas Geoffrayf6e206c2014-08-07 20:25:41 +0100358 AddSlowPath(slow_path);
Nicolas Geoffrayf12feb82014-07-17 18:32:41 +0100359
Nicolas Geoffrayf6e206c2014-08-07 20:25:41 +0100360 __ gs()->cmpq(CpuRegister(RSP),
361 Address::Absolute(Thread::StackEndOffset<kX86_64WordSize>(), true));
362 __ j(kLess, slow_path->GetEntryLabel());
Nicolas Geoffrayf12feb82014-07-17 18:32:41 +0100363 }
364
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100365 __ movl(Address(CpuRegister(RSP), kCurrentMethodStackOffset), CpuRegister(RDI));
366}
367
368void CodeGeneratorX86_64::GenerateFrameExit() {
369 __ addq(CpuRegister(RSP),
370 Immediate(GetFrameSize() - kNumberOfPushedRegistersAtEntry * kX86_64WordSize));
371}
372
Nicolas Geoffray92a73ae2014-10-16 11:12:52 +0100373void CodeGeneratorX86_64::Bind(HBasicBlock* block) {
374 __ Bind(GetLabelOf(block));
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100375}
376
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +0100377void CodeGeneratorX86_64::LoadCurrentMethod(CpuRegister reg) {
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100378 __ movl(reg, Address(CpuRegister(RSP), kCurrentMethodStackOffset));
379}
380
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100381Location CodeGeneratorX86_64::GetStackLocation(HLoadLocal* load) const {
382 switch (load->GetType()) {
383 case Primitive::kPrimLong:
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100384 case Primitive::kPrimDouble:
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100385 return Location::DoubleStackSlot(GetStackSlot(load->GetLocal()));
386 break;
387
388 case Primitive::kPrimInt:
389 case Primitive::kPrimNot:
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100390 case Primitive::kPrimFloat:
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100391 return Location::StackSlot(GetStackSlot(load->GetLocal()));
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100392
393 case Primitive::kPrimBoolean:
394 case Primitive::kPrimByte:
395 case Primitive::kPrimChar:
396 case Primitive::kPrimShort:
397 case Primitive::kPrimVoid:
398 LOG(FATAL) << "Unexpected type " << load->GetType();
399 }
400
401 LOG(FATAL) << "Unreachable";
402 return Location();
403}
404
405void CodeGeneratorX86_64::Move(Location destination, Location source) {
406 if (source.Equals(destination)) {
407 return;
408 }
409 if (destination.IsRegister()) {
410 if (source.IsRegister()) {
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100411 __ movq(destination.As<CpuRegister>(), source.As<CpuRegister>());
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100412 } else if (source.IsFpuRegister()) {
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100413 __ movd(destination.As<CpuRegister>(), source.As<XmmRegister>());
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100414 } else if (source.IsStackSlot()) {
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100415 __ movl(destination.As<CpuRegister>(),
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100416 Address(CpuRegister(RSP), source.GetStackIndex()));
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100417 } else {
418 DCHECK(source.IsDoubleStackSlot());
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100419 __ movq(destination.As<CpuRegister>(),
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100420 Address(CpuRegister(RSP), source.GetStackIndex()));
421 }
422 } else if (destination.IsFpuRegister()) {
423 if (source.IsRegister()) {
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100424 __ movd(destination.As<XmmRegister>(), source.As<CpuRegister>());
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100425 } else if (source.IsFpuRegister()) {
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100426 __ movaps(destination.As<XmmRegister>(), source.As<XmmRegister>());
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100427 } else if (source.IsStackSlot()) {
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100428 __ movss(destination.As<XmmRegister>(),
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100429 Address(CpuRegister(RSP), source.GetStackIndex()));
430 } else {
431 DCHECK(source.IsDoubleStackSlot());
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100432 __ movsd(destination.As<XmmRegister>(),
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100433 Address(CpuRegister(RSP), source.GetStackIndex()));
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100434 }
435 } else if (destination.IsStackSlot()) {
436 if (source.IsRegister()) {
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100437 __ movl(Address(CpuRegister(RSP), destination.GetStackIndex()),
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100438 source.As<CpuRegister>());
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100439 } else if (source.IsFpuRegister()) {
440 __ movss(Address(CpuRegister(RSP), destination.GetStackIndex()),
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100441 source.As<XmmRegister>());
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100442 } else {
443 DCHECK(source.IsStackSlot());
Nicolas Geoffrayecb2f9b2014-06-13 08:59:59 +0000444 __ movl(CpuRegister(TMP), Address(CpuRegister(RSP), source.GetStackIndex()));
445 __ movl(Address(CpuRegister(RSP), destination.GetStackIndex()), CpuRegister(TMP));
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100446 }
447 } else {
448 DCHECK(destination.IsDoubleStackSlot());
449 if (source.IsRegister()) {
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100450 __ movq(Address(CpuRegister(RSP), destination.GetStackIndex()),
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100451 source.As<CpuRegister>());
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100452 } else if (source.IsFpuRegister()) {
453 __ movsd(Address(CpuRegister(RSP), destination.GetStackIndex()),
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100454 source.As<XmmRegister>());
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100455 } else {
456 DCHECK(source.IsDoubleStackSlot());
Nicolas Geoffrayecb2f9b2014-06-13 08:59:59 +0000457 __ movq(CpuRegister(TMP), Address(CpuRegister(RSP), source.GetStackIndex()));
458 __ movq(Address(CpuRegister(RSP), destination.GetStackIndex()), CpuRegister(TMP));
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100459 }
460 }
461}
462
Nicolas Geoffray412f10c2014-06-19 10:00:34 +0100463void CodeGeneratorX86_64::Move(HInstruction* instruction,
464 Location location,
465 HInstruction* move_for) {
Roland Levillain476df552014-10-09 17:51:36 +0100466 if (instruction->IsIntConstant()) {
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100467 Immediate imm(instruction->AsIntConstant()->GetValue());
468 if (location.IsRegister()) {
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100469 __ movl(location.As<CpuRegister>(), imm);
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +0100470 } else if (location.IsStackSlot()) {
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100471 __ movl(Address(CpuRegister(RSP), location.GetStackIndex()), imm);
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +0100472 } else {
473 DCHECK(location.IsConstant());
474 DCHECK_EQ(location.GetConstant(), instruction);
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100475 }
Roland Levillain476df552014-10-09 17:51:36 +0100476 } else if (instruction->IsLongConstant()) {
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100477 int64_t value = instruction->AsLongConstant()->GetValue();
478 if (location.IsRegister()) {
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100479 __ movq(location.As<CpuRegister>(), Immediate(value));
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +0100480 } else if (location.IsDoubleStackSlot()) {
Nicolas Geoffrayecb2f9b2014-06-13 08:59:59 +0000481 __ movq(CpuRegister(TMP), Immediate(value));
482 __ movq(Address(CpuRegister(RSP), location.GetStackIndex()), CpuRegister(TMP));
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +0100483 } else {
484 DCHECK(location.IsConstant());
485 DCHECK_EQ(location.GetConstant(), instruction);
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100486 }
Roland Levillain476df552014-10-09 17:51:36 +0100487 } else if (instruction->IsLoadLocal()) {
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100488 switch (instruction->GetType()) {
489 case Primitive::kPrimBoolean:
490 case Primitive::kPrimByte:
491 case Primitive::kPrimChar:
492 case Primitive::kPrimShort:
493 case Primitive::kPrimInt:
494 case Primitive::kPrimNot:
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100495 case Primitive::kPrimFloat:
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100496 Move(location, Location::StackSlot(GetStackSlot(instruction->AsLoadLocal()->GetLocal())));
497 break;
498
499 case Primitive::kPrimLong:
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100500 case Primitive::kPrimDouble:
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100501 Move(location, Location::DoubleStackSlot(GetStackSlot(instruction->AsLoadLocal()->GetLocal())));
502 break;
503
504 default:
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100505 LOG(FATAL) << "Unexpected local type " << instruction->GetType();
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100506 }
507 } else {
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100508 DCHECK((instruction->GetNext() == move_for) || instruction->GetNext()->IsTemporary());
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100509 switch (instruction->GetType()) {
510 case Primitive::kPrimBoolean:
511 case Primitive::kPrimByte:
512 case Primitive::kPrimChar:
513 case Primitive::kPrimShort:
514 case Primitive::kPrimInt:
515 case Primitive::kPrimNot:
516 case Primitive::kPrimLong:
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100517 case Primitive::kPrimFloat:
518 case Primitive::kPrimDouble:
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100519 Move(location, instruction->GetLocations()->Out());
520 break;
521
522 default:
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100523 LOG(FATAL) << "Unexpected type " << instruction->GetType();
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100524 }
525 }
526}
527
528void LocationsBuilderX86_64::VisitGoto(HGoto* got) {
529 got->SetLocations(nullptr);
530}
531
532void InstructionCodeGeneratorX86_64::VisitGoto(HGoto* got) {
533 HBasicBlock* successor = got->GetSuccessor();
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100534 DCHECK(!successor->IsExitBlock());
535
536 HBasicBlock* block = got->GetBlock();
537 HInstruction* previous = got->GetPrevious();
538
539 HLoopInformation* info = block->GetLoopInformation();
540 if (info != nullptr && info->IsBackEdge(block) && info->HasSuspendCheck()) {
541 codegen_->ClearSpillSlotsFromLoopPhisInStackMap(info->GetSuspendCheck());
542 GenerateSuspendCheck(info->GetSuspendCheck(), successor);
543 return;
544 }
545
546 if (block->IsEntryBlock() && (previous != nullptr) && previous->IsSuspendCheck()) {
547 GenerateSuspendCheck(previous->AsSuspendCheck(), nullptr);
548 }
549 if (!codegen_->GoesToNextBlock(got->GetBlock(), successor)) {
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100550 __ jmp(codegen_->GetLabelOf(successor));
551 }
552}
553
554void LocationsBuilderX86_64::VisitExit(HExit* exit) {
555 exit->SetLocations(nullptr);
556}
557
558void InstructionCodeGeneratorX86_64::VisitExit(HExit* exit) {
559 if (kIsDebugBuild) {
560 __ Comment("Unreachable");
561 __ int3();
562 }
563}
564
565void LocationsBuilderX86_64::VisitIf(HIf* if_instr) {
Nicolas Geoffray39468442014-09-02 15:17:15 +0100566 LocationSummary* locations =
567 new (GetGraph()->GetArena()) LocationSummary(if_instr, LocationSummary::kNoCall);
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100568 HInstruction* cond = if_instr->InputAt(0);
Nicolas Geoffray01ef3452014-10-01 11:32:17 +0100569 if (!cond->IsCondition() || cond->AsCondition()->NeedsMaterialization()) {
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +0100570 locations->SetInAt(0, Location::Any());
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100571 }
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100572}
573
574void InstructionCodeGeneratorX86_64::VisitIf(HIf* if_instr) {
Dave Allison20dfc792014-06-16 20:44:29 -0700575 HInstruction* cond = if_instr->InputAt(0);
Roland Levillain3a3fd0f2014-10-10 13:56:31 +0100576 if (cond->IsIntConstant()) {
577 // Constant condition, statically compared against 1.
578 int32_t cond_value = cond->AsIntConstant()->GetValue();
579 if (cond_value == 1) {
580 if (!codegen_->GoesToNextBlock(if_instr->GetBlock(),
581 if_instr->IfTrueSuccessor())) {
582 __ jmp(codegen_->GetLabelOf(if_instr->IfTrueSuccessor()));
Nicolas Geoffray18efde52014-09-22 15:51:11 +0100583 }
Roland Levillain3a3fd0f2014-10-10 13:56:31 +0100584 return;
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100585 } else {
Roland Levillain3a3fd0f2014-10-10 13:56:31 +0100586 DCHECK_EQ(cond_value, 0);
587 }
588 } else {
589 bool materialized =
590 !cond->IsCondition() || cond->AsCondition()->NeedsMaterialization();
591 // Moves do not affect the eflags register, so if the condition is
592 // evaluated just before the if, we don't need to evaluate it
593 // again.
594 bool eflags_set = cond->IsCondition()
595 && cond->AsCondition()->IsBeforeWhenDisregardMoves(if_instr);
596 if (materialized) {
597 if (!eflags_set) {
598 // Materialized condition, compare against 0.
599 Location lhs = if_instr->GetLocations()->InAt(0);
600 if (lhs.IsRegister()) {
601 __ cmpl(lhs.As<CpuRegister>(), Immediate(0));
602 } else {
603 __ cmpl(Address(CpuRegister(RSP), lhs.GetStackIndex()),
604 Immediate(0));
605 }
606 __ j(kNotEqual, codegen_->GetLabelOf(if_instr->IfTrueSuccessor()));
607 } else {
608 __ j(X86_64Condition(cond->AsCondition()->GetCondition()),
609 codegen_->GetLabelOf(if_instr->IfTrueSuccessor()));
610 }
611 } else {
612 Location lhs = cond->GetLocations()->InAt(0);
613 Location rhs = cond->GetLocations()->InAt(1);
614 if (rhs.IsRegister()) {
615 __ cmpl(lhs.As<CpuRegister>(), rhs.As<CpuRegister>());
616 } else if (rhs.IsConstant()) {
617 __ cmpl(lhs.As<CpuRegister>(),
618 Immediate(rhs.GetConstant()->AsIntConstant()->GetValue()));
619 } else {
620 __ cmpl(lhs.As<CpuRegister>(),
621 Address(CpuRegister(RSP), rhs.GetStackIndex()));
622 }
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100623 __ j(X86_64Condition(cond->AsCondition()->GetCondition()),
624 codegen_->GetLabelOf(if_instr->IfTrueSuccessor()));
Dave Allison20dfc792014-06-16 20:44:29 -0700625 }
Dave Allison20dfc792014-06-16 20:44:29 -0700626 }
Roland Levillain3a3fd0f2014-10-10 13:56:31 +0100627 if (!codegen_->GoesToNextBlock(if_instr->GetBlock(),
628 if_instr->IfFalseSuccessor())) {
Dave Allison20dfc792014-06-16 20:44:29 -0700629 __ jmp(codegen_->GetLabelOf(if_instr->IfFalseSuccessor()));
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100630 }
631}
632
633void LocationsBuilderX86_64::VisitLocal(HLocal* local) {
634 local->SetLocations(nullptr);
635}
636
637void InstructionCodeGeneratorX86_64::VisitLocal(HLocal* local) {
638 DCHECK_EQ(local->GetBlock(), GetGraph()->GetEntryBlock());
639}
640
641void LocationsBuilderX86_64::VisitLoadLocal(HLoadLocal* local) {
642 local->SetLocations(nullptr);
643}
644
645void InstructionCodeGeneratorX86_64::VisitLoadLocal(HLoadLocal* load) {
646 // Nothing to do, this is driven by the code generator.
647}
648
649void LocationsBuilderX86_64::VisitStoreLocal(HStoreLocal* store) {
Nicolas Geoffray39468442014-09-02 15:17:15 +0100650 LocationSummary* locations =
651 new (GetGraph()->GetArena()) LocationSummary(store, LocationSummary::kNoCall);
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100652 switch (store->InputAt(1)->GetType()) {
653 case Primitive::kPrimBoolean:
654 case Primitive::kPrimByte:
655 case Primitive::kPrimChar:
656 case Primitive::kPrimShort:
657 case Primitive::kPrimInt:
658 case Primitive::kPrimNot:
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100659 case Primitive::kPrimFloat:
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100660 locations->SetInAt(1, Location::StackSlot(codegen_->GetStackSlot(store->GetLocal())));
661 break;
662
663 case Primitive::kPrimLong:
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100664 case Primitive::kPrimDouble:
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100665 locations->SetInAt(1, Location::DoubleStackSlot(codegen_->GetStackSlot(store->GetLocal())));
666 break;
667
668 default:
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100669 LOG(FATAL) << "Unexpected local type " << store->InputAt(1)->GetType();
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100670 }
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100671}
672
673void InstructionCodeGeneratorX86_64::VisitStoreLocal(HStoreLocal* store) {
674}
675
Dave Allison20dfc792014-06-16 20:44:29 -0700676void LocationsBuilderX86_64::VisitCondition(HCondition* comp) {
Nicolas Geoffray39468442014-09-02 15:17:15 +0100677 LocationSummary* locations =
678 new (GetGraph()->GetArena()) LocationSummary(comp, LocationSummary::kNoCall);
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +0100679 locations->SetInAt(0, Location::RequiresRegister());
680 locations->SetInAt(1, Location::Any());
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100681 if (comp->NeedsMaterialization()) {
682 locations->SetOut(Location::RequiresRegister());
683 }
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100684}
685
Dave Allison20dfc792014-06-16 20:44:29 -0700686void InstructionCodeGeneratorX86_64::VisitCondition(HCondition* comp) {
687 if (comp->NeedsMaterialization()) {
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100688 LocationSummary* locations = comp->GetLocations();
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100689 CpuRegister reg = locations->Out().As<CpuRegister>();
Nicolas Geoffray18efde52014-09-22 15:51:11 +0100690 // Clear register: setcc only sets the low byte.
691 __ xorq(reg, reg);
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100692 if (locations->InAt(1).IsRegister()) {
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100693 __ cmpl(locations->InAt(0).As<CpuRegister>(),
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100694 locations->InAt(1).As<CpuRegister>());
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100695 } else if (locations->InAt(1).IsConstant()) {
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100696 __ cmpl(locations->InAt(0).As<CpuRegister>(),
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100697 Immediate(locations->InAt(1).GetConstant()->AsIntConstant()->GetValue()));
698 } else {
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100699 __ cmpl(locations->InAt(0).As<CpuRegister>(),
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100700 Address(CpuRegister(RSP), locations->InAt(1).GetStackIndex()));
701 }
Nicolas Geoffray18efde52014-09-22 15:51:11 +0100702 __ setcc(X86_64Condition(comp->GetCondition()), reg);
Dave Allison20dfc792014-06-16 20:44:29 -0700703 }
704}
705
706void LocationsBuilderX86_64::VisitEqual(HEqual* comp) {
707 VisitCondition(comp);
708}
709
710void InstructionCodeGeneratorX86_64::VisitEqual(HEqual* comp) {
711 VisitCondition(comp);
712}
713
714void LocationsBuilderX86_64::VisitNotEqual(HNotEqual* comp) {
715 VisitCondition(comp);
716}
717
718void InstructionCodeGeneratorX86_64::VisitNotEqual(HNotEqual* comp) {
719 VisitCondition(comp);
720}
721
722void LocationsBuilderX86_64::VisitLessThan(HLessThan* comp) {
723 VisitCondition(comp);
724}
725
726void InstructionCodeGeneratorX86_64::VisitLessThan(HLessThan* comp) {
727 VisitCondition(comp);
728}
729
730void LocationsBuilderX86_64::VisitLessThanOrEqual(HLessThanOrEqual* comp) {
731 VisitCondition(comp);
732}
733
734void InstructionCodeGeneratorX86_64::VisitLessThanOrEqual(HLessThanOrEqual* comp) {
735 VisitCondition(comp);
736}
737
738void LocationsBuilderX86_64::VisitGreaterThan(HGreaterThan* comp) {
739 VisitCondition(comp);
740}
741
742void InstructionCodeGeneratorX86_64::VisitGreaterThan(HGreaterThan* comp) {
743 VisitCondition(comp);
744}
745
746void LocationsBuilderX86_64::VisitGreaterThanOrEqual(HGreaterThanOrEqual* comp) {
747 VisitCondition(comp);
748}
749
750void InstructionCodeGeneratorX86_64::VisitGreaterThanOrEqual(HGreaterThanOrEqual* comp) {
751 VisitCondition(comp);
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100752}
753
Nicolas Geoffray412f10c2014-06-19 10:00:34 +0100754void LocationsBuilderX86_64::VisitCompare(HCompare* compare) {
Nicolas Geoffray39468442014-09-02 15:17:15 +0100755 LocationSummary* locations =
756 new (GetGraph()->GetArena()) LocationSummary(compare, LocationSummary::kNoCall);
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +0100757 locations->SetInAt(0, Location::RequiresRegister());
758 locations->SetInAt(1, Location::RequiresRegister());
759 locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
Nicolas Geoffray412f10c2014-06-19 10:00:34 +0100760}
761
762void InstructionCodeGeneratorX86_64::VisitCompare(HCompare* compare) {
763 Label greater, done;
764 LocationSummary* locations = compare->GetLocations();
765 switch (compare->InputAt(0)->GetType()) {
766 case Primitive::kPrimLong:
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100767 __ cmpq(locations->InAt(0).As<CpuRegister>(),
768 locations->InAt(1).As<CpuRegister>());
Nicolas Geoffray412f10c2014-06-19 10:00:34 +0100769 break;
770 default:
771 LOG(FATAL) << "Unimplemented compare type " << compare->InputAt(0)->GetType();
772 }
773
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100774 CpuRegister output = locations->Out().As<CpuRegister>();
775 __ movl(output, Immediate(0));
Nicolas Geoffray412f10c2014-06-19 10:00:34 +0100776 __ j(kEqual, &done);
777 __ j(kGreater, &greater);
778
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100779 __ movl(output, Immediate(-1));
Nicolas Geoffray412f10c2014-06-19 10:00:34 +0100780 __ jmp(&done);
781
782 __ Bind(&greater);
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100783 __ movl(output, Immediate(1));
Nicolas Geoffray412f10c2014-06-19 10:00:34 +0100784
785 __ Bind(&done);
786}
787
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100788void LocationsBuilderX86_64::VisitIntConstant(HIntConstant* constant) {
Nicolas Geoffray39468442014-09-02 15:17:15 +0100789 LocationSummary* locations =
790 new (GetGraph()->GetArena()) LocationSummary(constant, LocationSummary::kNoCall);
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100791 locations->SetOut(Location::ConstantLocation(constant));
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100792}
793
794void InstructionCodeGeneratorX86_64::VisitIntConstant(HIntConstant* constant) {
Roland Levillain3a3fd0f2014-10-10 13:56:31 +0100795 // Will be generated at use site.
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100796}
797
798void LocationsBuilderX86_64::VisitLongConstant(HLongConstant* constant) {
Nicolas Geoffray39468442014-09-02 15:17:15 +0100799 LocationSummary* locations =
800 new (GetGraph()->GetArena()) LocationSummary(constant, LocationSummary::kNoCall);
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100801 locations->SetOut(Location::ConstantLocation(constant));
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100802}
803
804void InstructionCodeGeneratorX86_64::VisitLongConstant(HLongConstant* constant) {
Roland Levillain3a3fd0f2014-10-10 13:56:31 +0100805 // Will be generated at use site.
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100806}
807
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100808void LocationsBuilderX86_64::VisitFloatConstant(HFloatConstant* constant) {
809 LocationSummary* locations =
810 new (GetGraph()->GetArena()) LocationSummary(constant, LocationSummary::kNoCall);
811 locations->SetOut(Location::ConstantLocation(constant));
812}
813
814void InstructionCodeGeneratorX86_64::VisitFloatConstant(HFloatConstant* constant) {
815 // Will be generated at use site.
816}
817
818void LocationsBuilderX86_64::VisitDoubleConstant(HDoubleConstant* constant) {
819 LocationSummary* locations =
820 new (GetGraph()->GetArena()) LocationSummary(constant, LocationSummary::kNoCall);
821 locations->SetOut(Location::ConstantLocation(constant));
822}
823
824void InstructionCodeGeneratorX86_64::VisitDoubleConstant(HDoubleConstant* constant) {
825 // Will be generated at use site.
826}
827
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100828void LocationsBuilderX86_64::VisitReturnVoid(HReturnVoid* ret) {
829 ret->SetLocations(nullptr);
830}
831
832void InstructionCodeGeneratorX86_64::VisitReturnVoid(HReturnVoid* ret) {
833 codegen_->GenerateFrameExit();
834 __ ret();
835}
836
837void LocationsBuilderX86_64::VisitReturn(HReturn* ret) {
Nicolas Geoffray39468442014-09-02 15:17:15 +0100838 LocationSummary* locations =
839 new (GetGraph()->GetArena()) LocationSummary(ret, LocationSummary::kNoCall);
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100840 switch (ret->InputAt(0)->GetType()) {
841 case Primitive::kPrimBoolean:
842 case Primitive::kPrimByte:
843 case Primitive::kPrimChar:
844 case Primitive::kPrimShort:
845 case Primitive::kPrimInt:
846 case Primitive::kPrimNot:
847 case Primitive::kPrimLong:
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100848 locations->SetInAt(0, Location::RegisterLocation(RAX));
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100849 break;
850
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100851 case Primitive::kPrimFloat:
852 case Primitive::kPrimDouble:
853 locations->SetInAt(0,
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100854 Location::FpuRegisterLocation(XMM0));
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100855 break;
856
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100857 default:
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100858 LOG(FATAL) << "Unexpected return type " << ret->InputAt(0)->GetType();
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100859 }
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100860}
861
862void InstructionCodeGeneratorX86_64::VisitReturn(HReturn* ret) {
863 if (kIsDebugBuild) {
864 switch (ret->InputAt(0)->GetType()) {
865 case Primitive::kPrimBoolean:
866 case Primitive::kPrimByte:
867 case Primitive::kPrimChar:
868 case Primitive::kPrimShort:
869 case Primitive::kPrimInt:
870 case Primitive::kPrimNot:
871 case Primitive::kPrimLong:
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100872 DCHECK_EQ(ret->GetLocations()->InAt(0).As<CpuRegister>().AsRegister(), RAX);
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100873 break;
874
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100875 case Primitive::kPrimFloat:
876 case Primitive::kPrimDouble:
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100877 DCHECK_EQ(ret->GetLocations()->InAt(0).As<XmmRegister>().AsFloatRegister(),
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100878 XMM0);
879 break;
880
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100881 default:
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100882 LOG(FATAL) << "Unexpected return type " << ret->InputAt(0)->GetType();
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100883 }
884 }
885 codegen_->GenerateFrameExit();
886 __ ret();
887}
888
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100889Location InvokeDexCallingConventionVisitor::GetNextLocation(Primitive::Type type) {
890 switch (type) {
891 case Primitive::kPrimBoolean:
892 case Primitive::kPrimByte:
893 case Primitive::kPrimChar:
894 case Primitive::kPrimShort:
895 case Primitive::kPrimInt:
896 case Primitive::kPrimNot: {
897 uint32_t index = gp_index_++;
898 stack_index_++;
899 if (index < calling_convention.GetNumberOfRegisters()) {
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100900 return Location::RegisterLocation(calling_convention.GetRegisterAt(index));
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100901 } else {
902 return Location::StackSlot(calling_convention.GetStackOffsetOf(stack_index_ - 1));
903 }
904 }
905
906 case Primitive::kPrimLong: {
907 uint32_t index = gp_index_;
908 stack_index_ += 2;
909 if (index < calling_convention.GetNumberOfRegisters()) {
910 gp_index_ += 1;
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100911 return Location::RegisterLocation(calling_convention.GetRegisterAt(index));
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100912 } else {
913 gp_index_ += 2;
914 return Location::DoubleStackSlot(calling_convention.GetStackOffsetOf(stack_index_ - 2));
915 }
916 }
917
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100918 case Primitive::kPrimFloat: {
919 uint32_t index = fp_index_++;
920 stack_index_++;
921 if (index < calling_convention.GetNumberOfFpuRegisters()) {
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100922 return Location::FpuRegisterLocation(calling_convention.GetFpuRegisterAt(index));
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100923 } else {
924 return Location::StackSlot(calling_convention.GetStackOffsetOf(stack_index_ - 1));
925 }
926 }
927
928 case Primitive::kPrimDouble: {
929 uint32_t index = fp_index_++;
930 stack_index_ += 2;
931 if (index < calling_convention.GetNumberOfFpuRegisters()) {
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100932 return Location::FpuRegisterLocation(calling_convention.GetFpuRegisterAt(index));
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100933 } else {
934 return Location::DoubleStackSlot(calling_convention.GetStackOffsetOf(stack_index_ - 2));
935 }
936 }
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100937
938 case Primitive::kPrimVoid:
939 LOG(FATAL) << "Unexpected parameter type " << type;
940 break;
941 }
942 return Location();
943}
944
945void LocationsBuilderX86_64::VisitInvokeStatic(HInvokeStatic* invoke) {
Nicolas Geoffraye982f0b2014-08-13 02:11:24 +0100946 HandleInvoke(invoke);
947}
948
949void InstructionCodeGeneratorX86_64::VisitInvokeStatic(HInvokeStatic* invoke) {
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100950 CpuRegister temp = invoke->GetLocations()->GetTemp(0).As<CpuRegister>();
Nicolas Geoffraye982f0b2014-08-13 02:11:24 +0100951 // TODO: Implement all kinds of calls:
952 // 1) boot -> boot
953 // 2) app -> boot
954 // 3) app -> app
955 //
956 // Currently we implement the app -> app logic, which looks up in the resolve cache.
957
958 // temp = method;
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +0100959 codegen_->LoadCurrentMethod(temp);
Nicolas Geoffraye982f0b2014-08-13 02:11:24 +0100960 // temp = temp->dex_cache_resolved_methods_;
961 __ movl(temp, Address(temp, mirror::ArtMethod::DexCacheResolvedMethodsOffset().SizeValue()));
962 // temp = temp[index_in_cache]
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +0100963 __ movl(temp, Address(temp, CodeGenerator::GetCacheOffset(invoke->GetIndexInDexCache())));
Nicolas Geoffraye982f0b2014-08-13 02:11:24 +0100964 // (temp + offset_of_quick_compiled_code)()
965 __ call(Address(temp, mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset().SizeValue()));
966
967 DCHECK(!codegen_->IsLeafMethod());
968 codegen_->RecordPcInfo(invoke, invoke->GetDexPc());
969}
970
971void LocationsBuilderX86_64::VisitInvokeVirtual(HInvokeVirtual* invoke) {
972 HandleInvoke(invoke);
973}
974
975void LocationsBuilderX86_64::HandleInvoke(HInvoke* invoke) {
Nicolas Geoffray39468442014-09-02 15:17:15 +0100976 LocationSummary* locations =
977 new (GetGraph()->GetArena()) LocationSummary(invoke, LocationSummary::kCall);
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100978 locations->AddTemp(Location::RegisterLocation(RDI));
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100979
980 InvokeDexCallingConventionVisitor calling_convention_visitor;
Nicolas Geoffraye982f0b2014-08-13 02:11:24 +0100981 for (size_t i = 0; i < invoke->InputCount(); i++) {
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100982 HInstruction* input = invoke->InputAt(i);
983 locations->SetInAt(i, calling_convention_visitor.GetNextLocation(input->GetType()));
984 }
985
986 switch (invoke->GetType()) {
987 case Primitive::kPrimBoolean:
988 case Primitive::kPrimByte:
989 case Primitive::kPrimChar:
990 case Primitive::kPrimShort:
991 case Primitive::kPrimInt:
992 case Primitive::kPrimNot:
993 case Primitive::kPrimLong:
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100994 locations->SetOut(Location::RegisterLocation(RAX));
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100995 break;
996
997 case Primitive::kPrimVoid:
998 break;
999
1000 case Primitive::kPrimDouble:
1001 case Primitive::kPrimFloat:
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +01001002 locations->SetOut(Location::FpuRegisterLocation(XMM0));
Nicolas Geoffray9cf35522014-06-09 18:40:10 +01001003 break;
1004 }
Nicolas Geoffray9cf35522014-06-09 18:40:10 +01001005}
1006
Nicolas Geoffraye982f0b2014-08-13 02:11:24 +01001007void InstructionCodeGeneratorX86_64::VisitInvokeVirtual(HInvokeVirtual* invoke) {
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +01001008 CpuRegister temp = invoke->GetLocations()->GetTemp(0).As<CpuRegister>();
Nicolas Geoffraye982f0b2014-08-13 02:11:24 +01001009 size_t method_offset = mirror::Class::EmbeddedVTableOffset().SizeValue() +
1010 invoke->GetVTableIndex() * sizeof(mirror::Class::VTableEntry);
1011 LocationSummary* locations = invoke->GetLocations();
1012 Location receiver = locations->InAt(0);
1013 size_t class_offset = mirror::Object::ClassOffset().SizeValue();
1014 // temp = object->GetClass();
1015 if (receiver.IsStackSlot()) {
Nicolas Geoffray360231a2014-10-08 21:07:48 +01001016 __ movl(temp, Address(CpuRegister(RSP), receiver.GetStackIndex()));
1017 __ movl(temp, Address(temp, class_offset));
Nicolas Geoffraye982f0b2014-08-13 02:11:24 +01001018 } else {
Nicolas Geoffray360231a2014-10-08 21:07:48 +01001019 __ movl(temp, Address(receiver.As<CpuRegister>(), class_offset));
Nicolas Geoffraye982f0b2014-08-13 02:11:24 +01001020 }
1021 // temp = temp->GetMethodAt(method_offset);
1022 __ movl(temp, Address(temp, method_offset));
1023 // call temp->GetEntryPoint();
Nicolas Geoffray9cf35522014-06-09 18:40:10 +01001024 __ call(Address(temp, mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset().SizeValue()));
1025
Nicolas Geoffrayf12feb82014-07-17 18:32:41 +01001026 DCHECK(!codegen_->IsLeafMethod());
Nicolas Geoffray39468442014-09-02 15:17:15 +01001027 codegen_->RecordPcInfo(invoke, invoke->GetDexPc());
Nicolas Geoffray9cf35522014-06-09 18:40:10 +01001028}
1029
Roland Levillain88cb1752014-10-20 16:36:47 +01001030void LocationsBuilderX86_64::VisitNeg(HNeg* neg) {
1031 LocationSummary* locations =
1032 new (GetGraph()->GetArena()) LocationSummary(neg, LocationSummary::kNoCall);
1033 switch (neg->GetResultType()) {
1034 case Primitive::kPrimInt:
Roland Levillain2e07b4f2014-10-23 18:12:09 +01001035 case Primitive::kPrimLong:
Roland Levillain88cb1752014-10-20 16:36:47 +01001036 locations->SetInAt(0, Location::RequiresRegister());
1037 locations->SetOut(Location::SameAsFirstInput());
1038 break;
1039
Roland Levillain88cb1752014-10-20 16:36:47 +01001040 case Primitive::kPrimFloat:
1041 case Primitive::kPrimDouble:
1042 LOG(FATAL) << "Not yet implemented neg type " << neg->GetResultType();
1043 break;
1044
1045 default:
1046 LOG(FATAL) << "Unexpected neg type " << neg->GetResultType();
1047 }
1048}
1049
1050void InstructionCodeGeneratorX86_64::VisitNeg(HNeg* neg) {
1051 LocationSummary* locations = neg->GetLocations();
1052 Location out = locations->Out();
1053 Location in = locations->InAt(0);
1054 switch (neg->GetResultType()) {
1055 case Primitive::kPrimInt:
1056 DCHECK(in.IsRegister());
1057 __ negl(out.As<CpuRegister>());
1058 break;
1059
1060 case Primitive::kPrimLong:
Roland Levillain2e07b4f2014-10-23 18:12:09 +01001061 DCHECK(in.IsRegister());
1062 __ negq(out.As<CpuRegister>());
1063 break;
1064
Roland Levillain88cb1752014-10-20 16:36:47 +01001065 case Primitive::kPrimFloat:
1066 case Primitive::kPrimDouble:
1067 LOG(FATAL) << "Not yet implemented neg type " << neg->GetResultType();
1068 break;
1069
1070 default:
1071 LOG(FATAL) << "Unexpected neg type " << neg->GetResultType();
1072 }
1073}
1074
Nicolas Geoffray9cf35522014-06-09 18:40:10 +01001075void LocationsBuilderX86_64::VisitAdd(HAdd* add) {
Nicolas Geoffray39468442014-09-02 15:17:15 +01001076 LocationSummary* locations =
1077 new (GetGraph()->GetArena()) LocationSummary(add, LocationSummary::kNoCall);
Nicolas Geoffray9cf35522014-06-09 18:40:10 +01001078 switch (add->GetResultType()) {
Nicolas Geoffray96f89a22014-07-11 10:57:49 +01001079 case Primitive::kPrimInt: {
1080 locations->SetInAt(0, Location::RequiresRegister());
1081 locations->SetInAt(1, Location::Any());
1082 locations->SetOut(Location::SameAsFirstInput());
1083 break;
1084 }
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +01001085
Nicolas Geoffray9cf35522014-06-09 18:40:10 +01001086 case Primitive::kPrimLong: {
Nicolas Geoffrayecb2f9b2014-06-13 08:59:59 +00001087 locations->SetInAt(0, Location::RequiresRegister());
1088 locations->SetInAt(1, Location::RequiresRegister());
1089 locations->SetOut(Location::SameAsFirstInput());
Nicolas Geoffray9cf35522014-06-09 18:40:10 +01001090 break;
1091 }
1092
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +01001093 case Primitive::kPrimDouble:
1094 case Primitive::kPrimFloat: {
1095 locations->SetInAt(0, Location::RequiresFpuRegister());
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01001096 locations->SetInAt(1, Location::RequiresFpuRegister());
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +01001097 locations->SetOut(Location::SameAsFirstInput());
Nicolas Geoffray9cf35522014-06-09 18:40:10 +01001098 break;
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +01001099 }
Nicolas Geoffray9cf35522014-06-09 18:40:10 +01001100
1101 default:
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +01001102 LOG(FATAL) << "Unexpected add type " << add->GetResultType();
Nicolas Geoffray9cf35522014-06-09 18:40:10 +01001103 }
Nicolas Geoffray9cf35522014-06-09 18:40:10 +01001104}
1105
1106void InstructionCodeGeneratorX86_64::VisitAdd(HAdd* add) {
1107 LocationSummary* locations = add->GetLocations();
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +01001108 Location first = locations->InAt(0);
1109 Location second = locations->InAt(1);
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +01001110 DCHECK(first.Equals(locations->Out()));
Calin Juravle11351682014-10-23 15:38:15 +01001111
Nicolas Geoffray9cf35522014-06-09 18:40:10 +01001112 switch (add->GetResultType()) {
Nicolas Geoffrayecb2f9b2014-06-13 08:59:59 +00001113 case Primitive::kPrimInt: {
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +01001114 if (second.IsRegister()) {
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +01001115 __ addl(first.As<CpuRegister>(), second.As<CpuRegister>());
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +01001116 } else if (second.IsConstant()) {
Calin Juravle11351682014-10-23 15:38:15 +01001117 Immediate imm(second.GetConstant()->AsIntConstant()->GetValue());
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +01001118 __ addl(first.As<CpuRegister>(), imm);
Nicolas Geoffray96f89a22014-07-11 10:57:49 +01001119 } else {
Calin Juravle11351682014-10-23 15:38:15 +01001120 __ addl(first.As<CpuRegister>(), Address(CpuRegister(RSP), second.GetStackIndex()));
Nicolas Geoffray96f89a22014-07-11 10:57:49 +01001121 }
Nicolas Geoffrayecb2f9b2014-06-13 08:59:59 +00001122 break;
1123 }
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +01001124
Nicolas Geoffray9cf35522014-06-09 18:40:10 +01001125 case Primitive::kPrimLong: {
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +01001126 __ addq(first.As<CpuRegister>(), second.As<CpuRegister>());
Nicolas Geoffray9cf35522014-06-09 18:40:10 +01001127 break;
1128 }
1129
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +01001130 case Primitive::kPrimFloat: {
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01001131 __ addss(first.As<XmmRegister>(), second.As<XmmRegister>());
Nicolas Geoffray9cf35522014-06-09 18:40:10 +01001132 break;
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +01001133 }
1134
1135 case Primitive::kPrimDouble: {
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01001136 __ addsd(first.As<XmmRegister>(), second.As<XmmRegister>());
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +01001137 break;
1138 }
Nicolas Geoffray9cf35522014-06-09 18:40:10 +01001139
1140 default:
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +01001141 LOG(FATAL) << "Unexpected add type " << add->GetResultType();
Nicolas Geoffray9cf35522014-06-09 18:40:10 +01001142 }
1143}
1144
1145void LocationsBuilderX86_64::VisitSub(HSub* sub) {
Nicolas Geoffray39468442014-09-02 15:17:15 +01001146 LocationSummary* locations =
1147 new (GetGraph()->GetArena()) LocationSummary(sub, LocationSummary::kNoCall);
Nicolas Geoffray9cf35522014-06-09 18:40:10 +01001148 switch (sub->GetResultType()) {
Nicolas Geoffray96f89a22014-07-11 10:57:49 +01001149 case Primitive::kPrimInt: {
1150 locations->SetInAt(0, Location::RequiresRegister());
1151 locations->SetInAt(1, Location::Any());
1152 locations->SetOut(Location::SameAsFirstInput());
1153 break;
1154 }
Nicolas Geoffray9cf35522014-06-09 18:40:10 +01001155 case Primitive::kPrimLong: {
Nicolas Geoffrayecb2f9b2014-06-13 08:59:59 +00001156 locations->SetInAt(0, Location::RequiresRegister());
1157 locations->SetInAt(1, Location::RequiresRegister());
1158 locations->SetOut(Location::SameAsFirstInput());
Nicolas Geoffray9cf35522014-06-09 18:40:10 +01001159 break;
1160 }
Calin Juravle11351682014-10-23 15:38:15 +01001161 case Primitive::kPrimFloat:
1162 case Primitive::kPrimDouble: {
1163 locations->SetInAt(0, Location::RequiresFpuRegister());
1164 locations->SetInAt(1, Location::RequiresFpuRegister());
1165 locations->SetOut(Location::SameAsFirstInput());
Nicolas Geoffray9cf35522014-06-09 18:40:10 +01001166 break;
Calin Juravle11351682014-10-23 15:38:15 +01001167 }
Nicolas Geoffray9cf35522014-06-09 18:40:10 +01001168 default:
Calin Juravle11351682014-10-23 15:38:15 +01001169 LOG(FATAL) << "Unexpected sub type " << sub->GetResultType();
Nicolas Geoffray9cf35522014-06-09 18:40:10 +01001170 }
Nicolas Geoffray9cf35522014-06-09 18:40:10 +01001171}
1172
1173void InstructionCodeGeneratorX86_64::VisitSub(HSub* sub) {
1174 LocationSummary* locations = sub->GetLocations();
Calin Juravle11351682014-10-23 15:38:15 +01001175 Location first = locations->InAt(0);
1176 Location second = locations->InAt(1);
1177 DCHECK(first.Equals(locations->Out()));
Nicolas Geoffray9cf35522014-06-09 18:40:10 +01001178 switch (sub->GetResultType()) {
Nicolas Geoffrayecb2f9b2014-06-13 08:59:59 +00001179 case Primitive::kPrimInt: {
Calin Juravle11351682014-10-23 15:38:15 +01001180 if (second.IsRegister()) {
1181 __ subl(first.As<CpuRegister>(), second.As<CpuRegister>());
1182 } else if (second.IsConstant()) {
1183 Immediate imm(second.GetConstant()->AsIntConstant()->GetValue());
1184 __ subl(first.As<CpuRegister>(), imm);
Nicolas Geoffray96f89a22014-07-11 10:57:49 +01001185 } else {
Calin Juravle11351682014-10-23 15:38:15 +01001186 __ subl(first.As<CpuRegister>(), Address(CpuRegister(RSP), second.GetStackIndex()));
Nicolas Geoffray96f89a22014-07-11 10:57:49 +01001187 }
Nicolas Geoffrayecb2f9b2014-06-13 08:59:59 +00001188 break;
1189 }
Nicolas Geoffray9cf35522014-06-09 18:40:10 +01001190 case Primitive::kPrimLong: {
Calin Juravle11351682014-10-23 15:38:15 +01001191 __ subq(first.As<CpuRegister>(), second.As<CpuRegister>());
Nicolas Geoffray9cf35522014-06-09 18:40:10 +01001192 break;
1193 }
1194
Calin Juravle11351682014-10-23 15:38:15 +01001195 case Primitive::kPrimFloat: {
1196 __ subss(first.As<XmmRegister>(), second.As<XmmRegister>());
Nicolas Geoffray9cf35522014-06-09 18:40:10 +01001197 break;
Calin Juravle11351682014-10-23 15:38:15 +01001198 }
1199
1200 case Primitive::kPrimDouble: {
1201 __ subsd(first.As<XmmRegister>(), second.As<XmmRegister>());
1202 break;
1203 }
Nicolas Geoffray9cf35522014-06-09 18:40:10 +01001204
1205 default:
Calin Juravle11351682014-10-23 15:38:15 +01001206 LOG(FATAL) << "Unexpected sub type " << sub->GetResultType();
Nicolas Geoffray9cf35522014-06-09 18:40:10 +01001207 }
1208}
1209
Calin Juravle34bacdf2014-10-07 20:23:36 +01001210void LocationsBuilderX86_64::VisitMul(HMul* mul) {
1211 LocationSummary* locations =
1212 new (GetGraph()->GetArena()) LocationSummary(mul, LocationSummary::kNoCall);
1213 switch (mul->GetResultType()) {
1214 case Primitive::kPrimInt: {
1215 locations->SetInAt(0, Location::RequiresRegister());
1216 locations->SetInAt(1, Location::Any());
1217 locations->SetOut(Location::SameAsFirstInput());
1218 break;
1219 }
1220 case Primitive::kPrimLong: {
1221 locations->SetInAt(0, Location::RequiresRegister());
1222 locations->SetInAt(1, Location::RequiresRegister());
1223 locations->SetOut(Location::SameAsFirstInput());
1224 break;
1225 }
Calin Juravleb5bfa962014-10-21 18:02:24 +01001226 case Primitive::kPrimFloat:
1227 case Primitive::kPrimDouble: {
1228 locations->SetInAt(0, Location::RequiresFpuRegister());
1229 locations->SetInAt(1, Location::RequiresFpuRegister());
1230 locations->SetOut(Location::SameAsFirstInput());
Calin Juravle34bacdf2014-10-07 20:23:36 +01001231 break;
Calin Juravleb5bfa962014-10-21 18:02:24 +01001232 }
Calin Juravle34bacdf2014-10-07 20:23:36 +01001233
1234 default:
Calin Juravleb5bfa962014-10-21 18:02:24 +01001235 LOG(FATAL) << "Unexpected mul type " << mul->GetResultType();
Calin Juravle34bacdf2014-10-07 20:23:36 +01001236 }
1237}
1238
1239void InstructionCodeGeneratorX86_64::VisitMul(HMul* mul) {
1240 LocationSummary* locations = mul->GetLocations();
1241 Location first = locations->InAt(0);
1242 Location second = locations->InAt(1);
1243 DCHECK(first.Equals(locations->Out()));
1244 switch (mul->GetResultType()) {
1245 case Primitive::kPrimInt: {
1246 if (second.IsRegister()) {
1247 __ imull(first.As<CpuRegister>(), second.As<CpuRegister>());
1248 } else if (second.IsConstant()) {
1249 Immediate imm(second.GetConstant()->AsIntConstant()->GetValue());
1250 __ imull(first.As<CpuRegister>(), imm);
1251 } else {
1252 DCHECK(second.IsStackSlot());
1253 __ imull(first.As<CpuRegister>(), Address(CpuRegister(RSP), second.GetStackIndex()));
1254 }
1255 break;
1256 }
1257 case Primitive::kPrimLong: {
1258 __ imulq(first.As<CpuRegister>(), second.As<CpuRegister>());
1259 break;
1260 }
1261
Calin Juravleb5bfa962014-10-21 18:02:24 +01001262 case Primitive::kPrimFloat: {
1263 __ mulss(first.As<XmmRegister>(), second.As<XmmRegister>());
Calin Juravle34bacdf2014-10-07 20:23:36 +01001264 break;
Calin Juravleb5bfa962014-10-21 18:02:24 +01001265 }
1266
1267 case Primitive::kPrimDouble: {
1268 __ mulsd(first.As<XmmRegister>(), second.As<XmmRegister>());
1269 break;
1270 }
Calin Juravle34bacdf2014-10-07 20:23:36 +01001271
1272 default:
Calin Juravleb5bfa962014-10-21 18:02:24 +01001273 LOG(FATAL) << "Unexpected mul type " << mul->GetResultType();
Calin Juravle34bacdf2014-10-07 20:23:36 +01001274 }
1275}
1276
Calin Juravle7c4954d2014-10-28 16:57:40 +00001277void LocationsBuilderX86_64::VisitDiv(HDiv* div) {
1278 LocationSummary* locations =
1279 new (GetGraph()->GetArena()) LocationSummary(div, LocationSummary::kNoCall);
1280 switch (div->GetResultType()) {
1281 case Primitive::kPrimInt:
1282 case Primitive::kPrimLong: {
1283 LOG(FATAL) << "Not implemented div type" << div->GetResultType();
1284 break;
1285 }
1286 case Primitive::kPrimFloat:
1287 case Primitive::kPrimDouble: {
1288 locations->SetInAt(0, Location::RequiresFpuRegister());
1289 locations->SetInAt(1, Location::RequiresFpuRegister());
1290 locations->SetOut(Location::SameAsFirstInput());
1291 break;
1292 }
1293
1294 default:
1295 LOG(FATAL) << "Unexpected div type " << div->GetResultType();
1296 }
1297}
1298
1299void InstructionCodeGeneratorX86_64::VisitDiv(HDiv* div) {
1300 LocationSummary* locations = div->GetLocations();
1301 Location first = locations->InAt(0);
1302 Location second = locations->InAt(1);
1303 DCHECK(first.Equals(locations->Out()));
1304
1305 switch (div->GetResultType()) {
1306 case Primitive::kPrimInt:
1307 case Primitive::kPrimLong: {
1308 LOG(FATAL) << "Not implemented div type" << div->GetResultType();
1309 break;
1310 }
1311
1312 case Primitive::kPrimFloat: {
1313 __ divss(first.As<XmmRegister>(), second.As<XmmRegister>());
1314 break;
1315 }
1316
1317 case Primitive::kPrimDouble: {
1318 __ divsd(first.As<XmmRegister>(), second.As<XmmRegister>());
1319 break;
1320 }
1321
1322 default:
1323 LOG(FATAL) << "Unexpected div type " << div->GetResultType();
1324 }
1325}
1326
Nicolas Geoffray9cf35522014-06-09 18:40:10 +01001327void LocationsBuilderX86_64::VisitNewInstance(HNewInstance* instruction) {
Nicolas Geoffray39468442014-09-02 15:17:15 +01001328 LocationSummary* locations =
1329 new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCall);
Nicolas Geoffray9ae0daa2014-09-30 22:40:23 +01001330 InvokeRuntimeCallingConvention calling_convention;
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +01001331 locations->AddTemp(Location::RegisterLocation(calling_convention.GetRegisterAt(0)));
1332 locations->AddTemp(Location::RegisterLocation(calling_convention.GetRegisterAt(1)));
1333 locations->SetOut(Location::RegisterLocation(RAX));
Nicolas Geoffray9cf35522014-06-09 18:40:10 +01001334}
1335
1336void InstructionCodeGeneratorX86_64::VisitNewInstance(HNewInstance* instruction) {
1337 InvokeRuntimeCallingConvention calling_convention;
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01001338 codegen_->LoadCurrentMethod(CpuRegister(calling_convention.GetRegisterAt(1)));
Nicolas Geoffray9cf35522014-06-09 18:40:10 +01001339 __ movq(CpuRegister(calling_convention.GetRegisterAt(0)), Immediate(instruction->GetTypeIndex()));
1340
1341 __ gs()->call(Address::Absolute(
1342 QUICK_ENTRYPOINT_OFFSET(kX86_64WordSize, pAllocObjectWithAccessCheck), true));
1343
Nicolas Geoffrayf12feb82014-07-17 18:32:41 +01001344 DCHECK(!codegen_->IsLeafMethod());
Nicolas Geoffray39468442014-09-02 15:17:15 +01001345 codegen_->RecordPcInfo(instruction, instruction->GetDexPc());
Nicolas Geoffray9cf35522014-06-09 18:40:10 +01001346}
1347
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01001348void LocationsBuilderX86_64::VisitNewArray(HNewArray* instruction) {
1349 LocationSummary* locations =
1350 new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCall);
1351 InvokeRuntimeCallingConvention calling_convention;
1352 locations->AddTemp(Location::RegisterLocation(calling_convention.GetRegisterAt(0)));
1353 locations->AddTemp(Location::RegisterLocation(calling_convention.GetRegisterAt(1)));
1354 locations->SetOut(Location::RegisterLocation(RAX));
1355 locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(2)));
1356}
1357
1358void InstructionCodeGeneratorX86_64::VisitNewArray(HNewArray* instruction) {
1359 InvokeRuntimeCallingConvention calling_convention;
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01001360 codegen_->LoadCurrentMethod(CpuRegister(calling_convention.GetRegisterAt(1)));
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01001361 __ movq(CpuRegister(calling_convention.GetRegisterAt(0)), Immediate(instruction->GetTypeIndex()));
1362
1363 __ gs()->call(Address::Absolute(
1364 QUICK_ENTRYPOINT_OFFSET(kX86_64WordSize, pAllocArrayWithAccessCheck), true));
1365
1366 DCHECK(!codegen_->IsLeafMethod());
1367 codegen_->RecordPcInfo(instruction, instruction->GetDexPc());
1368}
1369
Nicolas Geoffray9cf35522014-06-09 18:40:10 +01001370void LocationsBuilderX86_64::VisitParameterValue(HParameterValue* instruction) {
Nicolas Geoffray39468442014-09-02 15:17:15 +01001371 LocationSummary* locations =
1372 new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
Nicolas Geoffray9cf35522014-06-09 18:40:10 +01001373 Location location = parameter_visitor_.GetNextLocation(instruction->GetType());
1374 if (location.IsStackSlot()) {
1375 location = Location::StackSlot(location.GetStackIndex() + codegen_->GetFrameSize());
1376 } else if (location.IsDoubleStackSlot()) {
1377 location = Location::DoubleStackSlot(location.GetStackIndex() + codegen_->GetFrameSize());
1378 }
1379 locations->SetOut(location);
Nicolas Geoffray9cf35522014-06-09 18:40:10 +01001380}
1381
1382void InstructionCodeGeneratorX86_64::VisitParameterValue(HParameterValue* instruction) {
1383 // Nothing to do, the parameter is already at its location.
1384}
1385
Roland Levillain1cc5f2512014-10-22 18:06:21 +01001386void LocationsBuilderX86_64::VisitNot(HNot* not_) {
Nicolas Geoffray39468442014-09-02 15:17:15 +01001387 LocationSummary* locations =
Roland Levillain1cc5f2512014-10-22 18:06:21 +01001388 new (GetGraph()->GetArena()) LocationSummary(not_, LocationSummary::kNoCall);
Nicolas Geoffrayecb2f9b2014-06-13 08:59:59 +00001389 locations->SetInAt(0, Location::RequiresRegister());
1390 locations->SetOut(Location::SameAsFirstInput());
Nicolas Geoffray9cf35522014-06-09 18:40:10 +01001391}
1392
Roland Levillain1cc5f2512014-10-22 18:06:21 +01001393void InstructionCodeGeneratorX86_64::VisitNot(HNot* not_) {
1394 LocationSummary* locations = not_->GetLocations();
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +01001395 DCHECK_EQ(locations->InAt(0).As<CpuRegister>().AsRegister(),
1396 locations->Out().As<CpuRegister>().AsRegister());
Roland Levillain1cc5f2512014-10-22 18:06:21 +01001397 Location out = locations->Out();
1398 switch (not_->InputAt(0)->GetType()) {
1399 case Primitive::kPrimBoolean:
1400 __ xorq(out.As<CpuRegister>(), Immediate(1));
1401 break;
1402
1403 case Primitive::kPrimInt:
1404 __ notl(out.As<CpuRegister>());
1405 break;
1406
1407 case Primitive::kPrimLong:
Roland Levillain70566432014-10-24 16:20:17 +01001408 __ notq(out.As<CpuRegister>());
Roland Levillain1cc5f2512014-10-22 18:06:21 +01001409 break;
1410
1411 default:
1412 LOG(FATAL) << "Unimplemented type for not operation " << not_->GetResultType();
1413 }
Nicolas Geoffray9cf35522014-06-09 18:40:10 +01001414}
1415
1416void LocationsBuilderX86_64::VisitPhi(HPhi* instruction) {
Nicolas Geoffray39468442014-09-02 15:17:15 +01001417 LocationSummary* locations =
1418 new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
Nicolas Geoffray9cf35522014-06-09 18:40:10 +01001419 for (size_t i = 0, e = instruction->InputCount(); i < e; ++i) {
1420 locations->SetInAt(i, Location::Any());
1421 }
1422 locations->SetOut(Location::Any());
Nicolas Geoffray9cf35522014-06-09 18:40:10 +01001423}
1424
1425void InstructionCodeGeneratorX86_64::VisitPhi(HPhi* instruction) {
1426 LOG(FATAL) << "Unimplemented";
1427}
1428
Nicolas Geoffraye5038322014-07-04 09:41:32 +01001429void LocationsBuilderX86_64::VisitInstanceFieldSet(HInstanceFieldSet* instruction) {
Nicolas Geoffray39468442014-09-02 15:17:15 +01001430 LocationSummary* locations =
1431 new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
Nicolas Geoffray9ae0daa2014-09-30 22:40:23 +01001432 Primitive::Type field_type = instruction->GetFieldType();
1433 bool is_object_type = field_type == Primitive::kPrimNot;
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +01001434 locations->SetInAt(0, Location::RequiresRegister());
1435 locations->SetInAt(1, Location::RequiresRegister());
Nicolas Geoffray9ae0daa2014-09-30 22:40:23 +01001436 if (is_object_type) {
1437 // Temporary registers for the write barrier.
Nicolas Geoffray1a43dd72014-07-17 15:15:34 +01001438 locations->AddTemp(Location::RequiresRegister());
1439 locations->AddTemp(Location::RequiresRegister());
1440 }
Nicolas Geoffraye5038322014-07-04 09:41:32 +01001441}
1442
1443void InstructionCodeGeneratorX86_64::VisitInstanceFieldSet(HInstanceFieldSet* instruction) {
1444 LocationSummary* locations = instruction->GetLocations();
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +01001445 CpuRegister obj = locations->InAt(0).As<CpuRegister>();
1446 CpuRegister value = locations->InAt(1).As<CpuRegister>();
Nicolas Geoffraye5038322014-07-04 09:41:32 +01001447 size_t offset = instruction->GetFieldOffset().SizeValue();
Nicolas Geoffray39468442014-09-02 15:17:15 +01001448 Primitive::Type field_type = instruction->GetFieldType();
Nicolas Geoffraye5038322014-07-04 09:41:32 +01001449
1450 switch (field_type) {
1451 case Primitive::kPrimBoolean:
1452 case Primitive::kPrimByte: {
1453 __ movb(Address(obj, offset), value);
1454 break;
1455 }
1456
1457 case Primitive::kPrimShort:
1458 case Primitive::kPrimChar: {
1459 __ movw(Address(obj, offset), value);
1460 break;
1461 }
1462
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001463 case Primitive::kPrimInt:
Nicolas Geoffraye5038322014-07-04 09:41:32 +01001464 case Primitive::kPrimNot: {
1465 __ movl(Address(obj, offset), value);
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001466 if (field_type == Primitive::kPrimNot) {
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +01001467 CpuRegister temp = locations->GetTemp(0).As<CpuRegister>();
1468 CpuRegister card = locations->GetTemp(1).As<CpuRegister>();
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001469 codegen_->MarkGCCard(temp, card, obj, value);
1470 }
Nicolas Geoffraye5038322014-07-04 09:41:32 +01001471 break;
1472 }
1473
1474 case Primitive::kPrimLong: {
1475 __ movq(Address(obj, offset), value);
1476 break;
1477 }
1478
1479 case Primitive::kPrimFloat:
1480 case Primitive::kPrimDouble:
1481 LOG(FATAL) << "Unimplemented register type " << field_type;
Ian Rogersfc787ec2014-10-09 21:56:44 -07001482 UNREACHABLE();
Nicolas Geoffraye5038322014-07-04 09:41:32 +01001483 case Primitive::kPrimVoid:
1484 LOG(FATAL) << "Unreachable type " << field_type;
Ian Rogersfc787ec2014-10-09 21:56:44 -07001485 UNREACHABLE();
Nicolas Geoffraye5038322014-07-04 09:41:32 +01001486 }
1487}
1488
1489void LocationsBuilderX86_64::VisitInstanceFieldGet(HInstanceFieldGet* instruction) {
Nicolas Geoffray39468442014-09-02 15:17:15 +01001490 LocationSummary* locations =
1491 new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +01001492 locations->SetInAt(0, Location::RequiresRegister());
1493 locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
Nicolas Geoffraye5038322014-07-04 09:41:32 +01001494}
1495
1496void InstructionCodeGeneratorX86_64::VisitInstanceFieldGet(HInstanceFieldGet* instruction) {
1497 LocationSummary* locations = instruction->GetLocations();
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +01001498 CpuRegister obj = locations->InAt(0).As<CpuRegister>();
1499 CpuRegister out = locations->Out().As<CpuRegister>();
Nicolas Geoffraye5038322014-07-04 09:41:32 +01001500 size_t offset = instruction->GetFieldOffset().SizeValue();
1501
1502 switch (instruction->GetType()) {
1503 case Primitive::kPrimBoolean: {
1504 __ movzxb(out, Address(obj, offset));
1505 break;
1506 }
1507
1508 case Primitive::kPrimByte: {
1509 __ movsxb(out, Address(obj, offset));
1510 break;
1511 }
1512
1513 case Primitive::kPrimShort: {
1514 __ movsxw(out, Address(obj, offset));
1515 break;
1516 }
1517
1518 case Primitive::kPrimChar: {
1519 __ movzxw(out, Address(obj, offset));
1520 break;
1521 }
1522
1523 case Primitive::kPrimInt:
1524 case Primitive::kPrimNot: {
1525 __ movl(out, Address(obj, offset));
1526 break;
1527 }
1528
1529 case Primitive::kPrimLong: {
1530 __ movq(out, Address(obj, offset));
1531 break;
1532 }
1533
1534 case Primitive::kPrimFloat:
1535 case Primitive::kPrimDouble:
1536 LOG(FATAL) << "Unimplemented register type " << instruction->GetType();
Ian Rogersfc787ec2014-10-09 21:56:44 -07001537 UNREACHABLE();
Nicolas Geoffraye5038322014-07-04 09:41:32 +01001538 case Primitive::kPrimVoid:
1539 LOG(FATAL) << "Unreachable type " << instruction->GetType();
Ian Rogersfc787ec2014-10-09 21:56:44 -07001540 UNREACHABLE();
Nicolas Geoffraye5038322014-07-04 09:41:32 +01001541 }
1542}
1543
1544void LocationsBuilderX86_64::VisitNullCheck(HNullCheck* instruction) {
Nicolas Geoffray39468442014-09-02 15:17:15 +01001545 LocationSummary* locations =
1546 new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
Nicolas Geoffraye5038322014-07-04 09:41:32 +01001547 locations->SetInAt(0, Location::Any());
Nicolas Geoffray26a25ef2014-09-30 13:54:09 +01001548 if (instruction->HasUses()) {
1549 locations->SetOut(Location::SameAsFirstInput());
1550 }
Nicolas Geoffraye5038322014-07-04 09:41:32 +01001551}
1552
1553void InstructionCodeGeneratorX86_64::VisitNullCheck(HNullCheck* instruction) {
Nicolas Geoffray92a73ae2014-10-16 11:12:52 +01001554 SlowPathCodeX86_64* slow_path = new (GetGraph()->GetArena()) NullCheckSlowPathX86_64(instruction);
Nicolas Geoffraye5038322014-07-04 09:41:32 +01001555 codegen_->AddSlowPath(slow_path);
1556
1557 LocationSummary* locations = instruction->GetLocations();
1558 Location obj = locations->InAt(0);
Nicolas Geoffraye5038322014-07-04 09:41:32 +01001559
1560 if (obj.IsRegister()) {
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +01001561 __ cmpl(obj.As<CpuRegister>(), Immediate(0));
Nicolas Geoffray26a25ef2014-09-30 13:54:09 +01001562 } else if (obj.IsStackSlot()) {
Nicolas Geoffraye5038322014-07-04 09:41:32 +01001563 __ cmpl(Address(CpuRegister(RSP), obj.GetStackIndex()), Immediate(0));
Nicolas Geoffray26a25ef2014-09-30 13:54:09 +01001564 } else {
1565 DCHECK(obj.IsConstant()) << obj;
1566 DCHECK_EQ(obj.GetConstant()->AsIntConstant()->GetValue(), 0);
1567 __ jmp(slow_path->GetEntryLabel());
1568 return;
Nicolas Geoffraye5038322014-07-04 09:41:32 +01001569 }
1570 __ j(kEqual, slow_path->GetEntryLabel());
1571}
1572
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001573void LocationsBuilderX86_64::VisitArrayGet(HArrayGet* instruction) {
Nicolas Geoffray39468442014-09-02 15:17:15 +01001574 LocationSummary* locations =
1575 new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +01001576 locations->SetInAt(0, Location::RequiresRegister());
Nicolas Geoffray9ae0daa2014-09-30 22:40:23 +01001577 locations->SetInAt(
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +01001578 1, Location::RegisterOrConstant(instruction->InputAt(1)));
1579 locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001580}
1581
1582void InstructionCodeGeneratorX86_64::VisitArrayGet(HArrayGet* instruction) {
1583 LocationSummary* locations = instruction->GetLocations();
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +01001584 CpuRegister obj = locations->InAt(0).As<CpuRegister>();
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001585 Location index = locations->InAt(1);
1586
1587 switch (instruction->GetType()) {
1588 case Primitive::kPrimBoolean: {
1589 uint32_t data_offset = mirror::Array::DataOffset(sizeof(uint8_t)).Uint32Value();
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +01001590 CpuRegister out = locations->Out().As<CpuRegister>();
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001591 if (index.IsConstant()) {
1592 __ movzxb(out, Address(obj,
1593 (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_1) + data_offset));
1594 } else {
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +01001595 __ movzxb(out, Address(obj, index.As<CpuRegister>(), TIMES_1, data_offset));
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001596 }
1597 break;
1598 }
1599
1600 case Primitive::kPrimByte: {
1601 uint32_t data_offset = mirror::Array::DataOffset(sizeof(int8_t)).Uint32Value();
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +01001602 CpuRegister out = locations->Out().As<CpuRegister>();
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001603 if (index.IsConstant()) {
1604 __ movsxb(out, Address(obj,
1605 (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_1) + data_offset));
1606 } else {
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +01001607 __ movsxb(out, Address(obj, index.As<CpuRegister>(), TIMES_1, data_offset));
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001608 }
1609 break;
1610 }
1611
1612 case Primitive::kPrimShort: {
1613 uint32_t data_offset = mirror::Array::DataOffset(sizeof(int16_t)).Uint32Value();
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +01001614 CpuRegister out = locations->Out().As<CpuRegister>();
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001615 if (index.IsConstant()) {
1616 __ movsxw(out, Address(obj,
1617 (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_2) + data_offset));
1618 } else {
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +01001619 __ movsxw(out, Address(obj, index.As<CpuRegister>(), TIMES_2, data_offset));
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001620 }
1621 break;
1622 }
1623
1624 case Primitive::kPrimChar: {
1625 uint32_t data_offset = mirror::Array::DataOffset(sizeof(uint16_t)).Uint32Value();
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +01001626 CpuRegister out = locations->Out().As<CpuRegister>();
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001627 if (index.IsConstant()) {
1628 __ movzxw(out, Address(obj,
1629 (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_2) + data_offset));
1630 } else {
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +01001631 __ movzxw(out, Address(obj, index.As<CpuRegister>(), TIMES_2, data_offset));
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001632 }
1633 break;
1634 }
1635
1636 case Primitive::kPrimInt:
1637 case Primitive::kPrimNot: {
1638 DCHECK_EQ(sizeof(mirror::HeapReference<mirror::Object>), sizeof(int32_t));
1639 uint32_t data_offset = mirror::Array::DataOffset(sizeof(int32_t)).Uint32Value();
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +01001640 CpuRegister out = locations->Out().As<CpuRegister>();
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001641 if (index.IsConstant()) {
1642 __ movl(out, Address(obj,
1643 (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_4) + data_offset));
1644 } else {
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +01001645 __ movl(out, Address(obj, index.As<CpuRegister>(), TIMES_4, data_offset));
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001646 }
1647 break;
1648 }
1649
1650 case Primitive::kPrimLong: {
1651 uint32_t data_offset = mirror::Array::DataOffset(sizeof(int64_t)).Uint32Value();
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +01001652 CpuRegister out = locations->Out().As<CpuRegister>();
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001653 if (index.IsConstant()) {
1654 __ movq(out, Address(obj,
1655 (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_8) + data_offset));
1656 } else {
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +01001657 __ movq(out, Address(obj, index.As<CpuRegister>(), TIMES_8, data_offset));
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001658 }
1659 break;
1660 }
1661
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01001662 case Primitive::kPrimFloat: {
1663 uint32_t data_offset = mirror::Array::DataOffset(sizeof(float)).Uint32Value();
1664 XmmRegister out = locations->Out().As<XmmRegister>();
1665 if (index.IsConstant()) {
1666 __ movss(out, Address(obj,
1667 (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_4) + data_offset));
1668 } else {
1669 __ movss(out, Address(obj, index.As<CpuRegister>(), TIMES_4, data_offset));
1670 }
1671 break;
1672 }
1673
1674 case Primitive::kPrimDouble: {
1675 uint32_t data_offset = mirror::Array::DataOffset(sizeof(double)).Uint32Value();
1676 XmmRegister out = locations->Out().As<XmmRegister>();
1677 if (index.IsConstant()) {
1678 __ movsd(out, Address(obj,
1679 (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_8) + data_offset));
1680 } else {
1681 __ movsd(out, Address(obj, index.As<CpuRegister>(), TIMES_8, data_offset));
1682 }
1683 break;
1684 }
1685
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001686 case Primitive::kPrimVoid:
1687 LOG(FATAL) << "Unreachable type " << instruction->GetType();
Ian Rogersfc787ec2014-10-09 21:56:44 -07001688 UNREACHABLE();
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001689 }
1690}
1691
1692void LocationsBuilderX86_64::VisitArraySet(HArraySet* instruction) {
Nicolas Geoffray39468442014-09-02 15:17:15 +01001693 Primitive::Type value_type = instruction->GetComponentType();
1694 bool is_object = value_type == Primitive::kPrimNot;
1695 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(
1696 instruction, is_object ? LocationSummary::kCall : LocationSummary::kNoCall);
1697 if (is_object) {
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001698 InvokeRuntimeCallingConvention calling_convention;
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +01001699 locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0)));
1700 locations->SetInAt(1, Location::RegisterLocation(calling_convention.GetRegisterAt(1)));
1701 locations->SetInAt(2, Location::RegisterLocation(calling_convention.GetRegisterAt(2)));
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001702 } else {
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +01001703 locations->SetInAt(0, Location::RequiresRegister());
Nicolas Geoffray9ae0daa2014-09-30 22:40:23 +01001704 locations->SetInAt(
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +01001705 1, Location::RegisterOrConstant(instruction->InputAt(1)));
1706 locations->SetInAt(2, Location::RequiresRegister());
Nicolas Geoffray26a25ef2014-09-30 13:54:09 +01001707 if (value_type == Primitive::kPrimLong) {
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +01001708 locations->SetInAt(2, Location::RequiresRegister());
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01001709 } else if (value_type == Primitive::kPrimFloat || value_type == Primitive::kPrimDouble) {
1710 locations->SetInAt(2, Location::RequiresFpuRegister());
Nicolas Geoffray26a25ef2014-09-30 13:54:09 +01001711 } else {
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +01001712 locations->SetInAt(2, Location::RegisterOrConstant(instruction->InputAt(2)));
Nicolas Geoffray26a25ef2014-09-30 13:54:09 +01001713 }
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001714 }
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001715}
1716
1717void InstructionCodeGeneratorX86_64::VisitArraySet(HArraySet* instruction) {
1718 LocationSummary* locations = instruction->GetLocations();
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +01001719 CpuRegister obj = locations->InAt(0).As<CpuRegister>();
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001720 Location index = locations->InAt(1);
Nicolas Geoffray26a25ef2014-09-30 13:54:09 +01001721 Location value = locations->InAt(2);
Nicolas Geoffray39468442014-09-02 15:17:15 +01001722 Primitive::Type value_type = instruction->GetComponentType();
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001723
1724 switch (value_type) {
1725 case Primitive::kPrimBoolean:
1726 case Primitive::kPrimByte: {
1727 uint32_t data_offset = mirror::Array::DataOffset(sizeof(uint8_t)).Uint32Value();
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001728 if (index.IsConstant()) {
1729 size_t offset = (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_1) + data_offset;
Nicolas Geoffray26a25ef2014-09-30 13:54:09 +01001730 if (value.IsRegister()) {
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +01001731 __ movb(Address(obj, offset), value.As<CpuRegister>());
Nicolas Geoffray26a25ef2014-09-30 13:54:09 +01001732 } else {
1733 __ movb(Address(obj, offset), Immediate(value.GetConstant()->AsIntConstant()->GetValue()));
1734 }
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001735 } else {
Nicolas Geoffray26a25ef2014-09-30 13:54:09 +01001736 if (value.IsRegister()) {
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +01001737 __ movb(Address(obj, index.As<CpuRegister>(), TIMES_1, data_offset),
1738 value.As<CpuRegister>());
Nicolas Geoffray26a25ef2014-09-30 13:54:09 +01001739 } else {
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +01001740 __ movb(Address(obj, index.As<CpuRegister>(), TIMES_1, data_offset),
Nicolas Geoffray26a25ef2014-09-30 13:54:09 +01001741 Immediate(value.GetConstant()->AsIntConstant()->GetValue()));
1742 }
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001743 }
1744 break;
1745 }
1746
1747 case Primitive::kPrimShort:
1748 case Primitive::kPrimChar: {
1749 uint32_t data_offset = mirror::Array::DataOffset(sizeof(uint16_t)).Uint32Value();
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001750 if (index.IsConstant()) {
1751 size_t offset = (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_2) + data_offset;
Nicolas Geoffray26a25ef2014-09-30 13:54:09 +01001752 if (value.IsRegister()) {
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +01001753 __ movw(Address(obj, offset), value.As<CpuRegister>());
Nicolas Geoffray26a25ef2014-09-30 13:54:09 +01001754 } else {
1755 __ movw(Address(obj, offset), Immediate(value.GetConstant()->AsIntConstant()->GetValue()));
1756 }
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001757 } else {
Nicolas Geoffray26a25ef2014-09-30 13:54:09 +01001758 if (value.IsRegister()) {
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +01001759 __ movw(Address(obj, index.As<CpuRegister>(), TIMES_2, data_offset),
1760 value.As<CpuRegister>());
Nicolas Geoffray26a25ef2014-09-30 13:54:09 +01001761 } else {
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +01001762 __ movw(Address(obj, index.As<CpuRegister>(), TIMES_2, data_offset),
Nicolas Geoffray26a25ef2014-09-30 13:54:09 +01001763 Immediate(value.GetConstant()->AsIntConstant()->GetValue()));
1764 }
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001765 }
1766 break;
1767 }
1768
1769 case Primitive::kPrimInt: {
1770 uint32_t data_offset = mirror::Array::DataOffset(sizeof(int32_t)).Uint32Value();
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001771 if (index.IsConstant()) {
1772 size_t offset = (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_4) + data_offset;
Nicolas Geoffray26a25ef2014-09-30 13:54:09 +01001773 if (value.IsRegister()) {
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +01001774 __ movl(Address(obj, offset), value.As<CpuRegister>());
Nicolas Geoffray26a25ef2014-09-30 13:54:09 +01001775 } else {
1776 __ movl(Address(obj, offset), Immediate(value.GetConstant()->AsIntConstant()->GetValue()));
1777 }
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001778 } else {
Nicolas Geoffray26a25ef2014-09-30 13:54:09 +01001779 if (value.IsRegister()) {
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +01001780 __ movl(Address(obj, index.As<CpuRegister>(), TIMES_4, data_offset),
1781 value.As<CpuRegister>());
Nicolas Geoffray26a25ef2014-09-30 13:54:09 +01001782 } else {
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01001783 DCHECK(value.IsConstant()) << value;
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +01001784 __ movl(Address(obj, index.As<CpuRegister>(), TIMES_4, data_offset),
Nicolas Geoffray26a25ef2014-09-30 13:54:09 +01001785 Immediate(value.GetConstant()->AsIntConstant()->GetValue()));
1786 }
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001787 }
1788 break;
1789 }
1790
1791 case Primitive::kPrimNot: {
1792 __ gs()->call(Address::Absolute(QUICK_ENTRYPOINT_OFFSET(kX86_64WordSize, pAputObject), true));
1793 DCHECK(!codegen_->IsLeafMethod());
Nicolas Geoffray39468442014-09-02 15:17:15 +01001794 codegen_->RecordPcInfo(instruction, instruction->GetDexPc());
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001795 break;
1796 }
1797
1798 case Primitive::kPrimLong: {
1799 uint32_t data_offset = mirror::Array::DataOffset(sizeof(int64_t)).Uint32Value();
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001800 if (index.IsConstant()) {
1801 size_t offset = (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_8) + data_offset;
Nicolas Geoffray26a25ef2014-09-30 13:54:09 +01001802 DCHECK(value.IsRegister());
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +01001803 __ movq(Address(obj, offset), value.As<CpuRegister>());
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001804 } else {
Nicolas Geoffray26a25ef2014-09-30 13:54:09 +01001805 DCHECK(value.IsRegister());
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +01001806 __ movq(Address(obj, index.As<CpuRegister>(), TIMES_8, data_offset),
1807 value.As<CpuRegister>());
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001808 }
1809 break;
1810 }
1811
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01001812 case Primitive::kPrimFloat: {
1813 uint32_t data_offset = mirror::Array::DataOffset(sizeof(float)).Uint32Value();
1814 if (index.IsConstant()) {
1815 size_t offset = (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_4) + data_offset;
1816 DCHECK(value.IsFpuRegister());
1817 __ movss(Address(obj, offset), value.As<XmmRegister>());
1818 } else {
1819 DCHECK(value.IsFpuRegister());
1820 __ movss(Address(obj, index.As<CpuRegister>(), TIMES_4, data_offset),
1821 value.As<XmmRegister>());
1822 }
1823 break;
1824 }
1825
1826 case Primitive::kPrimDouble: {
1827 uint32_t data_offset = mirror::Array::DataOffset(sizeof(double)).Uint32Value();
1828 if (index.IsConstant()) {
1829 size_t offset = (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_8) + data_offset;
1830 DCHECK(value.IsFpuRegister());
1831 __ movsd(Address(obj, offset), value.As<XmmRegister>());
1832 } else {
1833 DCHECK(value.IsFpuRegister());
1834 __ movsd(Address(obj, index.As<CpuRegister>(), TIMES_8, data_offset),
1835 value.As<XmmRegister>());
1836 }
1837 break;
1838 }
1839
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001840 case Primitive::kPrimVoid:
1841 LOG(FATAL) << "Unreachable type " << instruction->GetType();
Ian Rogersfc787ec2014-10-09 21:56:44 -07001842 UNREACHABLE();
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001843 }
1844}
1845
1846void LocationsBuilderX86_64::VisitArrayLength(HArrayLength* instruction) {
Nicolas Geoffray39468442014-09-02 15:17:15 +01001847 LocationSummary* locations =
1848 new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +01001849 locations->SetInAt(0, Location::RequiresRegister());
1850 locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001851}
1852
1853void InstructionCodeGeneratorX86_64::VisitArrayLength(HArrayLength* instruction) {
1854 LocationSummary* locations = instruction->GetLocations();
1855 uint32_t offset = mirror::Array::LengthOffset().Uint32Value();
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +01001856 CpuRegister obj = locations->InAt(0).As<CpuRegister>();
1857 CpuRegister out = locations->Out().As<CpuRegister>();
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001858 __ movl(out, Address(obj, offset));
1859}
1860
1861void LocationsBuilderX86_64::VisitBoundsCheck(HBoundsCheck* instruction) {
Nicolas Geoffray39468442014-09-02 15:17:15 +01001862 LocationSummary* locations =
1863 new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001864 locations->SetInAt(0, Location::RequiresRegister());
1865 locations->SetInAt(1, Location::RequiresRegister());
Nicolas Geoffray26a25ef2014-09-30 13:54:09 +01001866 if (instruction->HasUses()) {
1867 locations->SetOut(Location::SameAsFirstInput());
1868 }
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001869}
1870
1871void InstructionCodeGeneratorX86_64::VisitBoundsCheck(HBoundsCheck* instruction) {
1872 LocationSummary* locations = instruction->GetLocations();
Nicolas Geoffray92a73ae2014-10-16 11:12:52 +01001873 SlowPathCodeX86_64* slow_path = new (GetGraph()->GetArena()) BoundsCheckSlowPathX86_64(
Nicolas Geoffray39468442014-09-02 15:17:15 +01001874 instruction, locations->InAt(0), locations->InAt(1));
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001875 codegen_->AddSlowPath(slow_path);
1876
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +01001877 CpuRegister index = locations->InAt(0).As<CpuRegister>();
1878 CpuRegister length = locations->InAt(1).As<CpuRegister>();
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001879
1880 __ cmpl(index, length);
1881 __ j(kAboveEqual, slow_path->GetEntryLabel());
1882}
1883
1884void CodeGeneratorX86_64::MarkGCCard(CpuRegister temp,
1885 CpuRegister card,
1886 CpuRegister object,
1887 CpuRegister value) {
1888 Label is_null;
1889 __ testl(value, value);
1890 __ j(kEqual, &is_null);
1891 __ gs()->movq(card, Address::Absolute(
1892 Thread::CardTableOffset<kX86_64WordSize>().Int32Value(), true));
1893 __ movq(temp, object);
1894 __ shrq(temp, Immediate(gc::accounting::CardTable::kCardShift));
1895 __ movb(Address(temp, card, TIMES_1, 0), card);
1896 __ Bind(&is_null);
1897}
1898
Nicolas Geoffraye5038322014-07-04 09:41:32 +01001899void LocationsBuilderX86_64::VisitTemporary(HTemporary* temp) {
1900 temp->SetLocations(nullptr);
1901}
1902
1903void InstructionCodeGeneratorX86_64::VisitTemporary(HTemporary* temp) {
1904 // Nothing to do, this is driven by the code generator.
1905}
1906
Nicolas Geoffray9cf35522014-06-09 18:40:10 +01001907void LocationsBuilderX86_64::VisitParallelMove(HParallelMove* instruction) {
1908 LOG(FATAL) << "Unimplemented";
1909}
1910
1911void InstructionCodeGeneratorX86_64::VisitParallelMove(HParallelMove* instruction) {
Nicolas Geoffrayecb2f9b2014-06-13 08:59:59 +00001912 codegen_->GetMoveResolver()->EmitNativeCode(instruction);
1913}
1914
Nicolas Geoffrayfbc695f2014-09-15 15:33:30 +00001915void LocationsBuilderX86_64::VisitSuspendCheck(HSuspendCheck* instruction) {
1916 new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCallOnSlowPath);
1917}
1918
1919void InstructionCodeGeneratorX86_64::VisitSuspendCheck(HSuspendCheck* instruction) {
Nicolas Geoffray3c049742014-09-24 18:10:46 +01001920 HBasicBlock* block = instruction->GetBlock();
1921 if (block->GetLoopInformation() != nullptr) {
1922 DCHECK(block->GetLoopInformation()->GetSuspendCheck() == instruction);
1923 // The back edge will generate the suspend check.
1924 return;
1925 }
1926 if (block->IsEntryBlock() && instruction->GetNext()->IsGoto()) {
1927 // The goto will generate the suspend check.
1928 return;
1929 }
1930 GenerateSuspendCheck(instruction, nullptr);
1931}
1932
1933void InstructionCodeGeneratorX86_64::GenerateSuspendCheck(HSuspendCheck* instruction,
1934 HBasicBlock* successor) {
Nicolas Geoffrayfbc695f2014-09-15 15:33:30 +00001935 SuspendCheckSlowPathX86_64* slow_path =
Nicolas Geoffray3c049742014-09-24 18:10:46 +01001936 new (GetGraph()->GetArena()) SuspendCheckSlowPathX86_64(instruction, successor);
Nicolas Geoffrayfbc695f2014-09-15 15:33:30 +00001937 codegen_->AddSlowPath(slow_path);
Nicolas Geoffray3c049742014-09-24 18:10:46 +01001938 __ gs()->cmpw(Address::Absolute(
Nicolas Geoffrayfbc695f2014-09-15 15:33:30 +00001939 Thread::ThreadFlagsOffset<kX86_64WordSize>().Int32Value(), true), Immediate(0));
Nicolas Geoffray3c049742014-09-24 18:10:46 +01001940 if (successor == nullptr) {
1941 __ j(kNotEqual, slow_path->GetEntryLabel());
1942 __ Bind(slow_path->GetReturnLabel());
1943 } else {
1944 __ j(kEqual, codegen_->GetLabelOf(successor));
1945 __ jmp(slow_path->GetEntryLabel());
1946 }
Nicolas Geoffrayfbc695f2014-09-15 15:33:30 +00001947}
1948
Nicolas Geoffrayecb2f9b2014-06-13 08:59:59 +00001949X86_64Assembler* ParallelMoveResolverX86_64::GetAssembler() const {
1950 return codegen_->GetAssembler();
1951}
1952
1953void ParallelMoveResolverX86_64::EmitMove(size_t index) {
1954 MoveOperands* move = moves_.Get(index);
1955 Location source = move->GetSource();
1956 Location destination = move->GetDestination();
1957
1958 if (source.IsRegister()) {
1959 if (destination.IsRegister()) {
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +01001960 __ movq(destination.As<CpuRegister>(), source.As<CpuRegister>());
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01001961 } else if (destination.IsStackSlot()) {
Nicolas Geoffrayecb2f9b2014-06-13 08:59:59 +00001962 __ movl(Address(CpuRegister(RSP), destination.GetStackIndex()),
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +01001963 source.As<CpuRegister>());
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01001964 } else {
1965 DCHECK(destination.IsDoubleStackSlot());
1966 __ movq(Address(CpuRegister(RSP), destination.GetStackIndex()),
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +01001967 source.As<CpuRegister>());
Nicolas Geoffrayecb2f9b2014-06-13 08:59:59 +00001968 }
1969 } else if (source.IsStackSlot()) {
1970 if (destination.IsRegister()) {
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +01001971 __ movl(destination.As<CpuRegister>(),
Nicolas Geoffrayecb2f9b2014-06-13 08:59:59 +00001972 Address(CpuRegister(RSP), source.GetStackIndex()));
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01001973 } else if (destination.IsFpuRegister()) {
1974 __ movss(destination.As<XmmRegister>(),
1975 Address(CpuRegister(RSP), source.GetStackIndex()));
Nicolas Geoffrayecb2f9b2014-06-13 08:59:59 +00001976 } else {
1977 DCHECK(destination.IsStackSlot());
1978 __ movl(CpuRegister(TMP), Address(CpuRegister(RSP), source.GetStackIndex()));
1979 __ movl(Address(CpuRegister(RSP), destination.GetStackIndex()), CpuRegister(TMP));
1980 }
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01001981 } else if (source.IsDoubleStackSlot()) {
1982 if (destination.IsRegister()) {
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +01001983 __ movq(destination.As<CpuRegister>(),
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01001984 Address(CpuRegister(RSP), source.GetStackIndex()));
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01001985 } else if (destination.IsFpuRegister()) {
1986 __ movsd(destination.As<XmmRegister>(), Address(CpuRegister(RSP), source.GetStackIndex()));
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01001987 } else {
Nicolas Geoffrayc8147a72014-10-21 16:06:20 +01001988 DCHECK(destination.IsDoubleStackSlot()) << destination;
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01001989 __ movq(CpuRegister(TMP), Address(CpuRegister(RSP), source.GetStackIndex()));
1990 __ movq(Address(CpuRegister(RSP), destination.GetStackIndex()), CpuRegister(TMP));
1991 }
Nicolas Geoffray96f89a22014-07-11 10:57:49 +01001992 } else if (source.IsConstant()) {
1993 HConstant* constant = source.GetConstant();
1994 if (constant->IsIntConstant()) {
1995 Immediate imm(constant->AsIntConstant()->GetValue());
1996 if (destination.IsRegister()) {
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +01001997 __ movl(destination.As<CpuRegister>(), imm);
Nicolas Geoffray96f89a22014-07-11 10:57:49 +01001998 } else {
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01001999 DCHECK(destination.IsStackSlot()) << destination;
Nicolas Geoffray96f89a22014-07-11 10:57:49 +01002000 __ movl(Address(CpuRegister(RSP), destination.GetStackIndex()), imm);
2001 }
2002 } else if (constant->IsLongConstant()) {
2003 int64_t value = constant->AsLongConstant()->GetValue();
2004 if (destination.IsRegister()) {
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +01002005 __ movq(destination.As<CpuRegister>(), Immediate(value));
Nicolas Geoffray96f89a22014-07-11 10:57:49 +01002006 } else {
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01002007 DCHECK(destination.IsDoubleStackSlot()) << destination;
Nicolas Geoffray96f89a22014-07-11 10:57:49 +01002008 __ movq(CpuRegister(TMP), Immediate(value));
2009 __ movq(Address(CpuRegister(RSP), destination.GetStackIndex()), CpuRegister(TMP));
2010 }
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01002011 } else if (constant->IsFloatConstant()) {
2012 Immediate imm(bit_cast<float, int32_t>(constant->AsFloatConstant()->GetValue()));
2013 if (destination.IsFpuRegister()) {
2014 __ movl(CpuRegister(TMP), imm);
2015 __ movd(destination.As<XmmRegister>(), CpuRegister(TMP));
2016 } else {
2017 DCHECK(destination.IsStackSlot()) << destination;
2018 __ movl(Address(CpuRegister(RSP), destination.GetStackIndex()), imm);
2019 }
Nicolas Geoffray96f89a22014-07-11 10:57:49 +01002020 } else {
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01002021 DCHECK(constant->IsDoubleConstant()) << constant->DebugName();
2022 Immediate imm(bit_cast<double, int64_t>(constant->AsDoubleConstant()->GetValue()));
2023 if (destination.IsFpuRegister()) {
2024 __ movq(CpuRegister(TMP), imm);
2025 __ movd(destination.As<XmmRegister>(), CpuRegister(TMP));
2026 } else {
2027 DCHECK(destination.IsDoubleStackSlot()) << destination;
2028 __ movq(CpuRegister(TMP), imm);
2029 __ movq(Address(CpuRegister(RSP), destination.GetStackIndex()), CpuRegister(TMP));
2030 }
Nicolas Geoffray96f89a22014-07-11 10:57:49 +01002031 }
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01002032 } else if (source.IsFpuRegister()) {
2033 if (destination.IsFpuRegister()) {
2034 __ movaps(destination.As<XmmRegister>(), source.As<XmmRegister>());
2035 } else if (destination.IsStackSlot()) {
2036 __ movss(Address(CpuRegister(RSP), destination.GetStackIndex()),
2037 source.As<XmmRegister>());
2038 } else {
2039 DCHECK(destination.IsDoubleStackSlot());
2040 __ movsd(Address(CpuRegister(RSP), destination.GetStackIndex()),
2041 source.As<XmmRegister>());
2042 }
Nicolas Geoffrayecb2f9b2014-06-13 08:59:59 +00002043 }
2044}
2045
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01002046void ParallelMoveResolverX86_64::Exchange32(CpuRegister reg, int mem) {
Nicolas Geoffrayecb2f9b2014-06-13 08:59:59 +00002047 __ movl(CpuRegister(TMP), Address(CpuRegister(RSP), mem));
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01002048 __ movl(Address(CpuRegister(RSP), mem), reg);
2049 __ movl(reg, CpuRegister(TMP));
Nicolas Geoffrayecb2f9b2014-06-13 08:59:59 +00002050}
2051
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01002052void ParallelMoveResolverX86_64::Exchange32(int mem1, int mem2) {
Nicolas Geoffrayecb2f9b2014-06-13 08:59:59 +00002053 ScratchRegisterScope ensure_scratch(
2054 this, TMP, RAX, codegen_->GetNumberOfCoreRegisters());
2055
2056 int stack_offset = ensure_scratch.IsSpilled() ? kX86_64WordSize : 0;
2057 __ movl(CpuRegister(TMP), Address(CpuRegister(RSP), mem1 + stack_offset));
2058 __ movl(CpuRegister(ensure_scratch.GetRegister()),
2059 Address(CpuRegister(RSP), mem2 + stack_offset));
2060 __ movl(Address(CpuRegister(RSP), mem2 + stack_offset), CpuRegister(TMP));
2061 __ movl(Address(CpuRegister(RSP), mem1 + stack_offset),
2062 CpuRegister(ensure_scratch.GetRegister()));
2063}
2064
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01002065void ParallelMoveResolverX86_64::Exchange64(CpuRegister reg, int mem) {
2066 __ movq(CpuRegister(TMP), Address(CpuRegister(RSP), mem));
2067 __ movq(Address(CpuRegister(RSP), mem), reg);
2068 __ movq(reg, CpuRegister(TMP));
2069}
2070
2071void ParallelMoveResolverX86_64::Exchange64(int mem1, int mem2) {
2072 ScratchRegisterScope ensure_scratch(
2073 this, TMP, RAX, codegen_->GetNumberOfCoreRegisters());
2074
2075 int stack_offset = ensure_scratch.IsSpilled() ? kX86_64WordSize : 0;
2076 __ movq(CpuRegister(TMP), Address(CpuRegister(RSP), mem1 + stack_offset));
2077 __ movq(CpuRegister(ensure_scratch.GetRegister()),
2078 Address(CpuRegister(RSP), mem2 + stack_offset));
2079 __ movq(Address(CpuRegister(RSP), mem2 + stack_offset), CpuRegister(TMP));
2080 __ movq(Address(CpuRegister(RSP), mem1 + stack_offset),
2081 CpuRegister(ensure_scratch.GetRegister()));
2082}
2083
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01002084void ParallelMoveResolverX86_64::Exchange32(XmmRegister reg, int mem) {
2085 __ movl(CpuRegister(TMP), Address(CpuRegister(RSP), mem));
2086 __ movss(Address(CpuRegister(RSP), mem), reg);
2087 __ movd(reg, CpuRegister(TMP));
2088}
2089
2090void ParallelMoveResolverX86_64::Exchange64(XmmRegister reg, int mem) {
2091 __ movq(CpuRegister(TMP), Address(CpuRegister(RSP), mem));
2092 __ movsd(Address(CpuRegister(RSP), mem), reg);
2093 __ movd(reg, CpuRegister(TMP));
2094}
2095
Nicolas Geoffrayecb2f9b2014-06-13 08:59:59 +00002096void ParallelMoveResolverX86_64::EmitSwap(size_t index) {
2097 MoveOperands* move = moves_.Get(index);
2098 Location source = move->GetSource();
2099 Location destination = move->GetDestination();
2100
2101 if (source.IsRegister() && destination.IsRegister()) {
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +01002102 __ xchgq(destination.As<CpuRegister>(), source.As<CpuRegister>());
Nicolas Geoffrayecb2f9b2014-06-13 08:59:59 +00002103 } else if (source.IsRegister() && destination.IsStackSlot()) {
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +01002104 Exchange32(source.As<CpuRegister>(), destination.GetStackIndex());
Nicolas Geoffrayecb2f9b2014-06-13 08:59:59 +00002105 } else if (source.IsStackSlot() && destination.IsRegister()) {
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +01002106 Exchange32(destination.As<CpuRegister>(), source.GetStackIndex());
Nicolas Geoffrayecb2f9b2014-06-13 08:59:59 +00002107 } else if (source.IsStackSlot() && destination.IsStackSlot()) {
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01002108 Exchange32(destination.GetStackIndex(), source.GetStackIndex());
2109 } else if (source.IsRegister() && destination.IsDoubleStackSlot()) {
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +01002110 Exchange64(source.As<CpuRegister>(), destination.GetStackIndex());
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01002111 } else if (source.IsDoubleStackSlot() && destination.IsRegister()) {
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +01002112 Exchange64(destination.As<CpuRegister>(), source.GetStackIndex());
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01002113 } else if (source.IsDoubleStackSlot() && destination.IsDoubleStackSlot()) {
2114 Exchange64(destination.GetStackIndex(), source.GetStackIndex());
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01002115 } else if (source.IsFpuRegister() && destination.IsFpuRegister()) {
2116 __ movd(CpuRegister(TMP), source.As<XmmRegister>());
2117 __ movaps(source.As<XmmRegister>(), destination.As<XmmRegister>());
2118 __ movd(destination.As<XmmRegister>(), CpuRegister(TMP));
2119 } else if (source.IsFpuRegister() && destination.IsStackSlot()) {
2120 Exchange32(source.As<XmmRegister>(), destination.GetStackIndex());
2121 } else if (source.IsStackSlot() && destination.IsFpuRegister()) {
2122 Exchange32(destination.As<XmmRegister>(), source.GetStackIndex());
2123 } else if (source.IsFpuRegister() && destination.IsDoubleStackSlot()) {
2124 Exchange64(source.As<XmmRegister>(), destination.GetStackIndex());
2125 } else if (source.IsDoubleStackSlot() && destination.IsFpuRegister()) {
2126 Exchange64(destination.As<XmmRegister>(), source.GetStackIndex());
Nicolas Geoffrayecb2f9b2014-06-13 08:59:59 +00002127 } else {
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01002128 LOG(FATAL) << "Unimplemented swap between " << source << " and " << destination;
Nicolas Geoffrayecb2f9b2014-06-13 08:59:59 +00002129 }
2130}
2131
2132
2133void ParallelMoveResolverX86_64::SpillScratch(int reg) {
2134 __ pushq(CpuRegister(reg));
2135}
2136
2137
2138void ParallelMoveResolverX86_64::RestoreScratch(int reg) {
2139 __ popq(CpuRegister(reg));
Nicolas Geoffray9cf35522014-06-09 18:40:10 +01002140}
2141
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01002142void LocationsBuilderX86_64::VisitLoadClass(HLoadClass* cls) {
2143 LocationSummary* locations =
2144 new (GetGraph()->GetArena()) LocationSummary(cls, LocationSummary::kNoCall);
2145 locations->SetOut(Location::RequiresRegister());
2146}
2147
2148void InstructionCodeGeneratorX86_64::VisitLoadClass(HLoadClass* cls) {
2149 CpuRegister out = cls->GetLocations()->Out().As<CpuRegister>();
2150 if (cls->IsReferrersClass()) {
2151 codegen_->LoadCurrentMethod(out);
2152 __ movl(out, Address(out, mirror::ArtMethod::DeclaringClassOffset().Int32Value()));
2153 } else {
2154 codegen_->LoadCurrentMethod(out);
2155 __ movl(out, Address(out, mirror::ArtMethod::DexCacheResolvedTypesOffset().Int32Value()));
2156 __ movl(out, Address(out, CodeGenerator::GetCacheOffset(cls->GetTypeIndex())));
2157 }
2158}
2159
2160void LocationsBuilderX86_64::VisitClinitCheck(HClinitCheck* check) {
2161 LocationSummary* locations =
2162 new (GetGraph()->GetArena()) LocationSummary(check, LocationSummary::kCallOnSlowPath);
2163 locations->SetInAt(0, Location::RequiresRegister());
2164 if (check->HasUses()) {
2165 locations->SetOut(Location::SameAsFirstInput());
2166 }
2167}
2168
2169void InstructionCodeGeneratorX86_64::VisitClinitCheck(HClinitCheck* check) {
2170 SlowPathCodeX86_64* slow_path = new (GetGraph()->GetArena()) ClinitCheckSlowPathX86_64(check);
2171 codegen_->AddSlowPath(slow_path);
2172
2173 LocationSummary* locations = check->GetLocations();
2174 // We remove the class as a live register, we know it's null or unused in the slow path.
2175 RegisterSet* register_set = locations->GetLiveRegisters();
2176 register_set->Remove(locations->InAt(0));
2177
2178 CpuRegister class_reg = locations->InAt(0).As<CpuRegister>();
2179 __ testl(class_reg, class_reg);
2180 __ j(kEqual, slow_path->GetEntryLabel());
2181 __ cmpl(Address(class_reg, mirror::Class::StatusOffset().Int32Value()),
2182 Immediate(mirror::Class::kStatusInitialized));
2183 __ j(kLess, slow_path->GetEntryLabel());
2184 __ Bind(slow_path->GetExitLabel());
2185 // No need for memory fence, thanks to the X86_64 memory model.
2186}
2187
2188void LocationsBuilderX86_64::VisitStaticFieldGet(HStaticFieldGet* instruction) {
2189 LocationSummary* locations =
2190 new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
2191 locations->SetInAt(0, Location::RequiresRegister());
2192 locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
2193}
2194
2195void InstructionCodeGeneratorX86_64::VisitStaticFieldGet(HStaticFieldGet* instruction) {
2196 LocationSummary* locations = instruction->GetLocations();
2197 CpuRegister cls = locations->InAt(0).As<CpuRegister>();
2198 CpuRegister out = locations->Out().As<CpuRegister>();
2199 size_t offset = instruction->GetFieldOffset().SizeValue();
2200
2201 switch (instruction->GetType()) {
2202 case Primitive::kPrimBoolean: {
2203 __ movzxb(out, Address(cls, offset));
2204 break;
2205 }
2206
2207 case Primitive::kPrimByte: {
2208 __ movsxb(out, Address(cls, offset));
2209 break;
2210 }
2211
2212 case Primitive::kPrimShort: {
2213 __ movsxw(out, Address(cls, offset));
2214 break;
2215 }
2216
2217 case Primitive::kPrimChar: {
2218 __ movzxw(out, Address(cls, offset));
2219 break;
2220 }
2221
2222 case Primitive::kPrimInt:
2223 case Primitive::kPrimNot: {
2224 __ movl(out, Address(cls, offset));
2225 break;
2226 }
2227
2228 case Primitive::kPrimLong: {
2229 __ movq(out, Address(cls, offset));
2230 break;
2231 }
2232
2233 case Primitive::kPrimFloat:
2234 case Primitive::kPrimDouble:
2235 LOG(FATAL) << "Unimplemented register type " << instruction->GetType();
2236 UNREACHABLE();
2237 case Primitive::kPrimVoid:
2238 LOG(FATAL) << "Unreachable type " << instruction->GetType();
2239 UNREACHABLE();
2240 }
2241}
2242
2243void LocationsBuilderX86_64::VisitStaticFieldSet(HStaticFieldSet* instruction) {
2244 LocationSummary* locations =
2245 new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
2246 Primitive::Type field_type = instruction->GetFieldType();
2247 bool is_object_type = field_type == Primitive::kPrimNot;
2248 locations->SetInAt(0, Location::RequiresRegister());
2249 locations->SetInAt(1, Location::RequiresRegister());
2250 if (is_object_type) {
2251 // Temporary registers for the write barrier.
2252 locations->AddTemp(Location::RequiresRegister());
2253 locations->AddTemp(Location::RequiresRegister());
2254 }
2255}
2256
2257void InstructionCodeGeneratorX86_64::VisitStaticFieldSet(HStaticFieldSet* instruction) {
2258 LocationSummary* locations = instruction->GetLocations();
2259 CpuRegister cls = locations->InAt(0).As<CpuRegister>();
2260 CpuRegister value = locations->InAt(1).As<CpuRegister>();
2261 size_t offset = instruction->GetFieldOffset().SizeValue();
2262 Primitive::Type field_type = instruction->GetFieldType();
2263
2264 switch (field_type) {
2265 case Primitive::kPrimBoolean:
2266 case Primitive::kPrimByte: {
2267 __ movb(Address(cls, offset), value);
2268 break;
2269 }
2270
2271 case Primitive::kPrimShort:
2272 case Primitive::kPrimChar: {
2273 __ movw(Address(cls, offset), value);
2274 break;
2275 }
2276
2277 case Primitive::kPrimInt:
2278 case Primitive::kPrimNot: {
2279 __ movl(Address(cls, offset), value);
2280 if (field_type == Primitive::kPrimNot) {
2281 CpuRegister temp = locations->GetTemp(0).As<CpuRegister>();
2282 CpuRegister card = locations->GetTemp(1).As<CpuRegister>();
2283 codegen_->MarkGCCard(temp, card, cls, value);
2284 }
2285 break;
2286 }
2287
2288 case Primitive::kPrimLong: {
2289 __ movq(Address(cls, offset), value);
2290 break;
2291 }
2292
2293 case Primitive::kPrimFloat:
2294 case Primitive::kPrimDouble:
2295 LOG(FATAL) << "Unimplemented register type " << field_type;
2296 UNREACHABLE();
2297 case Primitive::kPrimVoid:
2298 LOG(FATAL) << "Unreachable type " << field_type;
2299 UNREACHABLE();
2300 }
2301}
2302
Nicolas Geoffrayb5f62b32014-10-30 10:58:41 +00002303void LocationsBuilderX86_64::VisitLoadString(HLoadString* load) {
2304 LocationSummary* locations =
2305 new (GetGraph()->GetArena()) LocationSummary(load, LocationSummary::kCallOnSlowPath);
2306 locations->SetOut(Location::RequiresRegister());
2307}
2308
2309void InstructionCodeGeneratorX86_64::VisitLoadString(HLoadString* load) {
2310 SlowPathCodeX86_64* slow_path = new (GetGraph()->GetArena()) LoadStringSlowPathX86_64(load);
2311 codegen_->AddSlowPath(slow_path);
2312
2313 CpuRegister out = load->GetLocations()->Out().As<CpuRegister>();
2314 codegen_->LoadCurrentMethod(CpuRegister(out));
2315 __ movl(out, Address(out, mirror::ArtMethod::DexCacheStringsOffset().Int32Value()));
2316 __ movl(out, Address(out, CodeGenerator::GetCacheOffset(load->GetStringIndex())));
2317 __ testl(out, out);
2318 __ j(kEqual, slow_path->GetEntryLabel());
2319 __ Bind(slow_path->GetExitLabel());
2320}
2321
Nicolas Geoffray9cf35522014-06-09 18:40:10 +01002322} // namespace x86_64
2323} // namespace art