code_generator_x86_64.cc revision 94015b939060f5041d408d48717f22443e55b6ad
1/*
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 "art_method.h"
20#include "code_generator_utils.h"
21#include "entrypoints/quick/quick_entrypoints.h"
22#include "gc/accounting/card_table.h"
23#include "intrinsics.h"
24#include "intrinsics_x86_64.h"
25#include "mirror/array-inl.h"
26#include "mirror/class-inl.h"
27#include "mirror/object_reference.h"
28#include "thread.h"
29#include "utils/assembler.h"
30#include "utils/stack_checks.h"
31#include "utils/x86_64/assembler_x86_64.h"
32#include "utils/x86_64/managed_register_x86_64.h"
33
34namespace art {
35
36namespace x86_64 {
37
38// Some x86_64 instructions require a register to be available as temp.
39static constexpr Register TMP = R11;
40
41static constexpr int kCurrentMethodStackOffset = 0;
42static constexpr Register kMethodRegisterArgument = RDI;
43
44static constexpr Register kCoreCalleeSaves[] = { RBX, RBP, R12, R13, R14, R15 };
45static constexpr FloatRegister kFpuCalleeSaves[] = { XMM12, XMM13, XMM14, XMM15 };
46
47static constexpr int kC2ConditionMask = 0x400;
48
49#define __ down_cast<X86_64Assembler*>(codegen->GetAssembler())->
50
51class NullCheckSlowPathX86_64 : public SlowPathCodeX86_64 {
52 public:
53  explicit NullCheckSlowPathX86_64(HNullCheck* instruction) : instruction_(instruction) {}
54
55  void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
56    __ Bind(GetEntryLabel());
57    __ gs()->call(
58        Address::Absolute(QUICK_ENTRYPOINT_OFFSET(kX86_64WordSize, pThrowNullPointer), true));
59    RecordPcInfo(codegen, instruction_, instruction_->GetDexPc());
60  }
61
62 private:
63  HNullCheck* const instruction_;
64  DISALLOW_COPY_AND_ASSIGN(NullCheckSlowPathX86_64);
65};
66
67class DivZeroCheckSlowPathX86_64 : public SlowPathCodeX86_64 {
68 public:
69  explicit DivZeroCheckSlowPathX86_64(HDivZeroCheck* instruction) : instruction_(instruction) {}
70
71  void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
72    __ Bind(GetEntryLabel());
73    __ gs()->call(
74        Address::Absolute(QUICK_ENTRYPOINT_OFFSET(kX86_64WordSize, pThrowDivZero), true));
75    RecordPcInfo(codegen, instruction_, instruction_->GetDexPc());
76  }
77
78 private:
79  HDivZeroCheck* const instruction_;
80  DISALLOW_COPY_AND_ASSIGN(DivZeroCheckSlowPathX86_64);
81};
82
83class DivRemMinusOneSlowPathX86_64 : public SlowPathCodeX86_64 {
84 public:
85  explicit DivRemMinusOneSlowPathX86_64(Register reg, Primitive::Type type, bool is_div)
86      : cpu_reg_(CpuRegister(reg)), type_(type), is_div_(is_div) {}
87
88  void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
89    __ Bind(GetEntryLabel());
90    if (type_ == Primitive::kPrimInt) {
91      if (is_div_) {
92        __ negl(cpu_reg_);
93      } else {
94        __ movl(cpu_reg_, Immediate(0));
95      }
96
97    } else {
98      DCHECK_EQ(Primitive::kPrimLong, type_);
99      if (is_div_) {
100        __ negq(cpu_reg_);
101      } else {
102        __ xorl(cpu_reg_, cpu_reg_);
103      }
104    }
105    __ jmp(GetExitLabel());
106  }
107
108 private:
109  const CpuRegister cpu_reg_;
110  const Primitive::Type type_;
111  const bool is_div_;
112  DISALLOW_COPY_AND_ASSIGN(DivRemMinusOneSlowPathX86_64);
113};
114
115class SuspendCheckSlowPathX86_64 : public SlowPathCodeX86_64 {
116 public:
117  explicit SuspendCheckSlowPathX86_64(HSuspendCheck* instruction, HBasicBlock* successor)
118      : instruction_(instruction), successor_(successor) {}
119
120  void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
121    CodeGeneratorX86_64* x64_codegen = down_cast<CodeGeneratorX86_64*>(codegen);
122    __ Bind(GetEntryLabel());
123    SaveLiveRegisters(codegen, instruction_->GetLocations());
124    __ gs()->call(Address::Absolute(QUICK_ENTRYPOINT_OFFSET(kX86_64WordSize, pTestSuspend), true));
125    RecordPcInfo(codegen, instruction_, instruction_->GetDexPc());
126    RestoreLiveRegisters(codegen, instruction_->GetLocations());
127    if (successor_ == nullptr) {
128      __ jmp(GetReturnLabel());
129    } else {
130      __ jmp(x64_codegen->GetLabelOf(successor_));
131    }
132  }
133
134  Label* GetReturnLabel() {
135    DCHECK(successor_ == nullptr);
136    return &return_label_;
137  }
138
139  HBasicBlock* GetSuccessor() const {
140    return successor_;
141  }
142
143 private:
144  HSuspendCheck* const instruction_;
145  HBasicBlock* const successor_;
146  Label return_label_;
147
148  DISALLOW_COPY_AND_ASSIGN(SuspendCheckSlowPathX86_64);
149};
150
151class BoundsCheckSlowPathX86_64 : public SlowPathCodeX86_64 {
152 public:
153  BoundsCheckSlowPathX86_64(HBoundsCheck* instruction,
154                            Location index_location,
155                            Location length_location)
156      : instruction_(instruction),
157        index_location_(index_location),
158        length_location_(length_location) {}
159
160  void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
161    __ Bind(GetEntryLabel());
162    // We're moving two locations to locations that could overlap, so we need a parallel
163    // move resolver.
164    InvokeRuntimeCallingConvention calling_convention;
165    codegen->EmitParallelMoves(
166        index_location_,
167        Location::RegisterLocation(calling_convention.GetRegisterAt(0)),
168        Primitive::kPrimInt,
169        length_location_,
170        Location::RegisterLocation(calling_convention.GetRegisterAt(1)),
171        Primitive::kPrimInt);
172    __ gs()->call(Address::Absolute(
173        QUICK_ENTRYPOINT_OFFSET(kX86_64WordSize, pThrowArrayBounds), true));
174    RecordPcInfo(codegen, instruction_, instruction_->GetDexPc());
175  }
176
177 private:
178  HBoundsCheck* const instruction_;
179  const Location index_location_;
180  const Location length_location_;
181
182  DISALLOW_COPY_AND_ASSIGN(BoundsCheckSlowPathX86_64);
183};
184
185class LoadClassSlowPathX86_64 : public SlowPathCodeX86_64 {
186 public:
187  LoadClassSlowPathX86_64(HLoadClass* cls,
188                          HInstruction* at,
189                          uint32_t dex_pc,
190                          bool do_clinit)
191      : cls_(cls), at_(at), dex_pc_(dex_pc), do_clinit_(do_clinit) {
192    DCHECK(at->IsLoadClass() || at->IsClinitCheck());
193  }
194
195  void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
196    LocationSummary* locations = at_->GetLocations();
197    CodeGeneratorX86_64* x64_codegen = down_cast<CodeGeneratorX86_64*>(codegen);
198    __ Bind(GetEntryLabel());
199
200    SaveLiveRegisters(codegen, locations);
201
202    InvokeRuntimeCallingConvention calling_convention;
203    __ movl(CpuRegister(calling_convention.GetRegisterAt(0)), Immediate(cls_->GetTypeIndex()));
204    __ gs()->call(Address::Absolute((do_clinit_
205          ? QUICK_ENTRYPOINT_OFFSET(kX86_64WordSize, pInitializeStaticStorage)
206          : QUICK_ENTRYPOINT_OFFSET(kX86_64WordSize, pInitializeType)) , true));
207    RecordPcInfo(codegen, at_, dex_pc_);
208
209    Location out = locations->Out();
210    // Move the class to the desired location.
211    if (out.IsValid()) {
212      DCHECK(out.IsRegister() && !locations->GetLiveRegisters()->ContainsCoreRegister(out.reg()));
213      x64_codegen->Move(out, Location::RegisterLocation(RAX));
214    }
215
216    RestoreLiveRegisters(codegen, locations);
217    __ jmp(GetExitLabel());
218  }
219
220 private:
221  // The class this slow path will load.
222  HLoadClass* const cls_;
223
224  // The instruction where this slow path is happening.
225  // (Might be the load class or an initialization check).
226  HInstruction* const at_;
227
228  // The dex PC of `at_`.
229  const uint32_t dex_pc_;
230
231  // Whether to initialize the class.
232  const bool do_clinit_;
233
234  DISALLOW_COPY_AND_ASSIGN(LoadClassSlowPathX86_64);
235};
236
237class LoadStringSlowPathX86_64 : public SlowPathCodeX86_64 {
238 public:
239  explicit LoadStringSlowPathX86_64(HLoadString* instruction) : instruction_(instruction) {}
240
241  void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
242    LocationSummary* locations = instruction_->GetLocations();
243    DCHECK(!locations->GetLiveRegisters()->ContainsCoreRegister(locations->Out().reg()));
244
245    CodeGeneratorX86_64* x64_codegen = down_cast<CodeGeneratorX86_64*>(codegen);
246    __ Bind(GetEntryLabel());
247    SaveLiveRegisters(codegen, locations);
248
249    InvokeRuntimeCallingConvention calling_convention;
250    __ movl(CpuRegister(calling_convention.GetRegisterAt(0)),
251            Immediate(instruction_->GetStringIndex()));
252    __ gs()->call(Address::Absolute(
253        QUICK_ENTRYPOINT_OFFSET(kX86_64WordSize, pResolveString), true));
254    RecordPcInfo(codegen, instruction_, instruction_->GetDexPc());
255    x64_codegen->Move(locations->Out(), Location::RegisterLocation(RAX));
256    RestoreLiveRegisters(codegen, locations);
257    __ jmp(GetExitLabel());
258  }
259
260 private:
261  HLoadString* const instruction_;
262
263  DISALLOW_COPY_AND_ASSIGN(LoadStringSlowPathX86_64);
264};
265
266class TypeCheckSlowPathX86_64 : public SlowPathCodeX86_64 {
267 public:
268  TypeCheckSlowPathX86_64(HInstruction* instruction,
269                          Location class_to_check,
270                          Location object_class,
271                          uint32_t dex_pc)
272      : instruction_(instruction),
273        class_to_check_(class_to_check),
274        object_class_(object_class),
275        dex_pc_(dex_pc) {}
276
277  void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
278    LocationSummary* locations = instruction_->GetLocations();
279    DCHECK(instruction_->IsCheckCast()
280           || !locations->GetLiveRegisters()->ContainsCoreRegister(locations->Out().reg()));
281
282    CodeGeneratorX86_64* x64_codegen = down_cast<CodeGeneratorX86_64*>(codegen);
283    __ Bind(GetEntryLabel());
284    SaveLiveRegisters(codegen, locations);
285
286    // We're moving two locations to locations that could overlap, so we need a parallel
287    // move resolver.
288    InvokeRuntimeCallingConvention calling_convention;
289    codegen->EmitParallelMoves(
290        class_to_check_,
291        Location::RegisterLocation(calling_convention.GetRegisterAt(0)),
292        Primitive::kPrimNot,
293        object_class_,
294        Location::RegisterLocation(calling_convention.GetRegisterAt(1)),
295        Primitive::kPrimNot);
296
297    if (instruction_->IsInstanceOf()) {
298      __ gs()->call(
299          Address::Absolute(QUICK_ENTRYPOINT_OFFSET(kX86_64WordSize, pInstanceofNonTrivial), true));
300    } else {
301      DCHECK(instruction_->IsCheckCast());
302      __ gs()->call(
303          Address::Absolute(QUICK_ENTRYPOINT_OFFSET(kX86_64WordSize, pCheckCast), true));
304    }
305    RecordPcInfo(codegen, instruction_, dex_pc_);
306
307    if (instruction_->IsInstanceOf()) {
308      x64_codegen->Move(locations->Out(), Location::RegisterLocation(RAX));
309    }
310
311    RestoreLiveRegisters(codegen, locations);
312    __ jmp(GetExitLabel());
313  }
314
315 private:
316  HInstruction* const instruction_;
317  const Location class_to_check_;
318  const Location object_class_;
319  const uint32_t dex_pc_;
320
321  DISALLOW_COPY_AND_ASSIGN(TypeCheckSlowPathX86_64);
322};
323
324class DeoptimizationSlowPathX86_64 : public SlowPathCodeX86_64 {
325 public:
326  explicit DeoptimizationSlowPathX86_64(HInstruction* instruction)
327      : instruction_(instruction) {}
328
329  void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
330    __ Bind(GetEntryLabel());
331    SaveLiveRegisters(codegen, instruction_->GetLocations());
332    __ gs()->call(
333        Address::Absolute(QUICK_ENTRYPOINT_OFFSET(kX86_64WordSize, pDeoptimize), true));
334    DCHECK(instruction_->IsDeoptimize());
335    HDeoptimize* deoptimize = instruction_->AsDeoptimize();
336    uint32_t dex_pc = deoptimize->GetDexPc();
337    codegen->RecordPcInfo(instruction_, dex_pc, this);
338  }
339
340 private:
341  HInstruction* const instruction_;
342  DISALLOW_COPY_AND_ASSIGN(DeoptimizationSlowPathX86_64);
343};
344
345#undef __
346#define __ down_cast<X86_64Assembler*>(GetAssembler())->
347
348inline Condition X86_64Condition(IfCondition cond) {
349  switch (cond) {
350    case kCondEQ: return kEqual;
351    case kCondNE: return kNotEqual;
352    case kCondLT: return kLess;
353    case kCondLE: return kLessEqual;
354    case kCondGT: return kGreater;
355    case kCondGE: return kGreaterEqual;
356    default:
357      LOG(FATAL) << "Unknown if condition";
358  }
359  return kEqual;
360}
361
362void CodeGeneratorX86_64::GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke,
363                                                     Location temp) {
364  // All registers are assumed to be correctly set up.
365
366  // TODO: Implement all kinds of calls:
367  // 1) boot -> boot
368  // 2) app -> boot
369  // 3) app -> app
370  //
371  // Currently we implement the app -> app logic, which looks up in the resolve cache.
372
373  if (invoke->IsStringInit()) {
374    CpuRegister reg = temp.AsRegister<CpuRegister>();
375    // temp = thread->string_init_entrypoint
376    __ gs()->movl(reg, Address::Absolute(invoke->GetStringInitOffset()));
377    // (temp + offset_of_quick_compiled_code)()
378    __ call(Address(reg, ArtMethod::EntryPointFromQuickCompiledCodeOffset(
379        kX86_64WordSize).SizeValue()));
380  } else if (invoke->IsRecursive()) {
381    __ call(&frame_entry_label_);
382  } else {
383    LocationSummary* locations = invoke->GetLocations();
384    CpuRegister reg = temp.AsRegister<CpuRegister>();
385    CpuRegister current_method =
386        locations->InAt(invoke->GetCurrentMethodInputIndex()).AsRegister<CpuRegister>();
387    // temp = temp->dex_cache_resolved_methods_;
388    __ movl(reg, Address(
389        current_method, ArtMethod::DexCacheResolvedMethodsOffset().SizeValue()));
390    // temp = temp[index_in_cache]
391    __ movq(reg, Address(
392        reg, CodeGenerator::GetCachePointerOffset(invoke->GetDexMethodIndex())));
393    // (temp + offset_of_quick_compiled_code)()
394    __ call(Address(reg, ArtMethod::EntryPointFromQuickCompiledCodeOffset(
395        kX86_64WordSize).SizeValue()));
396  }
397
398  DCHECK(!IsLeafMethod());
399}
400
401void CodeGeneratorX86_64::DumpCoreRegister(std::ostream& stream, int reg) const {
402  stream << Register(reg);
403}
404
405void CodeGeneratorX86_64::DumpFloatingPointRegister(std::ostream& stream, int reg) const {
406  stream << FloatRegister(reg);
407}
408
409size_t CodeGeneratorX86_64::SaveCoreRegister(size_t stack_index, uint32_t reg_id) {
410  __ movq(Address(CpuRegister(RSP), stack_index), CpuRegister(reg_id));
411  return kX86_64WordSize;
412}
413
414size_t CodeGeneratorX86_64::RestoreCoreRegister(size_t stack_index, uint32_t reg_id) {
415  __ movq(CpuRegister(reg_id), Address(CpuRegister(RSP), stack_index));
416  return kX86_64WordSize;
417}
418
419size_t CodeGeneratorX86_64::SaveFloatingPointRegister(size_t stack_index, uint32_t reg_id) {
420  __ movsd(Address(CpuRegister(RSP), stack_index), XmmRegister(reg_id));
421  return kX86_64WordSize;
422}
423
424size_t CodeGeneratorX86_64::RestoreFloatingPointRegister(size_t stack_index, uint32_t reg_id) {
425  __ movsd(XmmRegister(reg_id), Address(CpuRegister(RSP), stack_index));
426  return kX86_64WordSize;
427}
428
429static constexpr int kNumberOfCpuRegisterPairs = 0;
430// Use a fake return address register to mimic Quick.
431static constexpr Register kFakeReturnRegister = Register(kLastCpuRegister + 1);
432CodeGeneratorX86_64::CodeGeneratorX86_64(HGraph* graph,
433                const X86_64InstructionSetFeatures& isa_features,
434                const CompilerOptions& compiler_options)
435      : CodeGenerator(graph,
436                      kNumberOfCpuRegisters,
437                      kNumberOfFloatRegisters,
438                      kNumberOfCpuRegisterPairs,
439                      ComputeRegisterMask(reinterpret_cast<const int*>(kCoreCalleeSaves),
440                                          arraysize(kCoreCalleeSaves))
441                          | (1 << kFakeReturnRegister),
442                      ComputeRegisterMask(reinterpret_cast<const int*>(kFpuCalleeSaves),
443                                          arraysize(kFpuCalleeSaves)),
444                      compiler_options),
445        block_labels_(graph->GetArena(), 0),
446        location_builder_(graph, this),
447        instruction_visitor_(graph, this),
448        move_resolver_(graph->GetArena(), this),
449        isa_features_(isa_features),
450        constant_area_start_(0) {
451  AddAllocatedRegister(Location::RegisterLocation(kFakeReturnRegister));
452}
453
454InstructionCodeGeneratorX86_64::InstructionCodeGeneratorX86_64(HGraph* graph,
455                                                               CodeGeneratorX86_64* codegen)
456      : HGraphVisitor(graph),
457        assembler_(codegen->GetAssembler()),
458        codegen_(codegen) {}
459
460Location CodeGeneratorX86_64::AllocateFreeRegister(Primitive::Type type) const {
461  switch (type) {
462    case Primitive::kPrimLong:
463    case Primitive::kPrimByte:
464    case Primitive::kPrimBoolean:
465    case Primitive::kPrimChar:
466    case Primitive::kPrimShort:
467    case Primitive::kPrimInt:
468    case Primitive::kPrimNot: {
469      size_t reg = FindFreeEntry(blocked_core_registers_, kNumberOfCpuRegisters);
470      return Location::RegisterLocation(reg);
471    }
472
473    case Primitive::kPrimFloat:
474    case Primitive::kPrimDouble: {
475      size_t reg = FindFreeEntry(blocked_fpu_registers_, kNumberOfFloatRegisters);
476      return Location::FpuRegisterLocation(reg);
477    }
478
479    case Primitive::kPrimVoid:
480      LOG(FATAL) << "Unreachable type " << type;
481  }
482
483  return Location();
484}
485
486void CodeGeneratorX86_64::SetupBlockedRegisters(bool is_baseline) const {
487  // Stack register is always reserved.
488  blocked_core_registers_[RSP] = true;
489
490  // Block the register used as TMP.
491  blocked_core_registers_[TMP] = true;
492
493  if (is_baseline) {
494    for (size_t i = 0; i < arraysize(kCoreCalleeSaves); ++i) {
495      blocked_core_registers_[kCoreCalleeSaves[i]] = true;
496    }
497    for (size_t i = 0; i < arraysize(kFpuCalleeSaves); ++i) {
498      blocked_fpu_registers_[kFpuCalleeSaves[i]] = true;
499    }
500  }
501}
502
503static dwarf::Reg DWARFReg(Register reg) {
504  return dwarf::Reg::X86_64Core(static_cast<int>(reg));
505}
506
507static dwarf::Reg DWARFReg(FloatRegister reg) {
508  return dwarf::Reg::X86_64Fp(static_cast<int>(reg));
509}
510
511void CodeGeneratorX86_64::GenerateFrameEntry() {
512  __ cfi().SetCurrentCFAOffset(kX86_64WordSize);  // return address
513  __ Bind(&frame_entry_label_);
514  bool skip_overflow_check = IsLeafMethod()
515      && !FrameNeedsStackCheck(GetFrameSize(), InstructionSet::kX86_64);
516  DCHECK(GetCompilerOptions().GetImplicitStackOverflowChecks());
517
518  if (!skip_overflow_check) {
519    __ testq(CpuRegister(RAX), Address(
520        CpuRegister(RSP), -static_cast<int32_t>(GetStackOverflowReservedBytes(kX86_64))));
521    RecordPcInfo(nullptr, 0);
522  }
523
524  if (HasEmptyFrame()) {
525    return;
526  }
527
528  for (int i = arraysize(kCoreCalleeSaves) - 1; i >= 0; --i) {
529    Register reg = kCoreCalleeSaves[i];
530    if (allocated_registers_.ContainsCoreRegister(reg)) {
531      __ pushq(CpuRegister(reg));
532      __ cfi().AdjustCFAOffset(kX86_64WordSize);
533      __ cfi().RelOffset(DWARFReg(reg), 0);
534    }
535  }
536
537  int adjust = GetFrameSize() - GetCoreSpillSize();
538  __ subq(CpuRegister(RSP), Immediate(adjust));
539  __ cfi().AdjustCFAOffset(adjust);
540  uint32_t xmm_spill_location = GetFpuSpillStart();
541  size_t xmm_spill_slot_size = GetFloatingPointSpillSlotSize();
542
543  for (int i = arraysize(kFpuCalleeSaves) - 1; i >= 0; --i) {
544    if (allocated_registers_.ContainsFloatingPointRegister(kFpuCalleeSaves[i])) {
545      int offset = xmm_spill_location + (xmm_spill_slot_size * i);
546      __ movsd(Address(CpuRegister(RSP), offset), XmmRegister(kFpuCalleeSaves[i]));
547      __ cfi().RelOffset(DWARFReg(kFpuCalleeSaves[i]), offset);
548    }
549  }
550
551  __ movq(Address(CpuRegister(RSP), kCurrentMethodStackOffset),
552          CpuRegister(kMethodRegisterArgument));
553}
554
555void CodeGeneratorX86_64::GenerateFrameExit() {
556  __ cfi().RememberState();
557  if (!HasEmptyFrame()) {
558    uint32_t xmm_spill_location = GetFpuSpillStart();
559    size_t xmm_spill_slot_size = GetFloatingPointSpillSlotSize();
560    for (size_t i = 0; i < arraysize(kFpuCalleeSaves); ++i) {
561      if (allocated_registers_.ContainsFloatingPointRegister(kFpuCalleeSaves[i])) {
562        int offset = xmm_spill_location + (xmm_spill_slot_size * i);
563        __ movsd(XmmRegister(kFpuCalleeSaves[i]), Address(CpuRegister(RSP), offset));
564        __ cfi().Restore(DWARFReg(kFpuCalleeSaves[i]));
565      }
566    }
567
568    int adjust = GetFrameSize() - GetCoreSpillSize();
569    __ addq(CpuRegister(RSP), Immediate(adjust));
570    __ cfi().AdjustCFAOffset(-adjust);
571
572    for (size_t i = 0; i < arraysize(kCoreCalleeSaves); ++i) {
573      Register reg = kCoreCalleeSaves[i];
574      if (allocated_registers_.ContainsCoreRegister(reg)) {
575        __ popq(CpuRegister(reg));
576        __ cfi().AdjustCFAOffset(-static_cast<int>(kX86_64WordSize));
577        __ cfi().Restore(DWARFReg(reg));
578      }
579    }
580  }
581  __ ret();
582  __ cfi().RestoreState();
583  __ cfi().DefCFAOffset(GetFrameSize());
584}
585
586void CodeGeneratorX86_64::Bind(HBasicBlock* block) {
587  __ Bind(GetLabelOf(block));
588}
589
590void CodeGeneratorX86_64::LoadCurrentMethod(CpuRegister reg) {
591  DCHECK(RequiresCurrentMethod());
592  __ movq(reg, Address(CpuRegister(RSP), kCurrentMethodStackOffset));
593}
594
595Location CodeGeneratorX86_64::GetStackLocation(HLoadLocal* load) const {
596  switch (load->GetType()) {
597    case Primitive::kPrimLong:
598    case Primitive::kPrimDouble:
599      return Location::DoubleStackSlot(GetStackSlot(load->GetLocal()));
600
601    case Primitive::kPrimInt:
602    case Primitive::kPrimNot:
603    case Primitive::kPrimFloat:
604      return Location::StackSlot(GetStackSlot(load->GetLocal()));
605
606    case Primitive::kPrimBoolean:
607    case Primitive::kPrimByte:
608    case Primitive::kPrimChar:
609    case Primitive::kPrimShort:
610    case Primitive::kPrimVoid:
611      LOG(FATAL) << "Unexpected type " << load->GetType();
612      UNREACHABLE();
613  }
614
615  LOG(FATAL) << "Unreachable";
616  UNREACHABLE();
617}
618
619void CodeGeneratorX86_64::Move(Location destination, Location source) {
620  if (source.Equals(destination)) {
621    return;
622  }
623  if (destination.IsRegister()) {
624    if (source.IsRegister()) {
625      __ movq(destination.AsRegister<CpuRegister>(), source.AsRegister<CpuRegister>());
626    } else if (source.IsFpuRegister()) {
627      __ movd(destination.AsRegister<CpuRegister>(), source.AsFpuRegister<XmmRegister>());
628    } else if (source.IsStackSlot()) {
629      __ movl(destination.AsRegister<CpuRegister>(),
630              Address(CpuRegister(RSP), source.GetStackIndex()));
631    } else {
632      DCHECK(source.IsDoubleStackSlot());
633      __ movq(destination.AsRegister<CpuRegister>(),
634              Address(CpuRegister(RSP), source.GetStackIndex()));
635    }
636  } else if (destination.IsFpuRegister()) {
637    if (source.IsRegister()) {
638      __ movd(destination.AsFpuRegister<XmmRegister>(), source.AsRegister<CpuRegister>());
639    } else if (source.IsFpuRegister()) {
640      __ movaps(destination.AsFpuRegister<XmmRegister>(), source.AsFpuRegister<XmmRegister>());
641    } else if (source.IsStackSlot()) {
642      __ movss(destination.AsFpuRegister<XmmRegister>(),
643              Address(CpuRegister(RSP), source.GetStackIndex()));
644    } else {
645      DCHECK(source.IsDoubleStackSlot());
646      __ movsd(destination.AsFpuRegister<XmmRegister>(),
647               Address(CpuRegister(RSP), source.GetStackIndex()));
648    }
649  } else if (destination.IsStackSlot()) {
650    if (source.IsRegister()) {
651      __ movl(Address(CpuRegister(RSP), destination.GetStackIndex()),
652              source.AsRegister<CpuRegister>());
653    } else if (source.IsFpuRegister()) {
654      __ movss(Address(CpuRegister(RSP), destination.GetStackIndex()),
655               source.AsFpuRegister<XmmRegister>());
656    } else if (source.IsConstant()) {
657      HConstant* constant = source.GetConstant();
658      int32_t value = GetInt32ValueOf(constant);
659      __ movl(Address(CpuRegister(RSP), destination.GetStackIndex()), Immediate(value));
660    } else {
661      DCHECK(source.IsStackSlot()) << source;
662      __ movl(CpuRegister(TMP), Address(CpuRegister(RSP), source.GetStackIndex()));
663      __ movl(Address(CpuRegister(RSP), destination.GetStackIndex()), CpuRegister(TMP));
664    }
665  } else {
666    DCHECK(destination.IsDoubleStackSlot());
667    if (source.IsRegister()) {
668      __ movq(Address(CpuRegister(RSP), destination.GetStackIndex()),
669              source.AsRegister<CpuRegister>());
670    } else if (source.IsFpuRegister()) {
671      __ movsd(Address(CpuRegister(RSP), destination.GetStackIndex()),
672               source.AsFpuRegister<XmmRegister>());
673    } else if (source.IsConstant()) {
674      HConstant* constant = source.GetConstant();
675      int64_t value;
676      if (constant->IsDoubleConstant()) {
677        value = bit_cast<int64_t, double>(constant->AsDoubleConstant()->GetValue());
678      } else {
679        DCHECK(constant->IsLongConstant());
680        value = constant->AsLongConstant()->GetValue();
681      }
682      Load64BitValue(CpuRegister(TMP), value);
683      __ movq(Address(CpuRegister(RSP), destination.GetStackIndex()), CpuRegister(TMP));
684    } else {
685      DCHECK(source.IsDoubleStackSlot());
686      __ movq(CpuRegister(TMP), Address(CpuRegister(RSP), source.GetStackIndex()));
687      __ movq(Address(CpuRegister(RSP), destination.GetStackIndex()), CpuRegister(TMP));
688    }
689  }
690}
691
692void CodeGeneratorX86_64::Move(HInstruction* instruction,
693                               Location location,
694                               HInstruction* move_for) {
695  LocationSummary* locations = instruction->GetLocations();
696  if (instruction->IsCurrentMethod()) {
697    Move(location, Location::DoubleStackSlot(kCurrentMethodStackOffset));
698  } else if (locations != nullptr && locations->Out().Equals(location)) {
699    return;
700  } else if (locations != nullptr && locations->Out().IsConstant()) {
701    HConstant* const_to_move = locations->Out().GetConstant();
702    if (const_to_move->IsIntConstant() || const_to_move->IsNullConstant()) {
703      Immediate imm(GetInt32ValueOf(const_to_move));
704      if (location.IsRegister()) {
705        __ movl(location.AsRegister<CpuRegister>(), imm);
706      } else if (location.IsStackSlot()) {
707        __ movl(Address(CpuRegister(RSP), location.GetStackIndex()), imm);
708      } else {
709        DCHECK(location.IsConstant());
710        DCHECK_EQ(location.GetConstant(), const_to_move);
711      }
712    } else if (const_to_move->IsLongConstant()) {
713      int64_t value = const_to_move->AsLongConstant()->GetValue();
714      if (location.IsRegister()) {
715        Load64BitValue(location.AsRegister<CpuRegister>(), value);
716      } else if (location.IsDoubleStackSlot()) {
717        Load64BitValue(CpuRegister(TMP), value);
718        __ movq(Address(CpuRegister(RSP), location.GetStackIndex()), CpuRegister(TMP));
719      } else {
720        DCHECK(location.IsConstant());
721        DCHECK_EQ(location.GetConstant(), const_to_move);
722      }
723    }
724  } else if (instruction->IsLoadLocal()) {
725    switch (instruction->GetType()) {
726      case Primitive::kPrimBoolean:
727      case Primitive::kPrimByte:
728      case Primitive::kPrimChar:
729      case Primitive::kPrimShort:
730      case Primitive::kPrimInt:
731      case Primitive::kPrimNot:
732      case Primitive::kPrimFloat:
733        Move(location, Location::StackSlot(GetStackSlot(instruction->AsLoadLocal()->GetLocal())));
734        break;
735
736      case Primitive::kPrimLong:
737      case Primitive::kPrimDouble:
738        Move(location,
739             Location::DoubleStackSlot(GetStackSlot(instruction->AsLoadLocal()->GetLocal())));
740        break;
741
742      default:
743        LOG(FATAL) << "Unexpected local type " << instruction->GetType();
744    }
745  } else if (instruction->IsTemporary()) {
746    Location temp_location = GetTemporaryLocation(instruction->AsTemporary());
747    Move(location, temp_location);
748  } else {
749    DCHECK((instruction->GetNext() == move_for) || instruction->GetNext()->IsTemporary());
750    switch (instruction->GetType()) {
751      case Primitive::kPrimBoolean:
752      case Primitive::kPrimByte:
753      case Primitive::kPrimChar:
754      case Primitive::kPrimShort:
755      case Primitive::kPrimInt:
756      case Primitive::kPrimNot:
757      case Primitive::kPrimLong:
758      case Primitive::kPrimFloat:
759      case Primitive::kPrimDouble:
760        Move(location, locations->Out());
761        break;
762
763      default:
764        LOG(FATAL) << "Unexpected type " << instruction->GetType();
765    }
766  }
767}
768
769void LocationsBuilderX86_64::VisitGoto(HGoto* got) {
770  got->SetLocations(nullptr);
771}
772
773void InstructionCodeGeneratorX86_64::VisitGoto(HGoto* got) {
774  HBasicBlock* successor = got->GetSuccessor();
775  DCHECK(!successor->IsExitBlock());
776
777  HBasicBlock* block = got->GetBlock();
778  HInstruction* previous = got->GetPrevious();
779
780  HLoopInformation* info = block->GetLoopInformation();
781  if (info != nullptr && info->IsBackEdge(*block) && info->HasSuspendCheck()) {
782    GenerateSuspendCheck(info->GetSuspendCheck(), successor);
783    return;
784  }
785
786  if (block->IsEntryBlock() && (previous != nullptr) && previous->IsSuspendCheck()) {
787    GenerateSuspendCheck(previous->AsSuspendCheck(), nullptr);
788  }
789  if (!codegen_->GoesToNextBlock(got->GetBlock(), successor)) {
790    __ jmp(codegen_->GetLabelOf(successor));
791  }
792}
793
794void LocationsBuilderX86_64::VisitExit(HExit* exit) {
795  exit->SetLocations(nullptr);
796}
797
798void InstructionCodeGeneratorX86_64::VisitExit(HExit* exit) {
799  UNUSED(exit);
800}
801
802void InstructionCodeGeneratorX86_64::GenerateTestAndBranch(HInstruction* instruction,
803                                                           Label* true_target,
804                                                           Label* false_target,
805                                                           Label* always_true_target) {
806  HInstruction* cond = instruction->InputAt(0);
807  if (cond->IsIntConstant()) {
808    // Constant condition, statically compared against 1.
809    int32_t cond_value = cond->AsIntConstant()->GetValue();
810    if (cond_value == 1) {
811      if (always_true_target != nullptr) {
812        __ jmp(always_true_target);
813      }
814      return;
815    } else {
816      DCHECK_EQ(cond_value, 0);
817    }
818  } else {
819    bool materialized =
820        !cond->IsCondition() || cond->AsCondition()->NeedsMaterialization();
821    // Moves do not affect the eflags register, so if the condition is
822    // evaluated just before the if, we don't need to evaluate it
823    // again.
824    bool eflags_set = cond->IsCondition()
825        && cond->AsCondition()->IsBeforeWhenDisregardMoves(instruction);
826    if (materialized) {
827      if (!eflags_set) {
828        // Materialized condition, compare against 0.
829        Location lhs = instruction->GetLocations()->InAt(0);
830        if (lhs.IsRegister()) {
831          __ testl(lhs.AsRegister<CpuRegister>(), lhs.AsRegister<CpuRegister>());
832        } else {
833          __ cmpl(Address(CpuRegister(RSP), lhs.GetStackIndex()),
834                  Immediate(0));
835        }
836        __ j(kNotEqual, true_target);
837      } else {
838        __ j(X86_64Condition(cond->AsCondition()->GetCondition()), true_target);
839      }
840    } else {
841      Location lhs = cond->GetLocations()->InAt(0);
842      Location rhs = cond->GetLocations()->InAt(1);
843      if (rhs.IsRegister()) {
844        __ cmpl(lhs.AsRegister<CpuRegister>(), rhs.AsRegister<CpuRegister>());
845      } else if (rhs.IsConstant()) {
846        int32_t constant = CodeGenerator::GetInt32ValueOf(rhs.GetConstant());
847        if (constant == 0) {
848          __ testl(lhs.AsRegister<CpuRegister>(), lhs.AsRegister<CpuRegister>());
849        } else {
850          __ cmpl(lhs.AsRegister<CpuRegister>(), Immediate(constant));
851        }
852      } else {
853        __ cmpl(lhs.AsRegister<CpuRegister>(),
854                Address(CpuRegister(RSP), rhs.GetStackIndex()));
855      }
856      __ j(X86_64Condition(cond->AsCondition()->GetCondition()), true_target);
857    }
858  }
859  if (false_target != nullptr) {
860    __ jmp(false_target);
861  }
862}
863
864void LocationsBuilderX86_64::VisitIf(HIf* if_instr) {
865  LocationSummary* locations =
866      new (GetGraph()->GetArena()) LocationSummary(if_instr, LocationSummary::kNoCall);
867  HInstruction* cond = if_instr->InputAt(0);
868  if (!cond->IsCondition() || cond->AsCondition()->NeedsMaterialization()) {
869    locations->SetInAt(0, Location::Any());
870  }
871}
872
873void InstructionCodeGeneratorX86_64::VisitIf(HIf* if_instr) {
874  Label* true_target = codegen_->GetLabelOf(if_instr->IfTrueSuccessor());
875  Label* false_target = codegen_->GetLabelOf(if_instr->IfFalseSuccessor());
876  Label* always_true_target = true_target;
877  if (codegen_->GoesToNextBlock(if_instr->GetBlock(),
878                                if_instr->IfTrueSuccessor())) {
879    always_true_target = nullptr;
880  }
881  if (codegen_->GoesToNextBlock(if_instr->GetBlock(),
882                                if_instr->IfFalseSuccessor())) {
883    false_target = nullptr;
884  }
885  GenerateTestAndBranch(if_instr, true_target, false_target, always_true_target);
886}
887
888void LocationsBuilderX86_64::VisitDeoptimize(HDeoptimize* deoptimize) {
889  LocationSummary* locations = new (GetGraph()->GetArena())
890      LocationSummary(deoptimize, LocationSummary::kCallOnSlowPath);
891  HInstruction* cond = deoptimize->InputAt(0);
892  DCHECK(cond->IsCondition());
893  if (cond->AsCondition()->NeedsMaterialization()) {
894    locations->SetInAt(0, Location::Any());
895  }
896}
897
898void InstructionCodeGeneratorX86_64::VisitDeoptimize(HDeoptimize* deoptimize) {
899  SlowPathCodeX86_64* slow_path = new (GetGraph()->GetArena())
900      DeoptimizationSlowPathX86_64(deoptimize);
901  codegen_->AddSlowPath(slow_path);
902  Label* slow_path_entry = slow_path->GetEntryLabel();
903  GenerateTestAndBranch(deoptimize, slow_path_entry, nullptr, slow_path_entry);
904}
905
906void LocationsBuilderX86_64::VisitLocal(HLocal* local) {
907  local->SetLocations(nullptr);
908}
909
910void InstructionCodeGeneratorX86_64::VisitLocal(HLocal* local) {
911  DCHECK_EQ(local->GetBlock(), GetGraph()->GetEntryBlock());
912}
913
914void LocationsBuilderX86_64::VisitLoadLocal(HLoadLocal* local) {
915  local->SetLocations(nullptr);
916}
917
918void InstructionCodeGeneratorX86_64::VisitLoadLocal(HLoadLocal* load) {
919  // Nothing to do, this is driven by the code generator.
920  UNUSED(load);
921}
922
923void LocationsBuilderX86_64::VisitStoreLocal(HStoreLocal* store) {
924  LocationSummary* locations =
925      new (GetGraph()->GetArena()) LocationSummary(store, LocationSummary::kNoCall);
926  switch (store->InputAt(1)->GetType()) {
927    case Primitive::kPrimBoolean:
928    case Primitive::kPrimByte:
929    case Primitive::kPrimChar:
930    case Primitive::kPrimShort:
931    case Primitive::kPrimInt:
932    case Primitive::kPrimNot:
933    case Primitive::kPrimFloat:
934      locations->SetInAt(1, Location::StackSlot(codegen_->GetStackSlot(store->GetLocal())));
935      break;
936
937    case Primitive::kPrimLong:
938    case Primitive::kPrimDouble:
939      locations->SetInAt(1, Location::DoubleStackSlot(codegen_->GetStackSlot(store->GetLocal())));
940      break;
941
942    default:
943      LOG(FATAL) << "Unexpected local type " << store->InputAt(1)->GetType();
944  }
945}
946
947void InstructionCodeGeneratorX86_64::VisitStoreLocal(HStoreLocal* store) {
948  UNUSED(store);
949}
950
951void LocationsBuilderX86_64::VisitCondition(HCondition* cond) {
952  LocationSummary* locations =
953      new (GetGraph()->GetArena()) LocationSummary(cond, LocationSummary::kNoCall);
954  locations->SetInAt(0, Location::RequiresRegister());
955  locations->SetInAt(1, Location::Any());
956  if (cond->NeedsMaterialization()) {
957    locations->SetOut(Location::RequiresRegister());
958  }
959}
960
961void InstructionCodeGeneratorX86_64::VisitCondition(HCondition* cond) {
962  if (cond->NeedsMaterialization()) {
963    LocationSummary* locations = cond->GetLocations();
964    CpuRegister reg = locations->Out().AsRegister<CpuRegister>();
965    // Clear register: setcc only sets the low byte.
966    __ xorl(reg, reg);
967    Location lhs = locations->InAt(0);
968    Location rhs = locations->InAt(1);
969    if (rhs.IsRegister()) {
970      __ cmpl(lhs.AsRegister<CpuRegister>(), rhs.AsRegister<CpuRegister>());
971    } else if (rhs.IsConstant()) {
972      int32_t constant = CodeGenerator::GetInt32ValueOf(rhs.GetConstant());
973      if (constant == 0) {
974        __ testl(lhs.AsRegister<CpuRegister>(), lhs.AsRegister<CpuRegister>());
975      } else {
976        __ cmpl(lhs.AsRegister<CpuRegister>(), Immediate(constant));
977      }
978    } else {
979      __ cmpl(lhs.AsRegister<CpuRegister>(), Address(CpuRegister(RSP), rhs.GetStackIndex()));
980    }
981    __ setcc(X86_64Condition(cond->GetCondition()), reg);
982  }
983}
984
985void LocationsBuilderX86_64::VisitEqual(HEqual* comp) {
986  VisitCondition(comp);
987}
988
989void InstructionCodeGeneratorX86_64::VisitEqual(HEqual* comp) {
990  VisitCondition(comp);
991}
992
993void LocationsBuilderX86_64::VisitNotEqual(HNotEqual* comp) {
994  VisitCondition(comp);
995}
996
997void InstructionCodeGeneratorX86_64::VisitNotEqual(HNotEqual* comp) {
998  VisitCondition(comp);
999}
1000
1001void LocationsBuilderX86_64::VisitLessThan(HLessThan* comp) {
1002  VisitCondition(comp);
1003}
1004
1005void InstructionCodeGeneratorX86_64::VisitLessThan(HLessThan* comp) {
1006  VisitCondition(comp);
1007}
1008
1009void LocationsBuilderX86_64::VisitLessThanOrEqual(HLessThanOrEqual* comp) {
1010  VisitCondition(comp);
1011}
1012
1013void InstructionCodeGeneratorX86_64::VisitLessThanOrEqual(HLessThanOrEqual* comp) {
1014  VisitCondition(comp);
1015}
1016
1017void LocationsBuilderX86_64::VisitGreaterThan(HGreaterThan* comp) {
1018  VisitCondition(comp);
1019}
1020
1021void InstructionCodeGeneratorX86_64::VisitGreaterThan(HGreaterThan* comp) {
1022  VisitCondition(comp);
1023}
1024
1025void LocationsBuilderX86_64::VisitGreaterThanOrEqual(HGreaterThanOrEqual* comp) {
1026  VisitCondition(comp);
1027}
1028
1029void InstructionCodeGeneratorX86_64::VisitGreaterThanOrEqual(HGreaterThanOrEqual* comp) {
1030  VisitCondition(comp);
1031}
1032
1033void LocationsBuilderX86_64::VisitCompare(HCompare* compare) {
1034  LocationSummary* locations =
1035      new (GetGraph()->GetArena()) LocationSummary(compare, LocationSummary::kNoCall);
1036  switch (compare->InputAt(0)->GetType()) {
1037    case Primitive::kPrimLong: {
1038      locations->SetInAt(0, Location::RequiresRegister());
1039      locations->SetInAt(1, Location::Any());
1040      locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
1041      break;
1042    }
1043    case Primitive::kPrimFloat:
1044    case Primitive::kPrimDouble: {
1045      locations->SetInAt(0, Location::RequiresFpuRegister());
1046      locations->SetInAt(1, Location::Any());
1047      locations->SetOut(Location::RequiresRegister());
1048      break;
1049    }
1050    default:
1051      LOG(FATAL) << "Unexpected type for compare operation " << compare->InputAt(0)->GetType();
1052  }
1053}
1054
1055void InstructionCodeGeneratorX86_64::VisitCompare(HCompare* compare) {
1056  LocationSummary* locations = compare->GetLocations();
1057  CpuRegister out = locations->Out().AsRegister<CpuRegister>();
1058  Location left = locations->InAt(0);
1059  Location right = locations->InAt(1);
1060
1061  Label less, greater, done;
1062  Primitive::Type type = compare->InputAt(0)->GetType();
1063  switch (type) {
1064    case Primitive::kPrimLong: {
1065      CpuRegister left_reg = left.AsRegister<CpuRegister>();
1066      if (right.IsConstant()) {
1067        int64_t value = right.GetConstant()->AsLongConstant()->GetValue();
1068        if (IsInt<32>(value)) {
1069          if (value == 0) {
1070            __ testq(left_reg, left_reg);
1071          } else {
1072            __ cmpq(left_reg, Immediate(static_cast<int32_t>(value)));
1073          }
1074        } else {
1075          // Value won't fit in an int.
1076          __ cmpq(left_reg, codegen_->LiteralInt64Address(value));
1077        }
1078      } else if (right.IsDoubleStackSlot()) {
1079        __ cmpq(left_reg, Address(CpuRegister(RSP), right.GetStackIndex()));
1080      } else {
1081        __ cmpq(left_reg, right.AsRegister<CpuRegister>());
1082      }
1083      break;
1084    }
1085    case Primitive::kPrimFloat: {
1086      XmmRegister left_reg = left.AsFpuRegister<XmmRegister>();
1087      if (right.IsConstant()) {
1088        float value = right.GetConstant()->AsFloatConstant()->GetValue();
1089        __ ucomiss(left_reg, codegen_->LiteralFloatAddress(value));
1090      } else if (right.IsStackSlot()) {
1091        __ ucomiss(left_reg, Address(CpuRegister(RSP), right.GetStackIndex()));
1092      } else {
1093        __ ucomiss(left_reg, right.AsFpuRegister<XmmRegister>());
1094      }
1095      __ j(kUnordered, compare->IsGtBias() ? &greater : &less);
1096      break;
1097    }
1098    case Primitive::kPrimDouble: {
1099      XmmRegister left_reg = left.AsFpuRegister<XmmRegister>();
1100      if (right.IsConstant()) {
1101        double value = right.GetConstant()->AsDoubleConstant()->GetValue();
1102        __ ucomisd(left_reg, codegen_->LiteralDoubleAddress(value));
1103      } else if (right.IsDoubleStackSlot()) {
1104        __ ucomisd(left_reg, Address(CpuRegister(RSP), right.GetStackIndex()));
1105      } else {
1106        __ ucomisd(left_reg, right.AsFpuRegister<XmmRegister>());
1107      }
1108      __ j(kUnordered, compare->IsGtBias() ? &greater : &less);
1109      break;
1110    }
1111    default:
1112      LOG(FATAL) << "Unexpected compare type " << type;
1113  }
1114  __ movl(out, Immediate(0));
1115  __ j(kEqual, &done);
1116  __ j(type == Primitive::kPrimLong ? kLess : kBelow, &less);  //  ucomis{s,d} sets CF (kBelow)
1117
1118  __ Bind(&greater);
1119  __ movl(out, Immediate(1));
1120  __ jmp(&done);
1121
1122  __ Bind(&less);
1123  __ movl(out, Immediate(-1));
1124
1125  __ Bind(&done);
1126}
1127
1128void LocationsBuilderX86_64::VisitIntConstant(HIntConstant* constant) {
1129  LocationSummary* locations =
1130      new (GetGraph()->GetArena()) LocationSummary(constant, LocationSummary::kNoCall);
1131  locations->SetOut(Location::ConstantLocation(constant));
1132}
1133
1134void InstructionCodeGeneratorX86_64::VisitIntConstant(HIntConstant* constant) {
1135  // Will be generated at use site.
1136  UNUSED(constant);
1137}
1138
1139void LocationsBuilderX86_64::VisitNullConstant(HNullConstant* constant) {
1140  LocationSummary* locations =
1141      new (GetGraph()->GetArena()) LocationSummary(constant, LocationSummary::kNoCall);
1142  locations->SetOut(Location::ConstantLocation(constant));
1143}
1144
1145void InstructionCodeGeneratorX86_64::VisitNullConstant(HNullConstant* constant) {
1146  // Will be generated at use site.
1147  UNUSED(constant);
1148}
1149
1150void LocationsBuilderX86_64::VisitLongConstant(HLongConstant* constant) {
1151  LocationSummary* locations =
1152      new (GetGraph()->GetArena()) LocationSummary(constant, LocationSummary::kNoCall);
1153  locations->SetOut(Location::ConstantLocation(constant));
1154}
1155
1156void InstructionCodeGeneratorX86_64::VisitLongConstant(HLongConstant* constant) {
1157  // Will be generated at use site.
1158  UNUSED(constant);
1159}
1160
1161void LocationsBuilderX86_64::VisitFloatConstant(HFloatConstant* constant) {
1162  LocationSummary* locations =
1163      new (GetGraph()->GetArena()) LocationSummary(constant, LocationSummary::kNoCall);
1164  locations->SetOut(Location::ConstantLocation(constant));
1165}
1166
1167void InstructionCodeGeneratorX86_64::VisitFloatConstant(HFloatConstant* constant) {
1168  // Will be generated at use site.
1169  UNUSED(constant);
1170}
1171
1172void LocationsBuilderX86_64::VisitDoubleConstant(HDoubleConstant* constant) {
1173  LocationSummary* locations =
1174      new (GetGraph()->GetArena()) LocationSummary(constant, LocationSummary::kNoCall);
1175  locations->SetOut(Location::ConstantLocation(constant));
1176}
1177
1178void InstructionCodeGeneratorX86_64::VisitDoubleConstant(HDoubleConstant* constant) {
1179  // Will be generated at use site.
1180  UNUSED(constant);
1181}
1182
1183void LocationsBuilderX86_64::VisitMemoryBarrier(HMemoryBarrier* memory_barrier) {
1184  memory_barrier->SetLocations(nullptr);
1185}
1186
1187void InstructionCodeGeneratorX86_64::VisitMemoryBarrier(HMemoryBarrier* memory_barrier) {
1188  GenerateMemoryBarrier(memory_barrier->GetBarrierKind());
1189}
1190
1191void LocationsBuilderX86_64::VisitReturnVoid(HReturnVoid* ret) {
1192  ret->SetLocations(nullptr);
1193}
1194
1195void InstructionCodeGeneratorX86_64::VisitReturnVoid(HReturnVoid* ret) {
1196  UNUSED(ret);
1197  codegen_->GenerateFrameExit();
1198}
1199
1200void LocationsBuilderX86_64::VisitReturn(HReturn* ret) {
1201  LocationSummary* locations =
1202      new (GetGraph()->GetArena()) LocationSummary(ret, LocationSummary::kNoCall);
1203  switch (ret->InputAt(0)->GetType()) {
1204    case Primitive::kPrimBoolean:
1205    case Primitive::kPrimByte:
1206    case Primitive::kPrimChar:
1207    case Primitive::kPrimShort:
1208    case Primitive::kPrimInt:
1209    case Primitive::kPrimNot:
1210    case Primitive::kPrimLong:
1211      locations->SetInAt(0, Location::RegisterLocation(RAX));
1212      break;
1213
1214    case Primitive::kPrimFloat:
1215    case Primitive::kPrimDouble:
1216      locations->SetInAt(0, Location::FpuRegisterLocation(XMM0));
1217      break;
1218
1219    default:
1220      LOG(FATAL) << "Unexpected return type " << ret->InputAt(0)->GetType();
1221  }
1222}
1223
1224void InstructionCodeGeneratorX86_64::VisitReturn(HReturn* ret) {
1225  if (kIsDebugBuild) {
1226    switch (ret->InputAt(0)->GetType()) {
1227      case Primitive::kPrimBoolean:
1228      case Primitive::kPrimByte:
1229      case Primitive::kPrimChar:
1230      case Primitive::kPrimShort:
1231      case Primitive::kPrimInt:
1232      case Primitive::kPrimNot:
1233      case Primitive::kPrimLong:
1234        DCHECK_EQ(ret->GetLocations()->InAt(0).AsRegister<CpuRegister>().AsRegister(), RAX);
1235        break;
1236
1237      case Primitive::kPrimFloat:
1238      case Primitive::kPrimDouble:
1239        DCHECK_EQ(ret->GetLocations()->InAt(0).AsFpuRegister<XmmRegister>().AsFloatRegister(),
1240                  XMM0);
1241        break;
1242
1243      default:
1244        LOG(FATAL) << "Unexpected return type " << ret->InputAt(0)->GetType();
1245    }
1246  }
1247  codegen_->GenerateFrameExit();
1248}
1249
1250Location InvokeDexCallingConventionVisitorX86_64::GetReturnLocation(Primitive::Type type) const {
1251  switch (type) {
1252    case Primitive::kPrimBoolean:
1253    case Primitive::kPrimByte:
1254    case Primitive::kPrimChar:
1255    case Primitive::kPrimShort:
1256    case Primitive::kPrimInt:
1257    case Primitive::kPrimNot:
1258    case Primitive::kPrimLong:
1259      return Location::RegisterLocation(RAX);
1260
1261    case Primitive::kPrimVoid:
1262      return Location::NoLocation();
1263
1264    case Primitive::kPrimDouble:
1265    case Primitive::kPrimFloat:
1266      return Location::FpuRegisterLocation(XMM0);
1267  }
1268
1269  UNREACHABLE();
1270}
1271
1272Location InvokeDexCallingConventionVisitorX86_64::GetMethodLocation() const {
1273  return Location::RegisterLocation(kMethodRegisterArgument);
1274}
1275
1276Location InvokeDexCallingConventionVisitorX86_64::GetNextLocation(Primitive::Type type) {
1277  switch (type) {
1278    case Primitive::kPrimBoolean:
1279    case Primitive::kPrimByte:
1280    case Primitive::kPrimChar:
1281    case Primitive::kPrimShort:
1282    case Primitive::kPrimInt:
1283    case Primitive::kPrimNot: {
1284      uint32_t index = gp_index_++;
1285      stack_index_++;
1286      if (index < calling_convention.GetNumberOfRegisters()) {
1287        return Location::RegisterLocation(calling_convention.GetRegisterAt(index));
1288      } else {
1289        return Location::StackSlot(calling_convention.GetStackOffsetOf(stack_index_ - 1));
1290      }
1291    }
1292
1293    case Primitive::kPrimLong: {
1294      uint32_t index = gp_index_;
1295      stack_index_ += 2;
1296      if (index < calling_convention.GetNumberOfRegisters()) {
1297        gp_index_ += 1;
1298        return Location::RegisterLocation(calling_convention.GetRegisterAt(index));
1299      } else {
1300        gp_index_ += 2;
1301        return Location::DoubleStackSlot(calling_convention.GetStackOffsetOf(stack_index_ - 2));
1302      }
1303    }
1304
1305    case Primitive::kPrimFloat: {
1306      uint32_t index = float_index_++;
1307      stack_index_++;
1308      if (index < calling_convention.GetNumberOfFpuRegisters()) {
1309        return Location::FpuRegisterLocation(calling_convention.GetFpuRegisterAt(index));
1310      } else {
1311        return Location::StackSlot(calling_convention.GetStackOffsetOf(stack_index_ - 1));
1312      }
1313    }
1314
1315    case Primitive::kPrimDouble: {
1316      uint32_t index = float_index_++;
1317      stack_index_ += 2;
1318      if (index < calling_convention.GetNumberOfFpuRegisters()) {
1319        return Location::FpuRegisterLocation(calling_convention.GetFpuRegisterAt(index));
1320      } else {
1321        return Location::DoubleStackSlot(calling_convention.GetStackOffsetOf(stack_index_ - 2));
1322      }
1323    }
1324
1325    case Primitive::kPrimVoid:
1326      LOG(FATAL) << "Unexpected parameter type " << type;
1327      break;
1328  }
1329  return Location();
1330}
1331
1332void LocationsBuilderX86_64::VisitInvokeStaticOrDirect(HInvokeStaticOrDirect* invoke) {
1333  // When we do not run baseline, explicit clinit checks triggered by static
1334  // invokes must have been pruned by art::PrepareForRegisterAllocation.
1335  DCHECK(codegen_->IsBaseline() || !invoke->IsStaticWithExplicitClinitCheck());
1336
1337  IntrinsicLocationsBuilderX86_64 intrinsic(codegen_);
1338  if (intrinsic.TryDispatch(invoke)) {
1339    LocationSummary* locations = invoke->GetLocations();
1340    if (locations->CanCall()) {
1341      locations->SetInAt(invoke->GetCurrentMethodInputIndex(), Location::RequiresRegister());
1342    }
1343    return;
1344  }
1345
1346  HandleInvoke(invoke);
1347}
1348
1349static bool TryGenerateIntrinsicCode(HInvoke* invoke, CodeGeneratorX86_64* codegen) {
1350  if (invoke->GetLocations()->Intrinsified()) {
1351    IntrinsicCodeGeneratorX86_64 intrinsic(codegen);
1352    intrinsic.Dispatch(invoke);
1353    return true;
1354  }
1355  return false;
1356}
1357
1358void InstructionCodeGeneratorX86_64::VisitInvokeStaticOrDirect(HInvokeStaticOrDirect* invoke) {
1359  // When we do not run baseline, explicit clinit checks triggered by static
1360  // invokes must have been pruned by art::PrepareForRegisterAllocation.
1361  DCHECK(codegen_->IsBaseline() || !invoke->IsStaticWithExplicitClinitCheck());
1362
1363  if (TryGenerateIntrinsicCode(invoke, codegen_)) {
1364    return;
1365  }
1366
1367  LocationSummary* locations = invoke->GetLocations();
1368  codegen_->GenerateStaticOrDirectCall(
1369      invoke, locations->HasTemps() ? locations->GetTemp(0) : Location::NoLocation());
1370  codegen_->RecordPcInfo(invoke, invoke->GetDexPc());
1371}
1372
1373void LocationsBuilderX86_64::HandleInvoke(HInvoke* invoke) {
1374  InvokeDexCallingConventionVisitorX86_64 calling_convention_visitor;
1375  CodeGenerator::CreateCommonInvokeLocationSummary(invoke, &calling_convention_visitor);
1376}
1377
1378void LocationsBuilderX86_64::VisitInvokeVirtual(HInvokeVirtual* invoke) {
1379  IntrinsicLocationsBuilderX86_64 intrinsic(codegen_);
1380  if (intrinsic.TryDispatch(invoke)) {
1381    return;
1382  }
1383
1384  HandleInvoke(invoke);
1385}
1386
1387void InstructionCodeGeneratorX86_64::VisitInvokeVirtual(HInvokeVirtual* invoke) {
1388  if (TryGenerateIntrinsicCode(invoke, codegen_)) {
1389    return;
1390  }
1391
1392  CpuRegister temp = invoke->GetLocations()->GetTemp(0).AsRegister<CpuRegister>();
1393  size_t method_offset = mirror::Class::EmbeddedVTableEntryOffset(
1394      invoke->GetVTableIndex(), kX86_64PointerSize).SizeValue();
1395  LocationSummary* locations = invoke->GetLocations();
1396  Location receiver = locations->InAt(0);
1397  size_t class_offset = mirror::Object::ClassOffset().SizeValue();
1398  // temp = object->GetClass();
1399  DCHECK(receiver.IsRegister());
1400  __ movl(temp, Address(receiver.AsRegister<CpuRegister>(), class_offset));
1401  codegen_->MaybeRecordImplicitNullCheck(invoke);
1402  // temp = temp->GetMethodAt(method_offset);
1403  __ movq(temp, Address(temp, method_offset));
1404  // call temp->GetEntryPoint();
1405  __ call(Address(temp, ArtMethod::EntryPointFromQuickCompiledCodeOffset(
1406      kX86_64WordSize).SizeValue()));
1407
1408  DCHECK(!codegen_->IsLeafMethod());
1409  codegen_->RecordPcInfo(invoke, invoke->GetDexPc());
1410}
1411
1412void LocationsBuilderX86_64::VisitInvokeInterface(HInvokeInterface* invoke) {
1413  HandleInvoke(invoke);
1414  // Add the hidden argument.
1415  invoke->GetLocations()->AddTemp(Location::RegisterLocation(RAX));
1416}
1417
1418void InstructionCodeGeneratorX86_64::VisitInvokeInterface(HInvokeInterface* invoke) {
1419  // TODO: b/18116999, our IMTs can miss an IncompatibleClassChangeError.
1420  CpuRegister temp = invoke->GetLocations()->GetTemp(0).AsRegister<CpuRegister>();
1421  uint32_t method_offset = mirror::Class::EmbeddedImTableEntryOffset(
1422      invoke->GetImtIndex() % mirror::Class::kImtSize, kX86_64PointerSize).Uint32Value();
1423  LocationSummary* locations = invoke->GetLocations();
1424  Location receiver = locations->InAt(0);
1425  size_t class_offset = mirror::Object::ClassOffset().SizeValue();
1426
1427  // Set the hidden argument.
1428  CpuRegister hidden_reg = invoke->GetLocations()->GetTemp(1).AsRegister<CpuRegister>();
1429  codegen_->Load64BitValue(hidden_reg, invoke->GetDexMethodIndex());
1430
1431  // temp = object->GetClass();
1432  if (receiver.IsStackSlot()) {
1433    __ movl(temp, Address(CpuRegister(RSP), receiver.GetStackIndex()));
1434    __ movl(temp, Address(temp, class_offset));
1435  } else {
1436    __ movl(temp, Address(receiver.AsRegister<CpuRegister>(), class_offset));
1437  }
1438  codegen_->MaybeRecordImplicitNullCheck(invoke);
1439  // temp = temp->GetImtEntryAt(method_offset);
1440  __ movq(temp, Address(temp, method_offset));
1441  // call temp->GetEntryPoint();
1442  __ call(Address(temp, ArtMethod::EntryPointFromQuickCompiledCodeOffset(
1443      kX86_64WordSize).SizeValue()));
1444
1445  DCHECK(!codegen_->IsLeafMethod());
1446  codegen_->RecordPcInfo(invoke, invoke->GetDexPc());
1447}
1448
1449void LocationsBuilderX86_64::VisitNeg(HNeg* neg) {
1450  LocationSummary* locations =
1451      new (GetGraph()->GetArena()) LocationSummary(neg, LocationSummary::kNoCall);
1452  switch (neg->GetResultType()) {
1453    case Primitive::kPrimInt:
1454    case Primitive::kPrimLong:
1455      locations->SetInAt(0, Location::RequiresRegister());
1456      locations->SetOut(Location::SameAsFirstInput());
1457      break;
1458
1459    case Primitive::kPrimFloat:
1460    case Primitive::kPrimDouble:
1461      locations->SetInAt(0, Location::RequiresFpuRegister());
1462      locations->SetOut(Location::SameAsFirstInput());
1463      locations->AddTemp(Location::RequiresFpuRegister());
1464      break;
1465
1466    default:
1467      LOG(FATAL) << "Unexpected neg type " << neg->GetResultType();
1468  }
1469}
1470
1471void InstructionCodeGeneratorX86_64::VisitNeg(HNeg* neg) {
1472  LocationSummary* locations = neg->GetLocations();
1473  Location out = locations->Out();
1474  Location in = locations->InAt(0);
1475  switch (neg->GetResultType()) {
1476    case Primitive::kPrimInt:
1477      DCHECK(in.IsRegister());
1478      DCHECK(in.Equals(out));
1479      __ negl(out.AsRegister<CpuRegister>());
1480      break;
1481
1482    case Primitive::kPrimLong:
1483      DCHECK(in.IsRegister());
1484      DCHECK(in.Equals(out));
1485      __ negq(out.AsRegister<CpuRegister>());
1486      break;
1487
1488    case Primitive::kPrimFloat: {
1489      DCHECK(in.Equals(out));
1490      XmmRegister mask = locations->GetTemp(0).AsFpuRegister<XmmRegister>();
1491      // Implement float negation with an exclusive or with value
1492      // 0x80000000 (mask for bit 31, representing the sign of a
1493      // single-precision floating-point number).
1494      __ movss(mask, codegen_->LiteralInt32Address(0x80000000));
1495      __ xorps(out.AsFpuRegister<XmmRegister>(), mask);
1496      break;
1497    }
1498
1499    case Primitive::kPrimDouble: {
1500      DCHECK(in.Equals(out));
1501      XmmRegister mask = locations->GetTemp(0).AsFpuRegister<XmmRegister>();
1502      // Implement double negation with an exclusive or with value
1503      // 0x8000000000000000 (mask for bit 63, representing the sign of
1504      // a double-precision floating-point number).
1505      __ movsd(mask, codegen_->LiteralInt64Address(INT64_C(0x8000000000000000)));
1506      __ xorpd(out.AsFpuRegister<XmmRegister>(), mask);
1507      break;
1508    }
1509
1510    default:
1511      LOG(FATAL) << "Unexpected neg type " << neg->GetResultType();
1512  }
1513}
1514
1515void LocationsBuilderX86_64::VisitTypeConversion(HTypeConversion* conversion) {
1516  LocationSummary* locations =
1517      new (GetGraph()->GetArena()) LocationSummary(conversion, LocationSummary::kNoCall);
1518  Primitive::Type result_type = conversion->GetResultType();
1519  Primitive::Type input_type = conversion->GetInputType();
1520  DCHECK_NE(result_type, input_type);
1521
1522  // The Java language does not allow treating boolean as an integral type but
1523  // our bit representation makes it safe.
1524
1525  switch (result_type) {
1526    case Primitive::kPrimByte:
1527      switch (input_type) {
1528        case Primitive::kPrimBoolean:
1529          // Boolean input is a result of code transformations.
1530        case Primitive::kPrimShort:
1531        case Primitive::kPrimInt:
1532        case Primitive::kPrimChar:
1533          // Processing a Dex `int-to-byte' instruction.
1534          locations->SetInAt(0, Location::Any());
1535          locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
1536          break;
1537
1538        default:
1539          LOG(FATAL) << "Unexpected type conversion from " << input_type
1540                     << " to " << result_type;
1541      }
1542      break;
1543
1544    case Primitive::kPrimShort:
1545      switch (input_type) {
1546        case Primitive::kPrimBoolean:
1547          // Boolean input is a result of code transformations.
1548        case Primitive::kPrimByte:
1549        case Primitive::kPrimInt:
1550        case Primitive::kPrimChar:
1551          // Processing a Dex `int-to-short' instruction.
1552          locations->SetInAt(0, Location::Any());
1553          locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
1554          break;
1555
1556        default:
1557          LOG(FATAL) << "Unexpected type conversion from " << input_type
1558                     << " to " << result_type;
1559      }
1560      break;
1561
1562    case Primitive::kPrimInt:
1563      switch (input_type) {
1564        case Primitive::kPrimLong:
1565          // Processing a Dex `long-to-int' instruction.
1566          locations->SetInAt(0, Location::Any());
1567          locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
1568          break;
1569
1570        case Primitive::kPrimFloat:
1571          // Processing a Dex `float-to-int' instruction.
1572          locations->SetInAt(0, Location::RequiresFpuRegister());
1573          locations->SetOut(Location::RequiresRegister());
1574          locations->AddTemp(Location::RequiresFpuRegister());
1575          break;
1576
1577        case Primitive::kPrimDouble:
1578          // Processing a Dex `double-to-int' instruction.
1579          locations->SetInAt(0, Location::RequiresFpuRegister());
1580          locations->SetOut(Location::RequiresRegister());
1581          locations->AddTemp(Location::RequiresFpuRegister());
1582          break;
1583
1584        default:
1585          LOG(FATAL) << "Unexpected type conversion from " << input_type
1586                     << " to " << result_type;
1587      }
1588      break;
1589
1590    case Primitive::kPrimLong:
1591      switch (input_type) {
1592        case Primitive::kPrimBoolean:
1593          // Boolean input is a result of code transformations.
1594        case Primitive::kPrimByte:
1595        case Primitive::kPrimShort:
1596        case Primitive::kPrimInt:
1597        case Primitive::kPrimChar:
1598          // Processing a Dex `int-to-long' instruction.
1599          // TODO: We would benefit from a (to-be-implemented)
1600          // Location::RegisterOrStackSlot requirement for this input.
1601          locations->SetInAt(0, Location::RequiresRegister());
1602          locations->SetOut(Location::RequiresRegister());
1603          break;
1604
1605        case Primitive::kPrimFloat:
1606          // Processing a Dex `float-to-long' instruction.
1607          locations->SetInAt(0, Location::RequiresFpuRegister());
1608          locations->SetOut(Location::RequiresRegister());
1609          locations->AddTemp(Location::RequiresFpuRegister());
1610          break;
1611
1612        case Primitive::kPrimDouble:
1613          // Processing a Dex `double-to-long' instruction.
1614          locations->SetInAt(0, Location::RequiresFpuRegister());
1615          locations->SetOut(Location::RequiresRegister());
1616          locations->AddTemp(Location::RequiresFpuRegister());
1617          break;
1618
1619        default:
1620          LOG(FATAL) << "Unexpected type conversion from " << input_type
1621                     << " to " << result_type;
1622      }
1623      break;
1624
1625    case Primitive::kPrimChar:
1626      switch (input_type) {
1627        case Primitive::kPrimBoolean:
1628          // Boolean input is a result of code transformations.
1629        case Primitive::kPrimByte:
1630        case Primitive::kPrimShort:
1631        case Primitive::kPrimInt:
1632          // Processing a Dex `int-to-char' instruction.
1633          locations->SetInAt(0, Location::Any());
1634          locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
1635          break;
1636
1637        default:
1638          LOG(FATAL) << "Unexpected type conversion from " << input_type
1639                     << " to " << result_type;
1640      }
1641      break;
1642
1643    case Primitive::kPrimFloat:
1644      switch (input_type) {
1645        case Primitive::kPrimBoolean:
1646          // Boolean input is a result of code transformations.
1647        case Primitive::kPrimByte:
1648        case Primitive::kPrimShort:
1649        case Primitive::kPrimInt:
1650        case Primitive::kPrimChar:
1651          // Processing a Dex `int-to-float' instruction.
1652          locations->SetInAt(0, Location::Any());
1653          locations->SetOut(Location::RequiresFpuRegister());
1654          break;
1655
1656        case Primitive::kPrimLong:
1657          // Processing a Dex `long-to-float' instruction.
1658          locations->SetInAt(0, Location::Any());
1659          locations->SetOut(Location::RequiresFpuRegister());
1660          break;
1661
1662        case Primitive::kPrimDouble:
1663          // Processing a Dex `double-to-float' instruction.
1664          locations->SetInAt(0, Location::Any());
1665          locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
1666          break;
1667
1668        default:
1669          LOG(FATAL) << "Unexpected type conversion from " << input_type
1670                     << " to " << result_type;
1671      };
1672      break;
1673
1674    case Primitive::kPrimDouble:
1675      switch (input_type) {
1676        case Primitive::kPrimBoolean:
1677          // Boolean input is a result of code transformations.
1678        case Primitive::kPrimByte:
1679        case Primitive::kPrimShort:
1680        case Primitive::kPrimInt:
1681        case Primitive::kPrimChar:
1682          // Processing a Dex `int-to-double' instruction.
1683          locations->SetInAt(0, Location::Any());
1684          locations->SetOut(Location::RequiresFpuRegister());
1685          break;
1686
1687        case Primitive::kPrimLong:
1688          // Processing a Dex `long-to-double' instruction.
1689          locations->SetInAt(0, Location::Any());
1690          locations->SetOut(Location::RequiresFpuRegister());
1691          break;
1692
1693        case Primitive::kPrimFloat:
1694          // Processing a Dex `float-to-double' instruction.
1695          locations->SetInAt(0, Location::Any());
1696          locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
1697          break;
1698
1699        default:
1700          LOG(FATAL) << "Unexpected type conversion from " << input_type
1701                     << " to " << result_type;
1702      }
1703      break;
1704
1705    default:
1706      LOG(FATAL) << "Unexpected type conversion from " << input_type
1707                 << " to " << result_type;
1708  }
1709}
1710
1711void InstructionCodeGeneratorX86_64::VisitTypeConversion(HTypeConversion* conversion) {
1712  LocationSummary* locations = conversion->GetLocations();
1713  Location out = locations->Out();
1714  Location in = locations->InAt(0);
1715  Primitive::Type result_type = conversion->GetResultType();
1716  Primitive::Type input_type = conversion->GetInputType();
1717  DCHECK_NE(result_type, input_type);
1718  switch (result_type) {
1719    case Primitive::kPrimByte:
1720      switch (input_type) {
1721        case Primitive::kPrimBoolean:
1722          // Boolean input is a result of code transformations.
1723        case Primitive::kPrimShort:
1724        case Primitive::kPrimInt:
1725        case Primitive::kPrimChar:
1726          // Processing a Dex `int-to-byte' instruction.
1727          if (in.IsRegister()) {
1728            __ movsxb(out.AsRegister<CpuRegister>(), in.AsRegister<CpuRegister>());
1729          } else if (in.IsStackSlot()) {
1730            __ movsxb(out.AsRegister<CpuRegister>(),
1731                      Address(CpuRegister(RSP), in.GetStackIndex()));
1732          } else {
1733            DCHECK(in.GetConstant()->IsIntConstant());
1734            __ movl(out.AsRegister<CpuRegister>(),
1735                    Immediate(static_cast<int8_t>(in.GetConstant()->AsIntConstant()->GetValue())));
1736          }
1737          break;
1738
1739        default:
1740          LOG(FATAL) << "Unexpected type conversion from " << input_type
1741                     << " to " << result_type;
1742      }
1743      break;
1744
1745    case Primitive::kPrimShort:
1746      switch (input_type) {
1747        case Primitive::kPrimBoolean:
1748          // Boolean input is a result of code transformations.
1749        case Primitive::kPrimByte:
1750        case Primitive::kPrimInt:
1751        case Primitive::kPrimChar:
1752          // Processing a Dex `int-to-short' instruction.
1753          if (in.IsRegister()) {
1754            __ movsxw(out.AsRegister<CpuRegister>(), in.AsRegister<CpuRegister>());
1755          } else if (in.IsStackSlot()) {
1756            __ movsxw(out.AsRegister<CpuRegister>(),
1757                      Address(CpuRegister(RSP), in.GetStackIndex()));
1758          } else {
1759            DCHECK(in.GetConstant()->IsIntConstant());
1760            __ movl(out.AsRegister<CpuRegister>(),
1761                    Immediate(static_cast<int16_t>(in.GetConstant()->AsIntConstant()->GetValue())));
1762          }
1763          break;
1764
1765        default:
1766          LOG(FATAL) << "Unexpected type conversion from " << input_type
1767                     << " to " << result_type;
1768      }
1769      break;
1770
1771    case Primitive::kPrimInt:
1772      switch (input_type) {
1773        case Primitive::kPrimLong:
1774          // Processing a Dex `long-to-int' instruction.
1775          if (in.IsRegister()) {
1776            __ movl(out.AsRegister<CpuRegister>(), in.AsRegister<CpuRegister>());
1777          } else if (in.IsDoubleStackSlot()) {
1778            __ movl(out.AsRegister<CpuRegister>(),
1779                    Address(CpuRegister(RSP), in.GetStackIndex()));
1780          } else {
1781            DCHECK(in.IsConstant());
1782            DCHECK(in.GetConstant()->IsLongConstant());
1783            int64_t value = in.GetConstant()->AsLongConstant()->GetValue();
1784            __ movl(out.AsRegister<CpuRegister>(), Immediate(static_cast<int32_t>(value)));
1785          }
1786          break;
1787
1788        case Primitive::kPrimFloat: {
1789          // Processing a Dex `float-to-int' instruction.
1790          XmmRegister input = in.AsFpuRegister<XmmRegister>();
1791          CpuRegister output = out.AsRegister<CpuRegister>();
1792          XmmRegister temp = locations->GetTemp(0).AsFpuRegister<XmmRegister>();
1793          Label done, nan;
1794
1795          __ movl(output, Immediate(kPrimIntMax));
1796          // temp = int-to-float(output)
1797          __ cvtsi2ss(temp, output, false);
1798          // if input >= temp goto done
1799          __ comiss(input, temp);
1800          __ j(kAboveEqual, &done);
1801          // if input == NaN goto nan
1802          __ j(kUnordered, &nan);
1803          // output = float-to-int-truncate(input)
1804          __ cvttss2si(output, input, false);
1805          __ jmp(&done);
1806          __ Bind(&nan);
1807          //  output = 0
1808          __ xorl(output, output);
1809          __ Bind(&done);
1810          break;
1811        }
1812
1813        case Primitive::kPrimDouble: {
1814          // Processing a Dex `double-to-int' instruction.
1815          XmmRegister input = in.AsFpuRegister<XmmRegister>();
1816          CpuRegister output = out.AsRegister<CpuRegister>();
1817          XmmRegister temp = locations->GetTemp(0).AsFpuRegister<XmmRegister>();
1818          Label done, nan;
1819
1820          __ movl(output, Immediate(kPrimIntMax));
1821          // temp = int-to-double(output)
1822          __ cvtsi2sd(temp, output);
1823          // if input >= temp goto done
1824          __ comisd(input, temp);
1825          __ j(kAboveEqual, &done);
1826          // if input == NaN goto nan
1827          __ j(kUnordered, &nan);
1828          // output = double-to-int-truncate(input)
1829          __ cvttsd2si(output, input);
1830          __ jmp(&done);
1831          __ Bind(&nan);
1832          //  output = 0
1833          __ xorl(output, output);
1834          __ Bind(&done);
1835          break;
1836        }
1837
1838        default:
1839          LOG(FATAL) << "Unexpected type conversion from " << input_type
1840                     << " to " << result_type;
1841      }
1842      break;
1843
1844    case Primitive::kPrimLong:
1845      switch (input_type) {
1846        DCHECK(out.IsRegister());
1847        case Primitive::kPrimBoolean:
1848          // Boolean input is a result of code transformations.
1849        case Primitive::kPrimByte:
1850        case Primitive::kPrimShort:
1851        case Primitive::kPrimInt:
1852        case Primitive::kPrimChar:
1853          // Processing a Dex `int-to-long' instruction.
1854          DCHECK(in.IsRegister());
1855          __ movsxd(out.AsRegister<CpuRegister>(), in.AsRegister<CpuRegister>());
1856          break;
1857
1858        case Primitive::kPrimFloat: {
1859          // Processing a Dex `float-to-long' instruction.
1860          XmmRegister input = in.AsFpuRegister<XmmRegister>();
1861          CpuRegister output = out.AsRegister<CpuRegister>();
1862          XmmRegister temp = locations->GetTemp(0).AsFpuRegister<XmmRegister>();
1863          Label done, nan;
1864
1865          codegen_->Load64BitValue(output, kPrimLongMax);
1866          // temp = long-to-float(output)
1867          __ cvtsi2ss(temp, output, true);
1868          // if input >= temp goto done
1869          __ comiss(input, temp);
1870          __ j(kAboveEqual, &done);
1871          // if input == NaN goto nan
1872          __ j(kUnordered, &nan);
1873          // output = float-to-long-truncate(input)
1874          __ cvttss2si(output, input, true);
1875          __ jmp(&done);
1876          __ Bind(&nan);
1877          //  output = 0
1878          __ xorl(output, output);
1879          __ Bind(&done);
1880          break;
1881        }
1882
1883        case Primitive::kPrimDouble: {
1884          // Processing a Dex `double-to-long' instruction.
1885          XmmRegister input = in.AsFpuRegister<XmmRegister>();
1886          CpuRegister output = out.AsRegister<CpuRegister>();
1887          XmmRegister temp = locations->GetTemp(0).AsFpuRegister<XmmRegister>();
1888          Label done, nan;
1889
1890          codegen_->Load64BitValue(output, kPrimLongMax);
1891          // temp = long-to-double(output)
1892          __ cvtsi2sd(temp, output, true);
1893          // if input >= temp goto done
1894          __ comisd(input, temp);
1895          __ j(kAboveEqual, &done);
1896          // if input == NaN goto nan
1897          __ j(kUnordered, &nan);
1898          // output = double-to-long-truncate(input)
1899          __ cvttsd2si(output, input, true);
1900          __ jmp(&done);
1901          __ Bind(&nan);
1902          //  output = 0
1903          __ xorl(output, output);
1904          __ Bind(&done);
1905          break;
1906        }
1907
1908        default:
1909          LOG(FATAL) << "Unexpected type conversion from " << input_type
1910                     << " to " << result_type;
1911      }
1912      break;
1913
1914    case Primitive::kPrimChar:
1915      switch (input_type) {
1916        case Primitive::kPrimBoolean:
1917          // Boolean input is a result of code transformations.
1918        case Primitive::kPrimByte:
1919        case Primitive::kPrimShort:
1920        case Primitive::kPrimInt:
1921          // Processing a Dex `int-to-char' instruction.
1922          if (in.IsRegister()) {
1923            __ movzxw(out.AsRegister<CpuRegister>(), in.AsRegister<CpuRegister>());
1924          } else if (in.IsStackSlot()) {
1925            __ movzxw(out.AsRegister<CpuRegister>(),
1926                      Address(CpuRegister(RSP), in.GetStackIndex()));
1927          } else {
1928            DCHECK(in.GetConstant()->IsIntConstant());
1929            __ movl(out.AsRegister<CpuRegister>(),
1930                    Immediate(static_cast<uint16_t>(in.GetConstant()->AsIntConstant()->GetValue())));
1931          }
1932          break;
1933
1934        default:
1935          LOG(FATAL) << "Unexpected type conversion from " << input_type
1936                     << " to " << result_type;
1937      }
1938      break;
1939
1940    case Primitive::kPrimFloat:
1941      switch (input_type) {
1942        case Primitive::kPrimBoolean:
1943          // Boolean input is a result of code transformations.
1944        case Primitive::kPrimByte:
1945        case Primitive::kPrimShort:
1946        case Primitive::kPrimInt:
1947        case Primitive::kPrimChar:
1948          // Processing a Dex `int-to-float' instruction.
1949          if (in.IsRegister()) {
1950            __ cvtsi2ss(out.AsFpuRegister<XmmRegister>(), in.AsRegister<CpuRegister>(), false);
1951          } else if (in.IsConstant()) {
1952            int32_t v = in.GetConstant()->AsIntConstant()->GetValue();
1953            XmmRegister dest = out.AsFpuRegister<XmmRegister>();
1954            if (v == 0) {
1955              __ xorps(dest, dest);
1956            } else {
1957              __ movss(dest, codegen_->LiteralFloatAddress(static_cast<float>(v)));
1958            }
1959          } else {
1960            __ cvtsi2ss(out.AsFpuRegister<XmmRegister>(),
1961                        Address(CpuRegister(RSP), in.GetStackIndex()), false);
1962          }
1963          break;
1964
1965        case Primitive::kPrimLong:
1966          // Processing a Dex `long-to-float' instruction.
1967          if (in.IsRegister()) {
1968            __ cvtsi2ss(out.AsFpuRegister<XmmRegister>(), in.AsRegister<CpuRegister>(), true);
1969          } else if (in.IsConstant()) {
1970            int64_t v = in.GetConstant()->AsLongConstant()->GetValue();
1971            XmmRegister dest = out.AsFpuRegister<XmmRegister>();
1972            if (v == 0) {
1973              __ xorps(dest, dest);
1974            } else {
1975              __ movss(dest, codegen_->LiteralFloatAddress(static_cast<float>(v)));
1976            }
1977          } else {
1978            __ cvtsi2ss(out.AsFpuRegister<XmmRegister>(),
1979                        Address(CpuRegister(RSP), in.GetStackIndex()), true);
1980          }
1981          break;
1982
1983        case Primitive::kPrimDouble:
1984          // Processing a Dex `double-to-float' instruction.
1985          if (in.IsFpuRegister()) {
1986            __ cvtsd2ss(out.AsFpuRegister<XmmRegister>(), in.AsFpuRegister<XmmRegister>());
1987          } else if (in.IsConstant()) {
1988            double v = in.GetConstant()->AsDoubleConstant()->GetValue();
1989            XmmRegister dest = out.AsFpuRegister<XmmRegister>();
1990            if (bit_cast<int64_t, double>(v) == 0) {
1991              __ xorps(dest, dest);
1992            } else {
1993              __ movss(dest, codegen_->LiteralFloatAddress(static_cast<float>(v)));
1994            }
1995          } else {
1996            __ cvtsd2ss(out.AsFpuRegister<XmmRegister>(),
1997                        Address(CpuRegister(RSP), in.GetStackIndex()));
1998          }
1999          break;
2000
2001        default:
2002          LOG(FATAL) << "Unexpected type conversion from " << input_type
2003                     << " to " << result_type;
2004      };
2005      break;
2006
2007    case Primitive::kPrimDouble:
2008      switch (input_type) {
2009        case Primitive::kPrimBoolean:
2010          // Boolean input is a result of code transformations.
2011        case Primitive::kPrimByte:
2012        case Primitive::kPrimShort:
2013        case Primitive::kPrimInt:
2014        case Primitive::kPrimChar:
2015          // Processing a Dex `int-to-double' instruction.
2016          if (in.IsRegister()) {
2017            __ cvtsi2sd(out.AsFpuRegister<XmmRegister>(), in.AsRegister<CpuRegister>(), false);
2018          } else if (in.IsConstant()) {
2019            int32_t v = in.GetConstant()->AsIntConstant()->GetValue();
2020            XmmRegister dest = out.AsFpuRegister<XmmRegister>();
2021            if (v == 0) {
2022              __ xorpd(dest, dest);
2023            } else {
2024              __ movsd(dest, codegen_->LiteralDoubleAddress(static_cast<double>(v)));
2025            }
2026          } else {
2027            __ cvtsi2sd(out.AsFpuRegister<XmmRegister>(),
2028                        Address(CpuRegister(RSP), in.GetStackIndex()), false);
2029          }
2030          break;
2031
2032        case Primitive::kPrimLong:
2033          // Processing a Dex `long-to-double' instruction.
2034          if (in.IsRegister()) {
2035            __ cvtsi2sd(out.AsFpuRegister<XmmRegister>(), in.AsRegister<CpuRegister>(), true);
2036          } else if (in.IsConstant()) {
2037            int64_t v = in.GetConstant()->AsLongConstant()->GetValue();
2038            XmmRegister dest = out.AsFpuRegister<XmmRegister>();
2039            if (v == 0) {
2040              __ xorpd(dest, dest);
2041            } else {
2042              __ movsd(dest, codegen_->LiteralDoubleAddress(static_cast<double>(v)));
2043            }
2044          } else {
2045            __ cvtsi2sd(out.AsFpuRegister<XmmRegister>(),
2046                        Address(CpuRegister(RSP), in.GetStackIndex()), true);
2047          }
2048          break;
2049
2050        case Primitive::kPrimFloat:
2051          // Processing a Dex `float-to-double' instruction.
2052          if (in.IsFpuRegister()) {
2053            __ cvtss2sd(out.AsFpuRegister<XmmRegister>(), in.AsFpuRegister<XmmRegister>());
2054          } else if (in.IsConstant()) {
2055            float v = in.GetConstant()->AsFloatConstant()->GetValue();
2056            XmmRegister dest = out.AsFpuRegister<XmmRegister>();
2057            if (bit_cast<int32_t, float>(v) == 0) {
2058              __ xorpd(dest, dest);
2059            } else {
2060              __ movsd(dest, codegen_->LiteralDoubleAddress(static_cast<double>(v)));
2061            }
2062          } else {
2063            __ cvtss2sd(out.AsFpuRegister<XmmRegister>(),
2064                        Address(CpuRegister(RSP), in.GetStackIndex()));
2065          }
2066          break;
2067
2068        default:
2069          LOG(FATAL) << "Unexpected type conversion from " << input_type
2070                     << " to " << result_type;
2071      };
2072      break;
2073
2074    default:
2075      LOG(FATAL) << "Unexpected type conversion from " << input_type
2076                 << " to " << result_type;
2077  }
2078}
2079
2080void LocationsBuilderX86_64::VisitAdd(HAdd* add) {
2081  LocationSummary* locations =
2082      new (GetGraph()->GetArena()) LocationSummary(add, LocationSummary::kNoCall);
2083  switch (add->GetResultType()) {
2084    case Primitive::kPrimInt: {
2085      locations->SetInAt(0, Location::RequiresRegister());
2086      locations->SetInAt(1, Location::RegisterOrConstant(add->InputAt(1)));
2087      locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
2088      break;
2089    }
2090
2091    case Primitive::kPrimLong: {
2092      locations->SetInAt(0, Location::RequiresRegister());
2093      // We can use a leaq or addq if the constant can fit in an immediate.
2094      locations->SetInAt(1, Location::RegisterOrInt32LongConstant(add->InputAt(1)));
2095      locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
2096      break;
2097    }
2098
2099    case Primitive::kPrimDouble:
2100    case Primitive::kPrimFloat: {
2101      locations->SetInAt(0, Location::RequiresFpuRegister());
2102      locations->SetInAt(1, Location::Any());
2103      locations->SetOut(Location::SameAsFirstInput());
2104      break;
2105    }
2106
2107    default:
2108      LOG(FATAL) << "Unexpected add type " << add->GetResultType();
2109  }
2110}
2111
2112void InstructionCodeGeneratorX86_64::VisitAdd(HAdd* add) {
2113  LocationSummary* locations = add->GetLocations();
2114  Location first = locations->InAt(0);
2115  Location second = locations->InAt(1);
2116  Location out = locations->Out();
2117
2118  switch (add->GetResultType()) {
2119    case Primitive::kPrimInt: {
2120      if (second.IsRegister()) {
2121        if (out.AsRegister<Register>() == first.AsRegister<Register>()) {
2122          __ addl(out.AsRegister<CpuRegister>(), second.AsRegister<CpuRegister>());
2123        } else if (out.AsRegister<Register>() == second.AsRegister<Register>()) {
2124          __ addl(out.AsRegister<CpuRegister>(), first.AsRegister<CpuRegister>());
2125        } else {
2126          __ leal(out.AsRegister<CpuRegister>(), Address(
2127              first.AsRegister<CpuRegister>(), second.AsRegister<CpuRegister>(), TIMES_1, 0));
2128        }
2129      } else if (second.IsConstant()) {
2130        if (out.AsRegister<Register>() == first.AsRegister<Register>()) {
2131          __ addl(out.AsRegister<CpuRegister>(),
2132                  Immediate(second.GetConstant()->AsIntConstant()->GetValue()));
2133        } else {
2134          __ leal(out.AsRegister<CpuRegister>(), Address(
2135              first.AsRegister<CpuRegister>(), second.GetConstant()->AsIntConstant()->GetValue()));
2136        }
2137      } else {
2138        DCHECK(first.Equals(locations->Out()));
2139        __ addl(first.AsRegister<CpuRegister>(), Address(CpuRegister(RSP), second.GetStackIndex()));
2140      }
2141      break;
2142    }
2143
2144    case Primitive::kPrimLong: {
2145      if (second.IsRegister()) {
2146        if (out.AsRegister<Register>() == first.AsRegister<Register>()) {
2147          __ addq(out.AsRegister<CpuRegister>(), second.AsRegister<CpuRegister>());
2148        } else if (out.AsRegister<Register>() == second.AsRegister<Register>()) {
2149          __ addq(out.AsRegister<CpuRegister>(), first.AsRegister<CpuRegister>());
2150        } else {
2151          __ leaq(out.AsRegister<CpuRegister>(), Address(
2152              first.AsRegister<CpuRegister>(), second.AsRegister<CpuRegister>(), TIMES_1, 0));
2153        }
2154      } else {
2155        DCHECK(second.IsConstant());
2156        int64_t value = second.GetConstant()->AsLongConstant()->GetValue();
2157        int32_t int32_value = Low32Bits(value);
2158        DCHECK_EQ(int32_value, value);
2159        if (out.AsRegister<Register>() == first.AsRegister<Register>()) {
2160          __ addq(out.AsRegister<CpuRegister>(), Immediate(int32_value));
2161        } else {
2162          __ leaq(out.AsRegister<CpuRegister>(), Address(
2163              first.AsRegister<CpuRegister>(), int32_value));
2164        }
2165      }
2166      break;
2167    }
2168
2169    case Primitive::kPrimFloat: {
2170      if (second.IsFpuRegister()) {
2171        __ addss(first.AsFpuRegister<XmmRegister>(), second.AsFpuRegister<XmmRegister>());
2172      } else if (second.IsConstant()) {
2173        __ addss(first.AsFpuRegister<XmmRegister>(),
2174                 codegen_->LiteralFloatAddress(second.GetConstant()->AsFloatConstant()->GetValue()));
2175      } else {
2176        DCHECK(second.IsStackSlot());
2177        __ addss(first.AsFpuRegister<XmmRegister>(),
2178                 Address(CpuRegister(RSP), second.GetStackIndex()));
2179      }
2180      break;
2181    }
2182
2183    case Primitive::kPrimDouble: {
2184      if (second.IsFpuRegister()) {
2185        __ addsd(first.AsFpuRegister<XmmRegister>(), second.AsFpuRegister<XmmRegister>());
2186      } else if (second.IsConstant()) {
2187        __ addsd(first.AsFpuRegister<XmmRegister>(),
2188                 codegen_->LiteralDoubleAddress(second.GetConstant()->AsDoubleConstant()->GetValue()));
2189      } else {
2190        DCHECK(second.IsDoubleStackSlot());
2191        __ addsd(first.AsFpuRegister<XmmRegister>(),
2192                 Address(CpuRegister(RSP), second.GetStackIndex()));
2193      }
2194      break;
2195    }
2196
2197    default:
2198      LOG(FATAL) << "Unexpected add type " << add->GetResultType();
2199  }
2200}
2201
2202void LocationsBuilderX86_64::VisitSub(HSub* sub) {
2203  LocationSummary* locations =
2204      new (GetGraph()->GetArena()) LocationSummary(sub, LocationSummary::kNoCall);
2205  switch (sub->GetResultType()) {
2206    case Primitive::kPrimInt: {
2207      locations->SetInAt(0, Location::RequiresRegister());
2208      locations->SetInAt(1, Location::Any());
2209      locations->SetOut(Location::SameAsFirstInput());
2210      break;
2211    }
2212    case Primitive::kPrimLong: {
2213      locations->SetInAt(0, Location::RequiresRegister());
2214      locations->SetInAt(1, Location::RegisterOrInt32LongConstant(sub->InputAt(1)));
2215      locations->SetOut(Location::SameAsFirstInput());
2216      break;
2217    }
2218    case Primitive::kPrimFloat:
2219    case Primitive::kPrimDouble: {
2220      locations->SetInAt(0, Location::RequiresFpuRegister());
2221      locations->SetInAt(1, Location::Any());
2222      locations->SetOut(Location::SameAsFirstInput());
2223      break;
2224    }
2225    default:
2226      LOG(FATAL) << "Unexpected sub type " << sub->GetResultType();
2227  }
2228}
2229
2230void InstructionCodeGeneratorX86_64::VisitSub(HSub* sub) {
2231  LocationSummary* locations = sub->GetLocations();
2232  Location first = locations->InAt(0);
2233  Location second = locations->InAt(1);
2234  DCHECK(first.Equals(locations->Out()));
2235  switch (sub->GetResultType()) {
2236    case Primitive::kPrimInt: {
2237      if (second.IsRegister()) {
2238        __ subl(first.AsRegister<CpuRegister>(), second.AsRegister<CpuRegister>());
2239      } else if (second.IsConstant()) {
2240        Immediate imm(second.GetConstant()->AsIntConstant()->GetValue());
2241        __ subl(first.AsRegister<CpuRegister>(), imm);
2242      } else {
2243        __ subl(first.AsRegister<CpuRegister>(), Address(CpuRegister(RSP), second.GetStackIndex()));
2244      }
2245      break;
2246    }
2247    case Primitive::kPrimLong: {
2248      if (second.IsConstant()) {
2249        int64_t value = second.GetConstant()->AsLongConstant()->GetValue();
2250        DCHECK(IsInt<32>(value));
2251        __ subq(first.AsRegister<CpuRegister>(), Immediate(static_cast<int32_t>(value)));
2252      } else {
2253        __ subq(first.AsRegister<CpuRegister>(), second.AsRegister<CpuRegister>());
2254      }
2255      break;
2256    }
2257
2258    case Primitive::kPrimFloat: {
2259      if (second.IsFpuRegister()) {
2260        __ subss(first.AsFpuRegister<XmmRegister>(), second.AsFpuRegister<XmmRegister>());
2261      } else if (second.IsConstant()) {
2262        __ subss(first.AsFpuRegister<XmmRegister>(),
2263                 codegen_->LiteralFloatAddress(second.GetConstant()->AsFloatConstant()->GetValue()));
2264      } else {
2265        DCHECK(second.IsStackSlot());
2266        __ subss(first.AsFpuRegister<XmmRegister>(),
2267                 Address(CpuRegister(RSP), second.GetStackIndex()));
2268      }
2269      break;
2270    }
2271
2272    case Primitive::kPrimDouble: {
2273      if (second.IsFpuRegister()) {
2274        __ subsd(first.AsFpuRegister<XmmRegister>(), second.AsFpuRegister<XmmRegister>());
2275      } else if (second.IsConstant()) {
2276        __ subsd(first.AsFpuRegister<XmmRegister>(),
2277                 codegen_->LiteralDoubleAddress(second.GetConstant()->AsDoubleConstant()->GetValue()));
2278      } else {
2279        DCHECK(second.IsDoubleStackSlot());
2280        __ subsd(first.AsFpuRegister<XmmRegister>(),
2281                 Address(CpuRegister(RSP), second.GetStackIndex()));
2282      }
2283      break;
2284    }
2285
2286    default:
2287      LOG(FATAL) << "Unexpected sub type " << sub->GetResultType();
2288  }
2289}
2290
2291void LocationsBuilderX86_64::VisitMul(HMul* mul) {
2292  LocationSummary* locations =
2293      new (GetGraph()->GetArena()) LocationSummary(mul, LocationSummary::kNoCall);
2294  switch (mul->GetResultType()) {
2295    case Primitive::kPrimInt: {
2296      locations->SetInAt(0, Location::RequiresRegister());
2297      locations->SetInAt(1, Location::Any());
2298      locations->SetOut(Location::SameAsFirstInput());
2299      break;
2300    }
2301    case Primitive::kPrimLong: {
2302      locations->SetInAt(0, Location::RequiresRegister());
2303      locations->SetInAt(1, Location::RegisterOrInt32LongConstant(mul->InputAt(1)));
2304      if (locations->InAt(1).IsConstant()) {
2305        // Can use 3 operand multiply.
2306        locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
2307      } else {
2308        locations->SetOut(Location::SameAsFirstInput());
2309      }
2310      break;
2311    }
2312    case Primitive::kPrimFloat:
2313    case Primitive::kPrimDouble: {
2314      locations->SetInAt(0, Location::RequiresFpuRegister());
2315      locations->SetInAt(1, Location::Any());
2316      locations->SetOut(Location::SameAsFirstInput());
2317      break;
2318    }
2319
2320    default:
2321      LOG(FATAL) << "Unexpected mul type " << mul->GetResultType();
2322  }
2323}
2324
2325void InstructionCodeGeneratorX86_64::VisitMul(HMul* mul) {
2326  LocationSummary* locations = mul->GetLocations();
2327  Location first = locations->InAt(0);
2328  Location second = locations->InAt(1);
2329  switch (mul->GetResultType()) {
2330    case Primitive::kPrimInt: {
2331      DCHECK(first.Equals(locations->Out()));
2332      if (second.IsRegister()) {
2333        __ imull(first.AsRegister<CpuRegister>(), second.AsRegister<CpuRegister>());
2334      } else if (second.IsConstant()) {
2335        Immediate imm(second.GetConstant()->AsIntConstant()->GetValue());
2336        __ imull(first.AsRegister<CpuRegister>(), imm);
2337      } else {
2338        DCHECK(second.IsStackSlot());
2339        __ imull(first.AsRegister<CpuRegister>(),
2340                 Address(CpuRegister(RSP), second.GetStackIndex()));
2341      }
2342      break;
2343    }
2344    case Primitive::kPrimLong: {
2345      if (second.IsConstant()) {
2346        int64_t value = second.GetConstant()->AsLongConstant()->GetValue();
2347        DCHECK(IsInt<32>(value));
2348        __ imulq(locations->Out().AsRegister<CpuRegister>(),
2349                 first.AsRegister<CpuRegister>(),
2350                 Immediate(static_cast<int32_t>(value)));
2351      } else {
2352        DCHECK(first.Equals(locations->Out()));
2353        __ imulq(first.AsRegister<CpuRegister>(), second.AsRegister<CpuRegister>());
2354      }
2355      break;
2356    }
2357
2358    case Primitive::kPrimFloat: {
2359      DCHECK(first.Equals(locations->Out()));
2360      if (second.IsFpuRegister()) {
2361        __ mulss(first.AsFpuRegister<XmmRegister>(), second.AsFpuRegister<XmmRegister>());
2362      } else if (second.IsConstant()) {
2363        __ mulss(first.AsFpuRegister<XmmRegister>(),
2364                 codegen_->LiteralFloatAddress(second.GetConstant()->AsFloatConstant()->GetValue()));
2365      } else {
2366        DCHECK(second.IsStackSlot());
2367        __ mulss(first.AsFpuRegister<XmmRegister>(),
2368                 Address(CpuRegister(RSP), second.GetStackIndex()));
2369      }
2370      break;
2371    }
2372
2373    case Primitive::kPrimDouble: {
2374      DCHECK(first.Equals(locations->Out()));
2375      if (second.IsFpuRegister()) {
2376        __ mulsd(first.AsFpuRegister<XmmRegister>(), second.AsFpuRegister<XmmRegister>());
2377      } else if (second.IsConstant()) {
2378        __ mulsd(first.AsFpuRegister<XmmRegister>(),
2379                 codegen_->LiteralDoubleAddress(second.GetConstant()->AsDoubleConstant()->GetValue()));
2380      } else {
2381        DCHECK(second.IsDoubleStackSlot());
2382        __ mulsd(first.AsFpuRegister<XmmRegister>(),
2383                 Address(CpuRegister(RSP), second.GetStackIndex()));
2384      }
2385      break;
2386    }
2387
2388    default:
2389      LOG(FATAL) << "Unexpected mul type " << mul->GetResultType();
2390  }
2391}
2392
2393void InstructionCodeGeneratorX86_64::PushOntoFPStack(Location source, uint32_t temp_offset,
2394                                                     uint32_t stack_adjustment, bool is_float) {
2395  if (source.IsStackSlot()) {
2396    DCHECK(is_float);
2397    __ flds(Address(CpuRegister(RSP), source.GetStackIndex() + stack_adjustment));
2398  } else if (source.IsDoubleStackSlot()) {
2399    DCHECK(!is_float);
2400    __ fldl(Address(CpuRegister(RSP), source.GetStackIndex() + stack_adjustment));
2401  } else {
2402    // Write the value to the temporary location on the stack and load to FP stack.
2403    if (is_float) {
2404      Location stack_temp = Location::StackSlot(temp_offset);
2405      codegen_->Move(stack_temp, source);
2406      __ flds(Address(CpuRegister(RSP), temp_offset));
2407    } else {
2408      Location stack_temp = Location::DoubleStackSlot(temp_offset);
2409      codegen_->Move(stack_temp, source);
2410      __ fldl(Address(CpuRegister(RSP), temp_offset));
2411    }
2412  }
2413}
2414
2415void InstructionCodeGeneratorX86_64::GenerateRemFP(HRem *rem) {
2416  Primitive::Type type = rem->GetResultType();
2417  bool is_float = type == Primitive::kPrimFloat;
2418  size_t elem_size = Primitive::ComponentSize(type);
2419  LocationSummary* locations = rem->GetLocations();
2420  Location first = locations->InAt(0);
2421  Location second = locations->InAt(1);
2422  Location out = locations->Out();
2423
2424  // Create stack space for 2 elements.
2425  // TODO: enhance register allocator to ask for stack temporaries.
2426  __ subq(CpuRegister(RSP), Immediate(2 * elem_size));
2427
2428  // Load the values to the FP stack in reverse order, using temporaries if needed.
2429  PushOntoFPStack(second, elem_size, 2 * elem_size, is_float);
2430  PushOntoFPStack(first, 0, 2 * elem_size, is_float);
2431
2432  // Loop doing FPREM until we stabilize.
2433  Label retry;
2434  __ Bind(&retry);
2435  __ fprem();
2436
2437  // Move FP status to AX.
2438  __ fstsw();
2439
2440  // And see if the argument reduction is complete. This is signaled by the
2441  // C2 FPU flag bit set to 0.
2442  __ andl(CpuRegister(RAX), Immediate(kC2ConditionMask));
2443  __ j(kNotEqual, &retry);
2444
2445  // We have settled on the final value. Retrieve it into an XMM register.
2446  // Store FP top of stack to real stack.
2447  if (is_float) {
2448    __ fsts(Address(CpuRegister(RSP), 0));
2449  } else {
2450    __ fstl(Address(CpuRegister(RSP), 0));
2451  }
2452
2453  // Pop the 2 items from the FP stack.
2454  __ fucompp();
2455
2456  // Load the value from the stack into an XMM register.
2457  DCHECK(out.IsFpuRegister()) << out;
2458  if (is_float) {
2459    __ movss(out.AsFpuRegister<XmmRegister>(), Address(CpuRegister(RSP), 0));
2460  } else {
2461    __ movsd(out.AsFpuRegister<XmmRegister>(), Address(CpuRegister(RSP), 0));
2462  }
2463
2464  // And remove the temporary stack space we allocated.
2465  __ addq(CpuRegister(RSP), Immediate(2 * elem_size));
2466}
2467
2468void InstructionCodeGeneratorX86_64::DivRemOneOrMinusOne(HBinaryOperation* instruction) {
2469  DCHECK(instruction->IsDiv() || instruction->IsRem());
2470
2471  LocationSummary* locations = instruction->GetLocations();
2472  Location second = locations->InAt(1);
2473  DCHECK(second.IsConstant());
2474
2475  CpuRegister output_register = locations->Out().AsRegister<CpuRegister>();
2476  CpuRegister input_register = locations->InAt(0).AsRegister<CpuRegister>();
2477  int64_t imm = Int64FromConstant(second.GetConstant());
2478
2479  DCHECK(imm == 1 || imm == -1);
2480
2481  switch (instruction->GetResultType()) {
2482    case Primitive::kPrimInt: {
2483      if (instruction->IsRem()) {
2484        __ xorl(output_register, output_register);
2485      } else {
2486        __ movl(output_register, input_register);
2487        if (imm == -1) {
2488          __ negl(output_register);
2489        }
2490      }
2491      break;
2492    }
2493
2494    case Primitive::kPrimLong: {
2495      if (instruction->IsRem()) {
2496        __ xorl(output_register, output_register);
2497      } else {
2498        __ movq(output_register, input_register);
2499        if (imm == -1) {
2500          __ negq(output_register);
2501        }
2502      }
2503      break;
2504    }
2505
2506    default:
2507      LOG(FATAL) << "Unexpected type for div by (-)1 " << instruction->GetResultType();
2508  }
2509}
2510
2511void InstructionCodeGeneratorX86_64::DivByPowerOfTwo(HDiv* instruction) {
2512  LocationSummary* locations = instruction->GetLocations();
2513  Location second = locations->InAt(1);
2514
2515  CpuRegister output_register = locations->Out().AsRegister<CpuRegister>();
2516  CpuRegister numerator = locations->InAt(0).AsRegister<CpuRegister>();
2517
2518  int64_t imm = Int64FromConstant(second.GetConstant());
2519
2520  DCHECK(IsPowerOfTwo(std::abs(imm)));
2521
2522  CpuRegister tmp = locations->GetTemp(0).AsRegister<CpuRegister>();
2523
2524  if (instruction->GetResultType() == Primitive::kPrimInt) {
2525    __ leal(tmp, Address(numerator, std::abs(imm) - 1));
2526    __ testl(numerator, numerator);
2527    __ cmov(kGreaterEqual, tmp, numerator);
2528    int shift = CTZ(imm);
2529    __ sarl(tmp, Immediate(shift));
2530
2531    if (imm < 0) {
2532      __ negl(tmp);
2533    }
2534
2535    __ movl(output_register, tmp);
2536  } else {
2537    DCHECK_EQ(instruction->GetResultType(), Primitive::kPrimLong);
2538    CpuRegister rdx = locations->GetTemp(0).AsRegister<CpuRegister>();
2539
2540    codegen_->Load64BitValue(rdx, std::abs(imm) - 1);
2541    __ addq(rdx, numerator);
2542    __ testq(numerator, numerator);
2543    __ cmov(kGreaterEqual, rdx, numerator);
2544    int shift = CTZ(imm);
2545    __ sarq(rdx, Immediate(shift));
2546
2547    if (imm < 0) {
2548      __ negq(rdx);
2549    }
2550
2551    __ movq(output_register, rdx);
2552  }
2553}
2554
2555void InstructionCodeGeneratorX86_64::GenerateDivRemWithAnyConstant(HBinaryOperation* instruction) {
2556  DCHECK(instruction->IsDiv() || instruction->IsRem());
2557
2558  LocationSummary* locations = instruction->GetLocations();
2559  Location second = locations->InAt(1);
2560
2561  CpuRegister numerator = instruction->IsDiv() ? locations->GetTemp(1).AsRegister<CpuRegister>()
2562      : locations->GetTemp(0).AsRegister<CpuRegister>();
2563  CpuRegister eax = locations->InAt(0).AsRegister<CpuRegister>();
2564  CpuRegister edx = instruction->IsDiv() ? locations->GetTemp(0).AsRegister<CpuRegister>()
2565      : locations->Out().AsRegister<CpuRegister>();
2566  CpuRegister out = locations->Out().AsRegister<CpuRegister>();
2567
2568  DCHECK_EQ(RAX, eax.AsRegister());
2569  DCHECK_EQ(RDX, edx.AsRegister());
2570  if (instruction->IsDiv()) {
2571    DCHECK_EQ(RAX, out.AsRegister());
2572  } else {
2573    DCHECK_EQ(RDX, out.AsRegister());
2574  }
2575
2576  int64_t magic;
2577  int shift;
2578
2579  // TODO: can these branches be written as one?
2580  if (instruction->GetResultType() == Primitive::kPrimInt) {
2581    int imm = second.GetConstant()->AsIntConstant()->GetValue();
2582
2583    CalculateMagicAndShiftForDivRem(imm, false /* is_long */, &magic, &shift);
2584
2585    __ movl(numerator, eax);
2586
2587    Label no_div;
2588    Label end;
2589    __ testl(eax, eax);
2590    __ j(kNotEqual, &no_div);
2591
2592    __ xorl(out, out);
2593    __ jmp(&end);
2594
2595    __ Bind(&no_div);
2596
2597    __ movl(eax, Immediate(magic));
2598    __ imull(numerator);
2599
2600    if (imm > 0 && magic < 0) {
2601      __ addl(edx, numerator);
2602    } else if (imm < 0 && magic > 0) {
2603      __ subl(edx, numerator);
2604    }
2605
2606    if (shift != 0) {
2607      __ sarl(edx, Immediate(shift));
2608    }
2609
2610    __ movl(eax, edx);
2611    __ shrl(edx, Immediate(31));
2612    __ addl(edx, eax);
2613
2614    if (instruction->IsRem()) {
2615      __ movl(eax, numerator);
2616      __ imull(edx, Immediate(imm));
2617      __ subl(eax, edx);
2618      __ movl(edx, eax);
2619    } else {
2620      __ movl(eax, edx);
2621    }
2622    __ Bind(&end);
2623  } else {
2624    int64_t imm = second.GetConstant()->AsLongConstant()->GetValue();
2625
2626    DCHECK_EQ(instruction->GetResultType(), Primitive::kPrimLong);
2627
2628    CpuRegister rax = eax;
2629    CpuRegister rdx = edx;
2630
2631    CalculateMagicAndShiftForDivRem(imm, true /* is_long */, &magic, &shift);
2632
2633    // Save the numerator.
2634    __ movq(numerator, rax);
2635
2636    // RAX = magic
2637    codegen_->Load64BitValue(rax, magic);
2638
2639    // RDX:RAX = magic * numerator
2640    __ imulq(numerator);
2641
2642    if (imm > 0 && magic < 0) {
2643      // RDX += numerator
2644      __ addq(rdx, numerator);
2645    } else if (imm < 0 && magic > 0) {
2646      // RDX -= numerator
2647      __ subq(rdx, numerator);
2648    }
2649
2650    // Shift if needed.
2651    if (shift != 0) {
2652      __ sarq(rdx, Immediate(shift));
2653    }
2654
2655    // RDX += 1 if RDX < 0
2656    __ movq(rax, rdx);
2657    __ shrq(rdx, Immediate(63));
2658    __ addq(rdx, rax);
2659
2660    if (instruction->IsRem()) {
2661      __ movq(rax, numerator);
2662
2663      if (IsInt<32>(imm)) {
2664        __ imulq(rdx, Immediate(static_cast<int32_t>(imm)));
2665      } else {
2666        __ imulq(rdx, codegen_->LiteralInt64Address(imm));
2667      }
2668
2669      __ subq(rax, rdx);
2670      __ movq(rdx, rax);
2671    } else {
2672      __ movq(rax, rdx);
2673    }
2674  }
2675}
2676
2677void InstructionCodeGeneratorX86_64::GenerateDivRemIntegral(HBinaryOperation* instruction) {
2678  DCHECK(instruction->IsDiv() || instruction->IsRem());
2679  Primitive::Type type = instruction->GetResultType();
2680  DCHECK(type == Primitive::kPrimInt || Primitive::kPrimLong);
2681
2682  bool is_div = instruction->IsDiv();
2683  LocationSummary* locations = instruction->GetLocations();
2684
2685  CpuRegister out = locations->Out().AsRegister<CpuRegister>();
2686  Location second = locations->InAt(1);
2687
2688  DCHECK_EQ(RAX, locations->InAt(0).AsRegister<CpuRegister>().AsRegister());
2689  DCHECK_EQ(is_div ? RAX : RDX, out.AsRegister());
2690
2691  if (second.IsConstant()) {
2692    int64_t imm = Int64FromConstant(second.GetConstant());
2693
2694    if (imm == 0) {
2695      // Do not generate anything. DivZeroCheck would prevent any code to be executed.
2696    } else if (imm == 1 || imm == -1) {
2697      DivRemOneOrMinusOne(instruction);
2698    } else if (instruction->IsDiv() && IsPowerOfTwo(std::abs(imm))) {
2699      DivByPowerOfTwo(instruction->AsDiv());
2700    } else {
2701      DCHECK(imm <= -2 || imm >= 2);
2702      GenerateDivRemWithAnyConstant(instruction);
2703    }
2704  } else {
2705    SlowPathCodeX86_64* slow_path =
2706        new (GetGraph()->GetArena()) DivRemMinusOneSlowPathX86_64(
2707            out.AsRegister(), type, is_div);
2708    codegen_->AddSlowPath(slow_path);
2709
2710    CpuRegister second_reg = second.AsRegister<CpuRegister>();
2711    // 0x80000000(00000000)/-1 triggers an arithmetic exception!
2712    // Dividing by -1 is actually negation and -0x800000000(00000000) = 0x80000000(00000000)
2713    // so it's safe to just use negl instead of more complex comparisons.
2714    if (type == Primitive::kPrimInt) {
2715      __ cmpl(second_reg, Immediate(-1));
2716      __ j(kEqual, slow_path->GetEntryLabel());
2717      // edx:eax <- sign-extended of eax
2718      __ cdq();
2719      // eax = quotient, edx = remainder
2720      __ idivl(second_reg);
2721    } else {
2722      __ cmpq(second_reg, Immediate(-1));
2723      __ j(kEqual, slow_path->GetEntryLabel());
2724      // rdx:rax <- sign-extended of rax
2725      __ cqo();
2726      // rax = quotient, rdx = remainder
2727      __ idivq(second_reg);
2728    }
2729    __ Bind(slow_path->GetExitLabel());
2730  }
2731}
2732
2733void LocationsBuilderX86_64::VisitDiv(HDiv* div) {
2734  LocationSummary* locations =
2735      new (GetGraph()->GetArena()) LocationSummary(div, LocationSummary::kNoCall);
2736  switch (div->GetResultType()) {
2737    case Primitive::kPrimInt:
2738    case Primitive::kPrimLong: {
2739      locations->SetInAt(0, Location::RegisterLocation(RAX));
2740      locations->SetInAt(1, Location::RegisterOrConstant(div->InputAt(1)));
2741      locations->SetOut(Location::SameAsFirstInput());
2742      // Intel uses edx:eax as the dividend.
2743      locations->AddTemp(Location::RegisterLocation(RDX));
2744      // We need to save the numerator while we tweak rax and rdx. As we are using imul in a way
2745      // which enforces results to be in RAX and RDX, things are simpler if we use RDX also as
2746      // output and request another temp.
2747      if (div->InputAt(1)->IsConstant()) {
2748        locations->AddTemp(Location::RequiresRegister());
2749      }
2750      break;
2751    }
2752
2753    case Primitive::kPrimFloat:
2754    case Primitive::kPrimDouble: {
2755      locations->SetInAt(0, Location::RequiresFpuRegister());
2756      locations->SetInAt(1, Location::Any());
2757      locations->SetOut(Location::SameAsFirstInput());
2758      break;
2759    }
2760
2761    default:
2762      LOG(FATAL) << "Unexpected div type " << div->GetResultType();
2763  }
2764}
2765
2766void InstructionCodeGeneratorX86_64::VisitDiv(HDiv* div) {
2767  LocationSummary* locations = div->GetLocations();
2768  Location first = locations->InAt(0);
2769  Location second = locations->InAt(1);
2770  DCHECK(first.Equals(locations->Out()));
2771
2772  Primitive::Type type = div->GetResultType();
2773  switch (type) {
2774    case Primitive::kPrimInt:
2775    case Primitive::kPrimLong: {
2776      GenerateDivRemIntegral(div);
2777      break;
2778    }
2779
2780    case Primitive::kPrimFloat: {
2781      if (second.IsFpuRegister()) {
2782        __ divss(first.AsFpuRegister<XmmRegister>(), second.AsFpuRegister<XmmRegister>());
2783      } else if (second.IsConstant()) {
2784        __ divss(first.AsFpuRegister<XmmRegister>(),
2785                 codegen_->LiteralFloatAddress(second.GetConstant()->AsFloatConstant()->GetValue()));
2786      } else {
2787        DCHECK(second.IsStackSlot());
2788        __ divss(first.AsFpuRegister<XmmRegister>(),
2789                 Address(CpuRegister(RSP), second.GetStackIndex()));
2790      }
2791      break;
2792    }
2793
2794    case Primitive::kPrimDouble: {
2795      if (second.IsFpuRegister()) {
2796        __ divsd(first.AsFpuRegister<XmmRegister>(), second.AsFpuRegister<XmmRegister>());
2797      } else if (second.IsConstant()) {
2798        __ divsd(first.AsFpuRegister<XmmRegister>(),
2799                 codegen_->LiteralDoubleAddress(second.GetConstant()->AsDoubleConstant()->GetValue()));
2800      } else {
2801        DCHECK(second.IsDoubleStackSlot());
2802        __ divsd(first.AsFpuRegister<XmmRegister>(),
2803                 Address(CpuRegister(RSP), second.GetStackIndex()));
2804      }
2805      break;
2806    }
2807
2808    default:
2809      LOG(FATAL) << "Unexpected div type " << div->GetResultType();
2810  }
2811}
2812
2813void LocationsBuilderX86_64::VisitRem(HRem* rem) {
2814  Primitive::Type type = rem->GetResultType();
2815  LocationSummary* locations =
2816    new (GetGraph()->GetArena()) LocationSummary(rem, LocationSummary::kNoCall);
2817
2818  switch (type) {
2819    case Primitive::kPrimInt:
2820    case Primitive::kPrimLong: {
2821      locations->SetInAt(0, Location::RegisterLocation(RAX));
2822      locations->SetInAt(1, Location::RegisterOrConstant(rem->InputAt(1)));
2823      // Intel uses rdx:rax as the dividend and puts the remainder in rdx
2824      locations->SetOut(Location::RegisterLocation(RDX));
2825      // We need to save the numerator while we tweak eax and edx. As we are using imul in a way
2826      // which enforces results to be in RAX and RDX, things are simpler if we use EAX also as
2827      // output and request another temp.
2828      if (rem->InputAt(1)->IsConstant()) {
2829        locations->AddTemp(Location::RequiresRegister());
2830      }
2831      break;
2832    }
2833
2834    case Primitive::kPrimFloat:
2835    case Primitive::kPrimDouble: {
2836      locations->SetInAt(0, Location::Any());
2837      locations->SetInAt(1, Location::Any());
2838      locations->SetOut(Location::RequiresFpuRegister());
2839      locations->AddTemp(Location::RegisterLocation(RAX));
2840      break;
2841    }
2842
2843    default:
2844      LOG(FATAL) << "Unexpected rem type " << type;
2845  }
2846}
2847
2848void InstructionCodeGeneratorX86_64::VisitRem(HRem* rem) {
2849  Primitive::Type type = rem->GetResultType();
2850  switch (type) {
2851    case Primitive::kPrimInt:
2852    case Primitive::kPrimLong: {
2853      GenerateDivRemIntegral(rem);
2854      break;
2855    }
2856    case Primitive::kPrimFloat:
2857    case Primitive::kPrimDouble: {
2858      GenerateRemFP(rem);
2859      break;
2860    }
2861    default:
2862      LOG(FATAL) << "Unexpected rem type " << rem->GetResultType();
2863  }
2864}
2865
2866void LocationsBuilderX86_64::VisitDivZeroCheck(HDivZeroCheck* instruction) {
2867  LocationSummary* locations =
2868      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
2869  locations->SetInAt(0, Location::Any());
2870  if (instruction->HasUses()) {
2871    locations->SetOut(Location::SameAsFirstInput());
2872  }
2873}
2874
2875void InstructionCodeGeneratorX86_64::VisitDivZeroCheck(HDivZeroCheck* instruction) {
2876  SlowPathCodeX86_64* slow_path =
2877      new (GetGraph()->GetArena()) DivZeroCheckSlowPathX86_64(instruction);
2878  codegen_->AddSlowPath(slow_path);
2879
2880  LocationSummary* locations = instruction->GetLocations();
2881  Location value = locations->InAt(0);
2882
2883  switch (instruction->GetType()) {
2884    case Primitive::kPrimInt: {
2885      if (value.IsRegister()) {
2886        __ testl(value.AsRegister<CpuRegister>(), value.AsRegister<CpuRegister>());
2887        __ j(kEqual, slow_path->GetEntryLabel());
2888      } else if (value.IsStackSlot()) {
2889        __ cmpl(Address(CpuRegister(RSP), value.GetStackIndex()), Immediate(0));
2890        __ j(kEqual, slow_path->GetEntryLabel());
2891      } else {
2892        DCHECK(value.IsConstant()) << value;
2893        if (value.GetConstant()->AsIntConstant()->GetValue() == 0) {
2894        __ jmp(slow_path->GetEntryLabel());
2895        }
2896      }
2897      break;
2898    }
2899    case Primitive::kPrimLong: {
2900      if (value.IsRegister()) {
2901        __ testq(value.AsRegister<CpuRegister>(), value.AsRegister<CpuRegister>());
2902        __ j(kEqual, slow_path->GetEntryLabel());
2903      } else if (value.IsDoubleStackSlot()) {
2904        __ cmpq(Address(CpuRegister(RSP), value.GetStackIndex()), Immediate(0));
2905        __ j(kEqual, slow_path->GetEntryLabel());
2906      } else {
2907        DCHECK(value.IsConstant()) << value;
2908        if (value.GetConstant()->AsLongConstant()->GetValue() == 0) {
2909        __ jmp(slow_path->GetEntryLabel());
2910        }
2911      }
2912      break;
2913    }
2914    default:
2915      LOG(FATAL) << "Unexpected type for HDivZeroCheck " << instruction->GetType();
2916  }
2917}
2918
2919void LocationsBuilderX86_64::HandleShift(HBinaryOperation* op) {
2920  DCHECK(op->IsShl() || op->IsShr() || op->IsUShr());
2921
2922  LocationSummary* locations =
2923      new (GetGraph()->GetArena()) LocationSummary(op, LocationSummary::kNoCall);
2924
2925  switch (op->GetResultType()) {
2926    case Primitive::kPrimInt:
2927    case Primitive::kPrimLong: {
2928      locations->SetInAt(0, Location::RequiresRegister());
2929      // The shift count needs to be in CL.
2930      locations->SetInAt(1, Location::ByteRegisterOrConstant(RCX, op->InputAt(1)));
2931      locations->SetOut(Location::SameAsFirstInput());
2932      break;
2933    }
2934    default:
2935      LOG(FATAL) << "Unexpected operation type " << op->GetResultType();
2936  }
2937}
2938
2939void InstructionCodeGeneratorX86_64::HandleShift(HBinaryOperation* op) {
2940  DCHECK(op->IsShl() || op->IsShr() || op->IsUShr());
2941
2942  LocationSummary* locations = op->GetLocations();
2943  CpuRegister first_reg = locations->InAt(0).AsRegister<CpuRegister>();
2944  Location second = locations->InAt(1);
2945
2946  switch (op->GetResultType()) {
2947    case Primitive::kPrimInt: {
2948      if (second.IsRegister()) {
2949        CpuRegister second_reg = second.AsRegister<CpuRegister>();
2950        if (op->IsShl()) {
2951          __ shll(first_reg, second_reg);
2952        } else if (op->IsShr()) {
2953          __ sarl(first_reg, second_reg);
2954        } else {
2955          __ shrl(first_reg, second_reg);
2956        }
2957      } else {
2958        Immediate imm(second.GetConstant()->AsIntConstant()->GetValue() & kMaxIntShiftValue);
2959        if (op->IsShl()) {
2960          __ shll(first_reg, imm);
2961        } else if (op->IsShr()) {
2962          __ sarl(first_reg, imm);
2963        } else {
2964          __ shrl(first_reg, imm);
2965        }
2966      }
2967      break;
2968    }
2969    case Primitive::kPrimLong: {
2970      if (second.IsRegister()) {
2971        CpuRegister second_reg = second.AsRegister<CpuRegister>();
2972        if (op->IsShl()) {
2973          __ shlq(first_reg, second_reg);
2974        } else if (op->IsShr()) {
2975          __ sarq(first_reg, second_reg);
2976        } else {
2977          __ shrq(first_reg, second_reg);
2978        }
2979      } else {
2980        Immediate imm(second.GetConstant()->AsIntConstant()->GetValue() & kMaxLongShiftValue);
2981        if (op->IsShl()) {
2982          __ shlq(first_reg, imm);
2983        } else if (op->IsShr()) {
2984          __ sarq(first_reg, imm);
2985        } else {
2986          __ shrq(first_reg, imm);
2987        }
2988      }
2989      break;
2990    }
2991    default:
2992      LOG(FATAL) << "Unexpected operation type " << op->GetResultType();
2993  }
2994}
2995
2996void LocationsBuilderX86_64::VisitShl(HShl* shl) {
2997  HandleShift(shl);
2998}
2999
3000void InstructionCodeGeneratorX86_64::VisitShl(HShl* shl) {
3001  HandleShift(shl);
3002}
3003
3004void LocationsBuilderX86_64::VisitShr(HShr* shr) {
3005  HandleShift(shr);
3006}
3007
3008void InstructionCodeGeneratorX86_64::VisitShr(HShr* shr) {
3009  HandleShift(shr);
3010}
3011
3012void LocationsBuilderX86_64::VisitUShr(HUShr* ushr) {
3013  HandleShift(ushr);
3014}
3015
3016void InstructionCodeGeneratorX86_64::VisitUShr(HUShr* ushr) {
3017  HandleShift(ushr);
3018}
3019
3020void LocationsBuilderX86_64::VisitNewInstance(HNewInstance* instruction) {
3021  LocationSummary* locations =
3022      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCall);
3023  InvokeRuntimeCallingConvention calling_convention;
3024  locations->AddTemp(Location::RegisterLocation(calling_convention.GetRegisterAt(0)));
3025  locations->AddTemp(Location::RegisterLocation(calling_convention.GetRegisterAt(1)));
3026  locations->SetOut(Location::RegisterLocation(RAX));
3027}
3028
3029void InstructionCodeGeneratorX86_64::VisitNewInstance(HNewInstance* instruction) {
3030  InvokeRuntimeCallingConvention calling_convention;
3031  codegen_->LoadCurrentMethod(CpuRegister(calling_convention.GetRegisterAt(1)));
3032  codegen_->Load64BitValue(CpuRegister(calling_convention.GetRegisterAt(0)),
3033                           instruction->GetTypeIndex());
3034  __ gs()->call(
3035      Address::Absolute(GetThreadOffset<kX86_64WordSize>(instruction->GetEntrypoint()), true));
3036
3037  DCHECK(!codegen_->IsLeafMethod());
3038  codegen_->RecordPcInfo(instruction, instruction->GetDexPc());
3039}
3040
3041void LocationsBuilderX86_64::VisitNewArray(HNewArray* instruction) {
3042  LocationSummary* locations =
3043      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCall);
3044  InvokeRuntimeCallingConvention calling_convention;
3045  locations->AddTemp(Location::RegisterLocation(calling_convention.GetRegisterAt(0)));
3046  locations->AddTemp(Location::RegisterLocation(calling_convention.GetRegisterAt(2)));
3047  locations->SetOut(Location::RegisterLocation(RAX));
3048  locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(1)));
3049}
3050
3051void InstructionCodeGeneratorX86_64::VisitNewArray(HNewArray* instruction) {
3052  InvokeRuntimeCallingConvention calling_convention;
3053  codegen_->LoadCurrentMethod(CpuRegister(calling_convention.GetRegisterAt(2)));
3054  codegen_->Load64BitValue(CpuRegister(calling_convention.GetRegisterAt(0)),
3055                           instruction->GetTypeIndex());
3056
3057  __ gs()->call(
3058      Address::Absolute(GetThreadOffset<kX86_64WordSize>(instruction->GetEntrypoint()), true));
3059
3060  DCHECK(!codegen_->IsLeafMethod());
3061  codegen_->RecordPcInfo(instruction, instruction->GetDexPc());
3062}
3063
3064void LocationsBuilderX86_64::VisitParameterValue(HParameterValue* instruction) {
3065  LocationSummary* locations =
3066      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
3067  Location location = parameter_visitor_.GetNextLocation(instruction->GetType());
3068  if (location.IsStackSlot()) {
3069    location = Location::StackSlot(location.GetStackIndex() + codegen_->GetFrameSize());
3070  } else if (location.IsDoubleStackSlot()) {
3071    location = Location::DoubleStackSlot(location.GetStackIndex() + codegen_->GetFrameSize());
3072  }
3073  locations->SetOut(location);
3074}
3075
3076void InstructionCodeGeneratorX86_64::VisitParameterValue(
3077    HParameterValue* instruction ATTRIBUTE_UNUSED) {
3078  // Nothing to do, the parameter is already at its location.
3079}
3080
3081void LocationsBuilderX86_64::VisitCurrentMethod(HCurrentMethod* instruction) {
3082  LocationSummary* locations =
3083      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
3084  locations->SetOut(Location::RegisterLocation(kMethodRegisterArgument));
3085}
3086
3087void InstructionCodeGeneratorX86_64::VisitCurrentMethod(
3088    HCurrentMethod* instruction ATTRIBUTE_UNUSED) {
3089  // Nothing to do, the method is already at its location.
3090}
3091
3092void LocationsBuilderX86_64::VisitNot(HNot* not_) {
3093  LocationSummary* locations =
3094      new (GetGraph()->GetArena()) LocationSummary(not_, LocationSummary::kNoCall);
3095  locations->SetInAt(0, Location::RequiresRegister());
3096  locations->SetOut(Location::SameAsFirstInput());
3097}
3098
3099void InstructionCodeGeneratorX86_64::VisitNot(HNot* not_) {
3100  LocationSummary* locations = not_->GetLocations();
3101  DCHECK_EQ(locations->InAt(0).AsRegister<CpuRegister>().AsRegister(),
3102            locations->Out().AsRegister<CpuRegister>().AsRegister());
3103  Location out = locations->Out();
3104  switch (not_->GetResultType()) {
3105    case Primitive::kPrimInt:
3106      __ notl(out.AsRegister<CpuRegister>());
3107      break;
3108
3109    case Primitive::kPrimLong:
3110      __ notq(out.AsRegister<CpuRegister>());
3111      break;
3112
3113    default:
3114      LOG(FATAL) << "Unimplemented type for not operation " << not_->GetResultType();
3115  }
3116}
3117
3118void LocationsBuilderX86_64::VisitBooleanNot(HBooleanNot* bool_not) {
3119  LocationSummary* locations =
3120      new (GetGraph()->GetArena()) LocationSummary(bool_not, LocationSummary::kNoCall);
3121  locations->SetInAt(0, Location::RequiresRegister());
3122  locations->SetOut(Location::SameAsFirstInput());
3123}
3124
3125void InstructionCodeGeneratorX86_64::VisitBooleanNot(HBooleanNot* bool_not) {
3126  LocationSummary* locations = bool_not->GetLocations();
3127  DCHECK_EQ(locations->InAt(0).AsRegister<CpuRegister>().AsRegister(),
3128            locations->Out().AsRegister<CpuRegister>().AsRegister());
3129  Location out = locations->Out();
3130  __ xorl(out.AsRegister<CpuRegister>(), Immediate(1));
3131}
3132
3133void LocationsBuilderX86_64::VisitPhi(HPhi* instruction) {
3134  LocationSummary* locations =
3135      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
3136  for (size_t i = 0, e = instruction->InputCount(); i < e; ++i) {
3137    locations->SetInAt(i, Location::Any());
3138  }
3139  locations->SetOut(Location::Any());
3140}
3141
3142void InstructionCodeGeneratorX86_64::VisitPhi(HPhi* instruction) {
3143  UNUSED(instruction);
3144  LOG(FATAL) << "Unimplemented";
3145}
3146
3147void InstructionCodeGeneratorX86_64::GenerateMemoryBarrier(MemBarrierKind kind) {
3148  /*
3149   * According to the JSR-133 Cookbook, for x86 only StoreLoad/AnyAny barriers need memory fence.
3150   * All other barriers (LoadAny, AnyStore, StoreStore) are nops due to the x86 memory model.
3151   * For those cases, all we need to ensure is that there is a scheduling barrier in place.
3152   */
3153  switch (kind) {
3154    case MemBarrierKind::kAnyAny: {
3155      __ mfence();
3156      break;
3157    }
3158    case MemBarrierKind::kAnyStore:
3159    case MemBarrierKind::kLoadAny:
3160    case MemBarrierKind::kStoreStore: {
3161      // nop
3162      break;
3163    }
3164    default:
3165      LOG(FATAL) << "Unexpected memory barier " << kind;
3166  }
3167}
3168
3169void LocationsBuilderX86_64::HandleFieldGet(HInstruction* instruction) {
3170  DCHECK(instruction->IsInstanceFieldGet() || instruction->IsStaticFieldGet());
3171
3172  LocationSummary* locations =
3173      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
3174  locations->SetInAt(0, Location::RequiresRegister());
3175  if (Primitive::IsFloatingPointType(instruction->GetType())) {
3176    locations->SetOut(Location::RequiresFpuRegister());
3177  } else {
3178    locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
3179  }
3180}
3181
3182void InstructionCodeGeneratorX86_64::HandleFieldGet(HInstruction* instruction,
3183                                                    const FieldInfo& field_info) {
3184  DCHECK(instruction->IsInstanceFieldGet() || instruction->IsStaticFieldGet());
3185
3186  LocationSummary* locations = instruction->GetLocations();
3187  CpuRegister base = locations->InAt(0).AsRegister<CpuRegister>();
3188  Location out = locations->Out();
3189  bool is_volatile = field_info.IsVolatile();
3190  Primitive::Type field_type = field_info.GetFieldType();
3191  uint32_t offset = field_info.GetFieldOffset().Uint32Value();
3192
3193  switch (field_type) {
3194    case Primitive::kPrimBoolean: {
3195      __ movzxb(out.AsRegister<CpuRegister>(), Address(base, offset));
3196      break;
3197    }
3198
3199    case Primitive::kPrimByte: {
3200      __ movsxb(out.AsRegister<CpuRegister>(), Address(base, offset));
3201      break;
3202    }
3203
3204    case Primitive::kPrimShort: {
3205      __ movsxw(out.AsRegister<CpuRegister>(), Address(base, offset));
3206      break;
3207    }
3208
3209    case Primitive::kPrimChar: {
3210      __ movzxw(out.AsRegister<CpuRegister>(), Address(base, offset));
3211      break;
3212    }
3213
3214    case Primitive::kPrimInt:
3215    case Primitive::kPrimNot: {
3216      __ movl(out.AsRegister<CpuRegister>(), Address(base, offset));
3217      break;
3218    }
3219
3220    case Primitive::kPrimLong: {
3221      __ movq(out.AsRegister<CpuRegister>(), Address(base, offset));
3222      break;
3223    }
3224
3225    case Primitive::kPrimFloat: {
3226      __ movss(out.AsFpuRegister<XmmRegister>(), Address(base, offset));
3227      break;
3228    }
3229
3230    case Primitive::kPrimDouble: {
3231      __ movsd(out.AsFpuRegister<XmmRegister>(), Address(base, offset));
3232      break;
3233    }
3234
3235    case Primitive::kPrimVoid:
3236      LOG(FATAL) << "Unreachable type " << field_type;
3237      UNREACHABLE();
3238  }
3239
3240  codegen_->MaybeRecordImplicitNullCheck(instruction);
3241
3242  if (is_volatile) {
3243    GenerateMemoryBarrier(MemBarrierKind::kLoadAny);
3244  }
3245}
3246
3247void LocationsBuilderX86_64::HandleFieldSet(HInstruction* instruction,
3248                                            const FieldInfo& field_info) {
3249  DCHECK(instruction->IsInstanceFieldSet() || instruction->IsStaticFieldSet());
3250
3251  LocationSummary* locations =
3252      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
3253  bool needs_write_barrier =
3254      CodeGenerator::StoreNeedsWriteBarrier(field_info.GetFieldType(), instruction->InputAt(1));
3255
3256  locations->SetInAt(0, Location::RequiresRegister());
3257  if (Primitive::IsFloatingPointType(instruction->InputAt(1)->GetType())) {
3258    locations->SetInAt(1, Location::RequiresFpuRegister());
3259  } else {
3260    locations->SetInAt(1, Location::RegisterOrInt32LongConstant(instruction->InputAt(1)));
3261  }
3262  if (needs_write_barrier) {
3263    // Temporary registers for the write barrier.
3264    locations->AddTemp(Location::RequiresRegister());
3265    locations->AddTemp(Location::RequiresRegister());
3266  }
3267}
3268
3269void InstructionCodeGeneratorX86_64::HandleFieldSet(HInstruction* instruction,
3270                                                    const FieldInfo& field_info,
3271                                                    bool value_can_be_null) {
3272  DCHECK(instruction->IsInstanceFieldSet() || instruction->IsStaticFieldSet());
3273
3274  LocationSummary* locations = instruction->GetLocations();
3275  CpuRegister base = locations->InAt(0).AsRegister<CpuRegister>();
3276  Location value = locations->InAt(1);
3277  bool is_volatile = field_info.IsVolatile();
3278  Primitive::Type field_type = field_info.GetFieldType();
3279  uint32_t offset = field_info.GetFieldOffset().Uint32Value();
3280
3281  if (is_volatile) {
3282    GenerateMemoryBarrier(MemBarrierKind::kAnyStore);
3283  }
3284
3285  switch (field_type) {
3286    case Primitive::kPrimBoolean:
3287    case Primitive::kPrimByte: {
3288      if (value.IsConstant()) {
3289        int32_t v = CodeGenerator::GetInt32ValueOf(value.GetConstant());
3290        __ movb(Address(base, offset), Immediate(v));
3291      } else {
3292        __ movb(Address(base, offset), value.AsRegister<CpuRegister>());
3293      }
3294      break;
3295    }
3296
3297    case Primitive::kPrimShort:
3298    case Primitive::kPrimChar: {
3299      if (value.IsConstant()) {
3300        int32_t v = CodeGenerator::GetInt32ValueOf(value.GetConstant());
3301        __ movw(Address(base, offset), Immediate(v));
3302      } else {
3303        __ movw(Address(base, offset), value.AsRegister<CpuRegister>());
3304      }
3305      break;
3306    }
3307
3308    case Primitive::kPrimInt:
3309    case Primitive::kPrimNot: {
3310      if (value.IsConstant()) {
3311        int32_t v = CodeGenerator::GetInt32ValueOf(value.GetConstant());
3312        __ movw(Address(base, offset), Immediate(v));
3313      } else {
3314        __ movl(Address(base, offset), value.AsRegister<CpuRegister>());
3315      }
3316      break;
3317    }
3318
3319    case Primitive::kPrimLong: {
3320      if (value.IsConstant()) {
3321        int64_t v = value.GetConstant()->AsLongConstant()->GetValue();
3322        DCHECK(IsInt<32>(v));
3323        int32_t v_32 = v;
3324        __ movq(Address(base, offset), Immediate(v_32));
3325      } else {
3326        __ movq(Address(base, offset), value.AsRegister<CpuRegister>());
3327      }
3328      break;
3329    }
3330
3331    case Primitive::kPrimFloat: {
3332      __ movss(Address(base, offset), value.AsFpuRegister<XmmRegister>());
3333      break;
3334    }
3335
3336    case Primitive::kPrimDouble: {
3337      __ movsd(Address(base, offset), value.AsFpuRegister<XmmRegister>());
3338      break;
3339    }
3340
3341    case Primitive::kPrimVoid:
3342      LOG(FATAL) << "Unreachable type " << field_type;
3343      UNREACHABLE();
3344  }
3345
3346  codegen_->MaybeRecordImplicitNullCheck(instruction);
3347
3348  if (CodeGenerator::StoreNeedsWriteBarrier(field_type, instruction->InputAt(1))) {
3349    CpuRegister temp = locations->GetTemp(0).AsRegister<CpuRegister>();
3350    CpuRegister card = locations->GetTemp(1).AsRegister<CpuRegister>();
3351    codegen_->MarkGCCard(temp, card, base, value.AsRegister<CpuRegister>(), value_can_be_null);
3352  }
3353
3354  if (is_volatile) {
3355    GenerateMemoryBarrier(MemBarrierKind::kAnyAny);
3356  }
3357}
3358
3359void LocationsBuilderX86_64::VisitInstanceFieldSet(HInstanceFieldSet* instruction) {
3360  HandleFieldSet(instruction, instruction->GetFieldInfo());
3361}
3362
3363void InstructionCodeGeneratorX86_64::VisitInstanceFieldSet(HInstanceFieldSet* instruction) {
3364  HandleFieldSet(instruction, instruction->GetFieldInfo(), instruction->GetValueCanBeNull());
3365}
3366
3367void LocationsBuilderX86_64::VisitInstanceFieldGet(HInstanceFieldGet* instruction) {
3368  HandleFieldGet(instruction);
3369}
3370
3371void InstructionCodeGeneratorX86_64::VisitInstanceFieldGet(HInstanceFieldGet* instruction) {
3372  HandleFieldGet(instruction, instruction->GetFieldInfo());
3373}
3374
3375void LocationsBuilderX86_64::VisitStaticFieldGet(HStaticFieldGet* instruction) {
3376  HandleFieldGet(instruction);
3377}
3378
3379void InstructionCodeGeneratorX86_64::VisitStaticFieldGet(HStaticFieldGet* instruction) {
3380  HandleFieldGet(instruction, instruction->GetFieldInfo());
3381}
3382
3383void LocationsBuilderX86_64::VisitStaticFieldSet(HStaticFieldSet* instruction) {
3384  HandleFieldSet(instruction, instruction->GetFieldInfo());
3385}
3386
3387void InstructionCodeGeneratorX86_64::VisitStaticFieldSet(HStaticFieldSet* instruction) {
3388  HandleFieldSet(instruction, instruction->GetFieldInfo(), instruction->GetValueCanBeNull());
3389}
3390
3391void LocationsBuilderX86_64::VisitNullCheck(HNullCheck* instruction) {
3392  LocationSummary* locations =
3393      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
3394  Location loc = codegen_->GetCompilerOptions().GetImplicitNullChecks()
3395      ? Location::RequiresRegister()
3396      : Location::Any();
3397  locations->SetInAt(0, loc);
3398  if (instruction->HasUses()) {
3399    locations->SetOut(Location::SameAsFirstInput());
3400  }
3401}
3402
3403void InstructionCodeGeneratorX86_64::GenerateImplicitNullCheck(HNullCheck* instruction) {
3404  if (codegen_->CanMoveNullCheckToUser(instruction)) {
3405    return;
3406  }
3407  LocationSummary* locations = instruction->GetLocations();
3408  Location obj = locations->InAt(0);
3409
3410  __ testl(CpuRegister(RAX), Address(obj.AsRegister<CpuRegister>(), 0));
3411  codegen_->RecordPcInfo(instruction, instruction->GetDexPc());
3412}
3413
3414void InstructionCodeGeneratorX86_64::GenerateExplicitNullCheck(HNullCheck* instruction) {
3415  SlowPathCodeX86_64* slow_path = new (GetGraph()->GetArena()) NullCheckSlowPathX86_64(instruction);
3416  codegen_->AddSlowPath(slow_path);
3417
3418  LocationSummary* locations = instruction->GetLocations();
3419  Location obj = locations->InAt(0);
3420
3421  if (obj.IsRegister()) {
3422    __ testl(obj.AsRegister<CpuRegister>(), obj.AsRegister<CpuRegister>());
3423  } else if (obj.IsStackSlot()) {
3424    __ cmpl(Address(CpuRegister(RSP), obj.GetStackIndex()), Immediate(0));
3425  } else {
3426    DCHECK(obj.IsConstant()) << obj;
3427    DCHECK_EQ(obj.GetConstant()->AsIntConstant()->GetValue(), 0);
3428    __ jmp(slow_path->GetEntryLabel());
3429    return;
3430  }
3431  __ j(kEqual, slow_path->GetEntryLabel());
3432}
3433
3434void InstructionCodeGeneratorX86_64::VisitNullCheck(HNullCheck* instruction) {
3435  if (codegen_->GetCompilerOptions().GetImplicitNullChecks()) {
3436    GenerateImplicitNullCheck(instruction);
3437  } else {
3438    GenerateExplicitNullCheck(instruction);
3439  }
3440}
3441
3442void LocationsBuilderX86_64::VisitArrayGet(HArrayGet* instruction) {
3443  LocationSummary* locations =
3444      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
3445  locations->SetInAt(0, Location::RequiresRegister());
3446  locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1)));
3447  if (Primitive::IsFloatingPointType(instruction->GetType())) {
3448    locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
3449  } else {
3450    locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
3451  }
3452}
3453
3454void InstructionCodeGeneratorX86_64::VisitArrayGet(HArrayGet* instruction) {
3455  LocationSummary* locations = instruction->GetLocations();
3456  CpuRegister obj = locations->InAt(0).AsRegister<CpuRegister>();
3457  Location index = locations->InAt(1);
3458
3459  switch (instruction->GetType()) {
3460    case Primitive::kPrimBoolean: {
3461      uint32_t data_offset = mirror::Array::DataOffset(sizeof(uint8_t)).Uint32Value();
3462      CpuRegister out = locations->Out().AsRegister<CpuRegister>();
3463      if (index.IsConstant()) {
3464        __ movzxb(out, Address(obj,
3465            (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_1) + data_offset));
3466      } else {
3467        __ movzxb(out, Address(obj, index.AsRegister<CpuRegister>(), TIMES_1, data_offset));
3468      }
3469      break;
3470    }
3471
3472    case Primitive::kPrimByte: {
3473      uint32_t data_offset = mirror::Array::DataOffset(sizeof(int8_t)).Uint32Value();
3474      CpuRegister out = locations->Out().AsRegister<CpuRegister>();
3475      if (index.IsConstant()) {
3476        __ movsxb(out, Address(obj,
3477            (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_1) + data_offset));
3478      } else {
3479        __ movsxb(out, Address(obj, index.AsRegister<CpuRegister>(), TIMES_1, data_offset));
3480      }
3481      break;
3482    }
3483
3484    case Primitive::kPrimShort: {
3485      uint32_t data_offset = mirror::Array::DataOffset(sizeof(int16_t)).Uint32Value();
3486      CpuRegister out = locations->Out().AsRegister<CpuRegister>();
3487      if (index.IsConstant()) {
3488        __ movsxw(out, Address(obj,
3489            (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_2) + data_offset));
3490      } else {
3491        __ movsxw(out, Address(obj, index.AsRegister<CpuRegister>(), TIMES_2, data_offset));
3492      }
3493      break;
3494    }
3495
3496    case Primitive::kPrimChar: {
3497      uint32_t data_offset = mirror::Array::DataOffset(sizeof(uint16_t)).Uint32Value();
3498      CpuRegister out = locations->Out().AsRegister<CpuRegister>();
3499      if (index.IsConstant()) {
3500        __ movzxw(out, Address(obj,
3501            (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_2) + data_offset));
3502      } else {
3503        __ movzxw(out, Address(obj, index.AsRegister<CpuRegister>(), TIMES_2, data_offset));
3504      }
3505      break;
3506    }
3507
3508    case Primitive::kPrimInt:
3509    case Primitive::kPrimNot: {
3510      DCHECK_EQ(sizeof(mirror::HeapReference<mirror::Object>), sizeof(int32_t));
3511      uint32_t data_offset = mirror::Array::DataOffset(sizeof(int32_t)).Uint32Value();
3512      CpuRegister out = locations->Out().AsRegister<CpuRegister>();
3513      if (index.IsConstant()) {
3514        __ movl(out, Address(obj,
3515            (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_4) + data_offset));
3516      } else {
3517        __ movl(out, Address(obj, index.AsRegister<CpuRegister>(), TIMES_4, data_offset));
3518      }
3519      break;
3520    }
3521
3522    case Primitive::kPrimLong: {
3523      uint32_t data_offset = mirror::Array::DataOffset(sizeof(int64_t)).Uint32Value();
3524      CpuRegister out = locations->Out().AsRegister<CpuRegister>();
3525      if (index.IsConstant()) {
3526        __ movq(out, Address(obj,
3527            (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_8) + data_offset));
3528      } else {
3529        __ movq(out, Address(obj, index.AsRegister<CpuRegister>(), TIMES_8, data_offset));
3530      }
3531      break;
3532    }
3533
3534    case Primitive::kPrimFloat: {
3535      uint32_t data_offset = mirror::Array::DataOffset(sizeof(float)).Uint32Value();
3536      XmmRegister out = locations->Out().AsFpuRegister<XmmRegister>();
3537      if (index.IsConstant()) {
3538        __ movss(out, Address(obj,
3539            (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_4) + data_offset));
3540      } else {
3541        __ movss(out, Address(obj, index.AsRegister<CpuRegister>(), TIMES_4, data_offset));
3542      }
3543      break;
3544    }
3545
3546    case Primitive::kPrimDouble: {
3547      uint32_t data_offset = mirror::Array::DataOffset(sizeof(double)).Uint32Value();
3548      XmmRegister out = locations->Out().AsFpuRegister<XmmRegister>();
3549      if (index.IsConstant()) {
3550        __ movsd(out, Address(obj,
3551            (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_8) + data_offset));
3552      } else {
3553        __ movsd(out, Address(obj, index.AsRegister<CpuRegister>(), TIMES_8, data_offset));
3554      }
3555      break;
3556    }
3557
3558    case Primitive::kPrimVoid:
3559      LOG(FATAL) << "Unreachable type " << instruction->GetType();
3560      UNREACHABLE();
3561  }
3562  codegen_->MaybeRecordImplicitNullCheck(instruction);
3563}
3564
3565void LocationsBuilderX86_64::VisitArraySet(HArraySet* instruction) {
3566  Primitive::Type value_type = instruction->GetComponentType();
3567
3568  bool needs_write_barrier =
3569      CodeGenerator::StoreNeedsWriteBarrier(value_type, instruction->GetValue());
3570  bool needs_runtime_call = instruction->NeedsTypeCheck();
3571
3572  LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(
3573      instruction, needs_runtime_call ? LocationSummary::kCall : LocationSummary::kNoCall);
3574  if (needs_runtime_call) {
3575    InvokeRuntimeCallingConvention calling_convention;
3576    locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0)));
3577    locations->SetInAt(1, Location::RegisterLocation(calling_convention.GetRegisterAt(1)));
3578    locations->SetInAt(2, Location::RegisterLocation(calling_convention.GetRegisterAt(2)));
3579  } else {
3580    locations->SetInAt(0, Location::RequiresRegister());
3581    locations->SetInAt(
3582        1, Location::RegisterOrConstant(instruction->InputAt(1)));
3583    locations->SetInAt(2, Location::RequiresRegister());
3584    if (value_type == Primitive::kPrimLong) {
3585      locations->SetInAt(2, Location::RegisterOrInt32LongConstant(instruction->InputAt(2)));
3586    } else if (value_type == Primitive::kPrimFloat || value_type == Primitive::kPrimDouble) {
3587      locations->SetInAt(2, Location::RequiresFpuRegister());
3588    } else {
3589      locations->SetInAt(2, Location::RegisterOrConstant(instruction->InputAt(2)));
3590    }
3591
3592    if (needs_write_barrier) {
3593      // Temporary registers for the write barrier.
3594      locations->AddTemp(Location::RequiresRegister());
3595      locations->AddTemp(Location::RequiresRegister());
3596    }
3597  }
3598}
3599
3600void InstructionCodeGeneratorX86_64::VisitArraySet(HArraySet* instruction) {
3601  LocationSummary* locations = instruction->GetLocations();
3602  CpuRegister obj = locations->InAt(0).AsRegister<CpuRegister>();
3603  Location index = locations->InAt(1);
3604  Location value = locations->InAt(2);
3605  Primitive::Type value_type = instruction->GetComponentType();
3606  bool needs_runtime_call = locations->WillCall();
3607  bool needs_write_barrier =
3608      CodeGenerator::StoreNeedsWriteBarrier(value_type, instruction->GetValue());
3609
3610  switch (value_type) {
3611    case Primitive::kPrimBoolean:
3612    case Primitive::kPrimByte: {
3613      uint32_t data_offset = mirror::Array::DataOffset(sizeof(uint8_t)).Uint32Value();
3614      if (index.IsConstant()) {
3615        size_t offset = (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_1) + data_offset;
3616        if (value.IsRegister()) {
3617          __ movb(Address(obj, offset), value.AsRegister<CpuRegister>());
3618        } else {
3619          __ movb(Address(obj, offset),
3620                  Immediate(value.GetConstant()->AsIntConstant()->GetValue()));
3621        }
3622      } else {
3623        if (value.IsRegister()) {
3624          __ movb(Address(obj, index.AsRegister<CpuRegister>(), TIMES_1, data_offset),
3625                  value.AsRegister<CpuRegister>());
3626        } else {
3627          __ movb(Address(obj, index.AsRegister<CpuRegister>(), TIMES_1, data_offset),
3628                  Immediate(value.GetConstant()->AsIntConstant()->GetValue()));
3629        }
3630      }
3631      codegen_->MaybeRecordImplicitNullCheck(instruction);
3632      break;
3633    }
3634
3635    case Primitive::kPrimShort:
3636    case Primitive::kPrimChar: {
3637      uint32_t data_offset = mirror::Array::DataOffset(sizeof(uint16_t)).Uint32Value();
3638      if (index.IsConstant()) {
3639        size_t offset = (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_2) + data_offset;
3640        if (value.IsRegister()) {
3641          __ movw(Address(obj, offset), value.AsRegister<CpuRegister>());
3642        } else {
3643          DCHECK(value.IsConstant()) << value;
3644          __ movw(Address(obj, offset),
3645                  Immediate(value.GetConstant()->AsIntConstant()->GetValue()));
3646        }
3647      } else {
3648        DCHECK(index.IsRegister()) << index;
3649        if (value.IsRegister()) {
3650          __ movw(Address(obj, index.AsRegister<CpuRegister>(), TIMES_2, data_offset),
3651                  value.AsRegister<CpuRegister>());
3652        } else {
3653          DCHECK(value.IsConstant()) << value;
3654          __ movw(Address(obj, index.AsRegister<CpuRegister>(), TIMES_2, data_offset),
3655                  Immediate(value.GetConstant()->AsIntConstant()->GetValue()));
3656        }
3657      }
3658      codegen_->MaybeRecordImplicitNullCheck(instruction);
3659      break;
3660    }
3661
3662    case Primitive::kPrimInt:
3663    case Primitive::kPrimNot: {
3664      if (!needs_runtime_call) {
3665        uint32_t data_offset = mirror::Array::DataOffset(sizeof(int32_t)).Uint32Value();
3666        if (index.IsConstant()) {
3667          size_t offset =
3668              (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_4) + data_offset;
3669          if (value.IsRegister()) {
3670            __ movl(Address(obj, offset), value.AsRegister<CpuRegister>());
3671          } else {
3672            DCHECK(value.IsConstant()) << value;
3673            int32_t v = CodeGenerator::GetInt32ValueOf(value.GetConstant());
3674            __ movl(Address(obj, offset), Immediate(v));
3675          }
3676        } else {
3677          DCHECK(index.IsRegister()) << index;
3678          if (value.IsRegister()) {
3679            __ movl(Address(obj, index.AsRegister<CpuRegister>(), TIMES_4, data_offset),
3680                    value.AsRegister<CpuRegister>());
3681          } else {
3682            DCHECK(value.IsConstant()) << value;
3683            int32_t v = CodeGenerator::GetInt32ValueOf(value.GetConstant());
3684            __ movl(Address(obj, index.AsRegister<CpuRegister>(), TIMES_4, data_offset),
3685                    Immediate(v));
3686          }
3687        }
3688        codegen_->MaybeRecordImplicitNullCheck(instruction);
3689        if (needs_write_barrier) {
3690          DCHECK_EQ(value_type, Primitive::kPrimNot);
3691          CpuRegister temp = locations->GetTemp(0).AsRegister<CpuRegister>();
3692          CpuRegister card = locations->GetTemp(1).AsRegister<CpuRegister>();
3693          codegen_->MarkGCCard(
3694              temp, card, obj, value.AsRegister<CpuRegister>(), instruction->GetValueCanBeNull());
3695        }
3696      } else {
3697        DCHECK_EQ(value_type, Primitive::kPrimNot);
3698        __ gs()->call(Address::Absolute(QUICK_ENTRYPOINT_OFFSET(kX86_64WordSize, pAputObject),
3699                                        true));
3700        DCHECK(!codegen_->IsLeafMethod());
3701        codegen_->RecordPcInfo(instruction, instruction->GetDexPc());
3702      }
3703      break;
3704    }
3705
3706    case Primitive::kPrimLong: {
3707      uint32_t data_offset = mirror::Array::DataOffset(sizeof(int64_t)).Uint32Value();
3708      if (index.IsConstant()) {
3709        size_t offset = (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_8) + data_offset;
3710        if (value.IsRegister()) {
3711          __ movq(Address(obj, offset), value.AsRegister<CpuRegister>());
3712        } else {
3713          int64_t v = value.GetConstant()->AsLongConstant()->GetValue();
3714          DCHECK(IsInt<32>(v));
3715          int32_t v_32 = v;
3716          __ movq(Address(obj, offset), Immediate(v_32));
3717        }
3718      } else {
3719        if (value.IsRegister()) {
3720          __ movq(Address(obj, index.AsRegister<CpuRegister>(), TIMES_8, data_offset),
3721                  value.AsRegister<CpuRegister>());
3722        } else {
3723          int64_t v = value.GetConstant()->AsLongConstant()->GetValue();
3724          DCHECK(IsInt<32>(v));
3725          int32_t v_32 = v;
3726          __ movq(Address(obj, index.AsRegister<CpuRegister>(), TIMES_8, data_offset),
3727                  Immediate(v_32));
3728        }
3729      }
3730      codegen_->MaybeRecordImplicitNullCheck(instruction);
3731      break;
3732    }
3733
3734    case Primitive::kPrimFloat: {
3735      uint32_t data_offset = mirror::Array::DataOffset(sizeof(float)).Uint32Value();
3736      if (index.IsConstant()) {
3737        size_t offset = (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_4) + data_offset;
3738        DCHECK(value.IsFpuRegister());
3739        __ movss(Address(obj, offset), value.AsFpuRegister<XmmRegister>());
3740      } else {
3741        DCHECK(value.IsFpuRegister());
3742        __ movss(Address(obj, index.AsRegister<CpuRegister>(), TIMES_4, data_offset),
3743                value.AsFpuRegister<XmmRegister>());
3744      }
3745      codegen_->MaybeRecordImplicitNullCheck(instruction);
3746      break;
3747    }
3748
3749    case Primitive::kPrimDouble: {
3750      uint32_t data_offset = mirror::Array::DataOffset(sizeof(double)).Uint32Value();
3751      if (index.IsConstant()) {
3752        size_t offset = (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_8) + data_offset;
3753        DCHECK(value.IsFpuRegister());
3754        __ movsd(Address(obj, offset), value.AsFpuRegister<XmmRegister>());
3755      } else {
3756        DCHECK(value.IsFpuRegister());
3757        __ movsd(Address(obj, index.AsRegister<CpuRegister>(), TIMES_8, data_offset),
3758                value.AsFpuRegister<XmmRegister>());
3759      }
3760      codegen_->MaybeRecordImplicitNullCheck(instruction);
3761      break;
3762    }
3763
3764    case Primitive::kPrimVoid:
3765      LOG(FATAL) << "Unreachable type " << instruction->GetType();
3766      UNREACHABLE();
3767  }
3768}
3769
3770void LocationsBuilderX86_64::VisitArrayLength(HArrayLength* instruction) {
3771  LocationSummary* locations =
3772      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
3773  locations->SetInAt(0, Location::RequiresRegister());
3774  locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
3775}
3776
3777void InstructionCodeGeneratorX86_64::VisitArrayLength(HArrayLength* instruction) {
3778  LocationSummary* locations = instruction->GetLocations();
3779  uint32_t offset = mirror::Array::LengthOffset().Uint32Value();
3780  CpuRegister obj = locations->InAt(0).AsRegister<CpuRegister>();
3781  CpuRegister out = locations->Out().AsRegister<CpuRegister>();
3782  __ movl(out, Address(obj, offset));
3783  codegen_->MaybeRecordImplicitNullCheck(instruction);
3784}
3785
3786void LocationsBuilderX86_64::VisitBoundsCheck(HBoundsCheck* instruction) {
3787  LocationSummary* locations =
3788      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
3789  locations->SetInAt(0, Location::RegisterOrConstant(instruction->InputAt(0)));
3790  locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1)));
3791  if (instruction->HasUses()) {
3792    locations->SetOut(Location::SameAsFirstInput());
3793  }
3794}
3795
3796void InstructionCodeGeneratorX86_64::VisitBoundsCheck(HBoundsCheck* instruction) {
3797  LocationSummary* locations = instruction->GetLocations();
3798  Location index_loc = locations->InAt(0);
3799  Location length_loc = locations->InAt(1);
3800  SlowPathCodeX86_64* slow_path =
3801    new (GetGraph()->GetArena()) BoundsCheckSlowPathX86_64(instruction, index_loc, length_loc);
3802
3803  if (length_loc.IsConstant()) {
3804    int32_t length = CodeGenerator::GetInt32ValueOf(length_loc.GetConstant());
3805    if (index_loc.IsConstant()) {
3806      // BCE will remove the bounds check if we are guarenteed to pass.
3807      int32_t index = CodeGenerator::GetInt32ValueOf(index_loc.GetConstant());
3808      if (index < 0 || index >= length) {
3809        codegen_->AddSlowPath(slow_path);
3810        __ jmp(slow_path->GetEntryLabel());
3811      } else {
3812        // Some optimization after BCE may have generated this, and we should not
3813        // generate a bounds check if it is a valid range.
3814      }
3815      return;
3816    }
3817
3818    // We have to reverse the jump condition because the length is the constant.
3819    CpuRegister index_reg = index_loc.AsRegister<CpuRegister>();
3820    __ cmpl(index_reg, Immediate(length));
3821    codegen_->AddSlowPath(slow_path);
3822    __ j(kAboveEqual, slow_path->GetEntryLabel());
3823  } else {
3824    CpuRegister length = length_loc.AsRegister<CpuRegister>();
3825    if (index_loc.IsConstant()) {
3826      int32_t value = CodeGenerator::GetInt32ValueOf(index_loc.GetConstant());
3827      __ cmpl(length, Immediate(value));
3828    } else {
3829      __ cmpl(length, index_loc.AsRegister<CpuRegister>());
3830    }
3831    codegen_->AddSlowPath(slow_path);
3832    __ j(kBelowEqual, slow_path->GetEntryLabel());
3833  }
3834}
3835
3836void CodeGeneratorX86_64::MarkGCCard(CpuRegister temp,
3837                                     CpuRegister card,
3838                                     CpuRegister object,
3839                                     CpuRegister value,
3840                                     bool value_can_be_null) {
3841  Label is_null;
3842  if (value_can_be_null) {
3843    __ testl(value, value);
3844    __ j(kEqual, &is_null);
3845  }
3846  __ gs()->movq(card, Address::Absolute(
3847      Thread::CardTableOffset<kX86_64WordSize>().Int32Value(), true));
3848  __ movq(temp, object);
3849  __ shrq(temp, Immediate(gc::accounting::CardTable::kCardShift));
3850  __ movb(Address(temp, card, TIMES_1, 0),  card);
3851  if (value_can_be_null) {
3852    __ Bind(&is_null);
3853  }
3854}
3855
3856void LocationsBuilderX86_64::VisitTemporary(HTemporary* temp) {
3857  temp->SetLocations(nullptr);
3858}
3859
3860void InstructionCodeGeneratorX86_64::VisitTemporary(HTemporary* temp) {
3861  // Nothing to do, this is driven by the code generator.
3862  UNUSED(temp);
3863}
3864
3865void LocationsBuilderX86_64::VisitParallelMove(HParallelMove* instruction) {
3866  UNUSED(instruction);
3867  LOG(FATAL) << "Unimplemented";
3868}
3869
3870void InstructionCodeGeneratorX86_64::VisitParallelMove(HParallelMove* instruction) {
3871  codegen_->GetMoveResolver()->EmitNativeCode(instruction);
3872}
3873
3874void LocationsBuilderX86_64::VisitSuspendCheck(HSuspendCheck* instruction) {
3875  new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCallOnSlowPath);
3876}
3877
3878void InstructionCodeGeneratorX86_64::VisitSuspendCheck(HSuspendCheck* instruction) {
3879  HBasicBlock* block = instruction->GetBlock();
3880  if (block->GetLoopInformation() != nullptr) {
3881    DCHECK(block->GetLoopInformation()->GetSuspendCheck() == instruction);
3882    // The back edge will generate the suspend check.
3883    return;
3884  }
3885  if (block->IsEntryBlock() && instruction->GetNext()->IsGoto()) {
3886    // The goto will generate the suspend check.
3887    return;
3888  }
3889  GenerateSuspendCheck(instruction, nullptr);
3890}
3891
3892void InstructionCodeGeneratorX86_64::GenerateSuspendCheck(HSuspendCheck* instruction,
3893                                                          HBasicBlock* successor) {
3894  SuspendCheckSlowPathX86_64* slow_path =
3895      down_cast<SuspendCheckSlowPathX86_64*>(instruction->GetSlowPath());
3896  if (slow_path == nullptr) {
3897    slow_path = new (GetGraph()->GetArena()) SuspendCheckSlowPathX86_64(instruction, successor);
3898    instruction->SetSlowPath(slow_path);
3899    codegen_->AddSlowPath(slow_path);
3900    if (successor != nullptr) {
3901      DCHECK(successor->IsLoopHeader());
3902      codegen_->ClearSpillSlotsFromLoopPhisInStackMap(instruction);
3903    }
3904  } else {
3905    DCHECK_EQ(slow_path->GetSuccessor(), successor);
3906  }
3907
3908  __ gs()->cmpw(Address::Absolute(
3909      Thread::ThreadFlagsOffset<kX86_64WordSize>().Int32Value(), true), Immediate(0));
3910  if (successor == nullptr) {
3911    __ j(kNotEqual, slow_path->GetEntryLabel());
3912    __ Bind(slow_path->GetReturnLabel());
3913  } else {
3914    __ j(kEqual, codegen_->GetLabelOf(successor));
3915    __ jmp(slow_path->GetEntryLabel());
3916  }
3917}
3918
3919X86_64Assembler* ParallelMoveResolverX86_64::GetAssembler() const {
3920  return codegen_->GetAssembler();
3921}
3922
3923void ParallelMoveResolverX86_64::EmitMove(size_t index) {
3924  MoveOperands* move = moves_.Get(index);
3925  Location source = move->GetSource();
3926  Location destination = move->GetDestination();
3927
3928  if (source.IsRegister()) {
3929    if (destination.IsRegister()) {
3930      __ movq(destination.AsRegister<CpuRegister>(), source.AsRegister<CpuRegister>());
3931    } else if (destination.IsStackSlot()) {
3932      __ movl(Address(CpuRegister(RSP), destination.GetStackIndex()),
3933              source.AsRegister<CpuRegister>());
3934    } else {
3935      DCHECK(destination.IsDoubleStackSlot());
3936      __ movq(Address(CpuRegister(RSP), destination.GetStackIndex()),
3937              source.AsRegister<CpuRegister>());
3938    }
3939  } else if (source.IsStackSlot()) {
3940    if (destination.IsRegister()) {
3941      __ movl(destination.AsRegister<CpuRegister>(),
3942              Address(CpuRegister(RSP), source.GetStackIndex()));
3943    } else if (destination.IsFpuRegister()) {
3944      __ movss(destination.AsFpuRegister<XmmRegister>(),
3945              Address(CpuRegister(RSP), source.GetStackIndex()));
3946    } else {
3947      DCHECK(destination.IsStackSlot());
3948      __ movl(CpuRegister(TMP), Address(CpuRegister(RSP), source.GetStackIndex()));
3949      __ movl(Address(CpuRegister(RSP), destination.GetStackIndex()), CpuRegister(TMP));
3950    }
3951  } else if (source.IsDoubleStackSlot()) {
3952    if (destination.IsRegister()) {
3953      __ movq(destination.AsRegister<CpuRegister>(),
3954              Address(CpuRegister(RSP), source.GetStackIndex()));
3955    } else if (destination.IsFpuRegister()) {
3956      __ movsd(destination.AsFpuRegister<XmmRegister>(),
3957               Address(CpuRegister(RSP), source.GetStackIndex()));
3958    } else {
3959      DCHECK(destination.IsDoubleStackSlot()) << destination;
3960      __ movq(CpuRegister(TMP), Address(CpuRegister(RSP), source.GetStackIndex()));
3961      __ movq(Address(CpuRegister(RSP), destination.GetStackIndex()), CpuRegister(TMP));
3962    }
3963  } else if (source.IsConstant()) {
3964    HConstant* constant = source.GetConstant();
3965    if (constant->IsIntConstant() || constant->IsNullConstant()) {
3966      int32_t value = CodeGenerator::GetInt32ValueOf(constant);
3967      if (destination.IsRegister()) {
3968        if (value == 0) {
3969          __ xorl(destination.AsRegister<CpuRegister>(), destination.AsRegister<CpuRegister>());
3970        } else {
3971          __ movl(destination.AsRegister<CpuRegister>(), Immediate(value));
3972        }
3973      } else {
3974        DCHECK(destination.IsStackSlot()) << destination;
3975        __ movl(Address(CpuRegister(RSP), destination.GetStackIndex()), Immediate(value));
3976      }
3977    } else if (constant->IsLongConstant()) {
3978      int64_t value = constant->AsLongConstant()->GetValue();
3979      if (destination.IsRegister()) {
3980        codegen_->Load64BitValue(destination.AsRegister<CpuRegister>(), value);
3981      } else {
3982        DCHECK(destination.IsDoubleStackSlot()) << destination;
3983        codegen_->Load64BitValue(CpuRegister(TMP), value);
3984        __ movq(Address(CpuRegister(RSP), destination.GetStackIndex()), CpuRegister(TMP));
3985      }
3986    } else if (constant->IsFloatConstant()) {
3987      float fp_value = constant->AsFloatConstant()->GetValue();
3988      int32_t value = bit_cast<int32_t, float>(fp_value);
3989      if (destination.IsFpuRegister()) {
3990        XmmRegister dest = destination.AsFpuRegister<XmmRegister>();
3991        if (value == 0) {
3992          // easy FP 0.0.
3993          __ xorps(dest, dest);
3994        } else {
3995          __ movss(dest, codegen_->LiteralFloatAddress(fp_value));
3996        }
3997      } else {
3998        DCHECK(destination.IsStackSlot()) << destination;
3999        Immediate imm(value);
4000        __ movl(Address(CpuRegister(RSP), destination.GetStackIndex()), imm);
4001      }
4002    } else {
4003      DCHECK(constant->IsDoubleConstant()) << constant->DebugName();
4004      double fp_value =  constant->AsDoubleConstant()->GetValue();
4005      int64_t value = bit_cast<int64_t, double>(fp_value);
4006      if (destination.IsFpuRegister()) {
4007        XmmRegister dest = destination.AsFpuRegister<XmmRegister>();
4008        if (value == 0) {
4009          __ xorpd(dest, dest);
4010        } else {
4011          __ movsd(dest, codegen_->LiteralDoubleAddress(fp_value));
4012        }
4013      } else {
4014        DCHECK(destination.IsDoubleStackSlot()) << destination;
4015        codegen_->Load64BitValue(CpuRegister(TMP), value);
4016        __ movq(Address(CpuRegister(RSP), destination.GetStackIndex()), CpuRegister(TMP));
4017      }
4018    }
4019  } else if (source.IsFpuRegister()) {
4020    if (destination.IsFpuRegister()) {
4021      __ movaps(destination.AsFpuRegister<XmmRegister>(), source.AsFpuRegister<XmmRegister>());
4022    } else if (destination.IsStackSlot()) {
4023      __ movss(Address(CpuRegister(RSP), destination.GetStackIndex()),
4024               source.AsFpuRegister<XmmRegister>());
4025    } else {
4026      DCHECK(destination.IsDoubleStackSlot()) << destination;
4027      __ movsd(Address(CpuRegister(RSP), destination.GetStackIndex()),
4028               source.AsFpuRegister<XmmRegister>());
4029    }
4030  }
4031}
4032
4033void ParallelMoveResolverX86_64::Exchange32(CpuRegister reg, int mem) {
4034  __ movl(CpuRegister(TMP), Address(CpuRegister(RSP), mem));
4035  __ movl(Address(CpuRegister(RSP), mem), reg);
4036  __ movl(reg, CpuRegister(TMP));
4037}
4038
4039void ParallelMoveResolverX86_64::Exchange32(int mem1, int mem2) {
4040  ScratchRegisterScope ensure_scratch(
4041      this, TMP, RAX, codegen_->GetNumberOfCoreRegisters());
4042
4043  int stack_offset = ensure_scratch.IsSpilled() ? kX86_64WordSize : 0;
4044  __ movl(CpuRegister(TMP), Address(CpuRegister(RSP), mem1 + stack_offset));
4045  __ movl(CpuRegister(ensure_scratch.GetRegister()),
4046          Address(CpuRegister(RSP), mem2 + stack_offset));
4047  __ movl(Address(CpuRegister(RSP), mem2 + stack_offset), CpuRegister(TMP));
4048  __ movl(Address(CpuRegister(RSP), mem1 + stack_offset),
4049          CpuRegister(ensure_scratch.GetRegister()));
4050}
4051
4052void ParallelMoveResolverX86_64::Exchange64(CpuRegister reg, int mem) {
4053  __ movq(CpuRegister(TMP), Address(CpuRegister(RSP), mem));
4054  __ movq(Address(CpuRegister(RSP), mem), reg);
4055  __ movq(reg, CpuRegister(TMP));
4056}
4057
4058void ParallelMoveResolverX86_64::Exchange64(int mem1, int mem2) {
4059  ScratchRegisterScope ensure_scratch(
4060      this, TMP, RAX, codegen_->GetNumberOfCoreRegisters());
4061
4062  int stack_offset = ensure_scratch.IsSpilled() ? kX86_64WordSize : 0;
4063  __ movq(CpuRegister(TMP), Address(CpuRegister(RSP), mem1 + stack_offset));
4064  __ movq(CpuRegister(ensure_scratch.GetRegister()),
4065          Address(CpuRegister(RSP), mem2 + stack_offset));
4066  __ movq(Address(CpuRegister(RSP), mem2 + stack_offset), CpuRegister(TMP));
4067  __ movq(Address(CpuRegister(RSP), mem1 + stack_offset),
4068          CpuRegister(ensure_scratch.GetRegister()));
4069}
4070
4071void ParallelMoveResolverX86_64::Exchange32(XmmRegister reg, int mem) {
4072  __ movl(CpuRegister(TMP), Address(CpuRegister(RSP), mem));
4073  __ movss(Address(CpuRegister(RSP), mem), reg);
4074  __ movd(reg, CpuRegister(TMP));
4075}
4076
4077void ParallelMoveResolverX86_64::Exchange64(XmmRegister reg, int mem) {
4078  __ movq(CpuRegister(TMP), Address(CpuRegister(RSP), mem));
4079  __ movsd(Address(CpuRegister(RSP), mem), reg);
4080  __ movd(reg, CpuRegister(TMP));
4081}
4082
4083void ParallelMoveResolverX86_64::EmitSwap(size_t index) {
4084  MoveOperands* move = moves_.Get(index);
4085  Location source = move->GetSource();
4086  Location destination = move->GetDestination();
4087
4088  if (source.IsRegister() && destination.IsRegister()) {
4089    __ xchgq(destination.AsRegister<CpuRegister>(), source.AsRegister<CpuRegister>());
4090  } else if (source.IsRegister() && destination.IsStackSlot()) {
4091    Exchange32(source.AsRegister<CpuRegister>(), destination.GetStackIndex());
4092  } else if (source.IsStackSlot() && destination.IsRegister()) {
4093    Exchange32(destination.AsRegister<CpuRegister>(), source.GetStackIndex());
4094  } else if (source.IsStackSlot() && destination.IsStackSlot()) {
4095    Exchange32(destination.GetStackIndex(), source.GetStackIndex());
4096  } else if (source.IsRegister() && destination.IsDoubleStackSlot()) {
4097    Exchange64(source.AsRegister<CpuRegister>(), destination.GetStackIndex());
4098  } else if (source.IsDoubleStackSlot() && destination.IsRegister()) {
4099    Exchange64(destination.AsRegister<CpuRegister>(), source.GetStackIndex());
4100  } else if (source.IsDoubleStackSlot() && destination.IsDoubleStackSlot()) {
4101    Exchange64(destination.GetStackIndex(), source.GetStackIndex());
4102  } else if (source.IsFpuRegister() && destination.IsFpuRegister()) {
4103    __ movd(CpuRegister(TMP), source.AsFpuRegister<XmmRegister>());
4104    __ movaps(source.AsFpuRegister<XmmRegister>(), destination.AsFpuRegister<XmmRegister>());
4105    __ movd(destination.AsFpuRegister<XmmRegister>(), CpuRegister(TMP));
4106  } else if (source.IsFpuRegister() && destination.IsStackSlot()) {
4107    Exchange32(source.AsFpuRegister<XmmRegister>(), destination.GetStackIndex());
4108  } else if (source.IsStackSlot() && destination.IsFpuRegister()) {
4109    Exchange32(destination.AsFpuRegister<XmmRegister>(), source.GetStackIndex());
4110  } else if (source.IsFpuRegister() && destination.IsDoubleStackSlot()) {
4111    Exchange64(source.AsFpuRegister<XmmRegister>(), destination.GetStackIndex());
4112  } else if (source.IsDoubleStackSlot() && destination.IsFpuRegister()) {
4113    Exchange64(destination.AsFpuRegister<XmmRegister>(), source.GetStackIndex());
4114  } else {
4115    LOG(FATAL) << "Unimplemented swap between " << source << " and " << destination;
4116  }
4117}
4118
4119
4120void ParallelMoveResolverX86_64::SpillScratch(int reg) {
4121  __ pushq(CpuRegister(reg));
4122}
4123
4124
4125void ParallelMoveResolverX86_64::RestoreScratch(int reg) {
4126  __ popq(CpuRegister(reg));
4127}
4128
4129void InstructionCodeGeneratorX86_64::GenerateClassInitializationCheck(
4130    SlowPathCodeX86_64* slow_path, CpuRegister class_reg) {
4131  __ cmpl(Address(class_reg,  mirror::Class::StatusOffset().Int32Value()),
4132          Immediate(mirror::Class::kStatusInitialized));
4133  __ j(kLess, slow_path->GetEntryLabel());
4134  __ Bind(slow_path->GetExitLabel());
4135  // No need for memory fence, thanks to the X86_64 memory model.
4136}
4137
4138void LocationsBuilderX86_64::VisitLoadClass(HLoadClass* cls) {
4139  LocationSummary::CallKind call_kind = cls->CanCallRuntime()
4140      ? LocationSummary::kCallOnSlowPath
4141      : LocationSummary::kNoCall;
4142  LocationSummary* locations =
4143      new (GetGraph()->GetArena()) LocationSummary(cls, call_kind);
4144  locations->SetInAt(0, Location::RequiresRegister());
4145  locations->SetOut(Location::RequiresRegister());
4146}
4147
4148void InstructionCodeGeneratorX86_64::VisitLoadClass(HLoadClass* cls) {
4149  LocationSummary* locations = cls->GetLocations();
4150  CpuRegister out = locations->Out().AsRegister<CpuRegister>();
4151  CpuRegister current_method = locations->InAt(0).AsRegister<CpuRegister>();
4152  if (cls->IsReferrersClass()) {
4153    DCHECK(!cls->CanCallRuntime());
4154    DCHECK(!cls->MustGenerateClinitCheck());
4155    __ movl(out, Address(current_method, ArtMethod::DeclaringClassOffset().Int32Value()));
4156  } else {
4157    DCHECK(cls->CanCallRuntime());
4158    __ movl(out, Address(
4159        current_method, ArtMethod::DexCacheResolvedTypesOffset().Int32Value()));
4160    __ movl(out, Address(out, CodeGenerator::GetCacheOffset(cls->GetTypeIndex())));
4161    SlowPathCodeX86_64* slow_path = new (GetGraph()->GetArena()) LoadClassSlowPathX86_64(
4162        cls, cls, cls->GetDexPc(), cls->MustGenerateClinitCheck());
4163    codegen_->AddSlowPath(slow_path);
4164    __ testl(out, out);
4165    __ j(kEqual, slow_path->GetEntryLabel());
4166    if (cls->MustGenerateClinitCheck()) {
4167      GenerateClassInitializationCheck(slow_path, out);
4168    } else {
4169      __ Bind(slow_path->GetExitLabel());
4170    }
4171  }
4172}
4173
4174void LocationsBuilderX86_64::VisitClinitCheck(HClinitCheck* check) {
4175  LocationSummary* locations =
4176      new (GetGraph()->GetArena()) LocationSummary(check, LocationSummary::kCallOnSlowPath);
4177  locations->SetInAt(0, Location::RequiresRegister());
4178  if (check->HasUses()) {
4179    locations->SetOut(Location::SameAsFirstInput());
4180  }
4181}
4182
4183void InstructionCodeGeneratorX86_64::VisitClinitCheck(HClinitCheck* check) {
4184  // We assume the class to not be null.
4185  SlowPathCodeX86_64* slow_path = new (GetGraph()->GetArena()) LoadClassSlowPathX86_64(
4186      check->GetLoadClass(), check, check->GetDexPc(), true);
4187  codegen_->AddSlowPath(slow_path);
4188  GenerateClassInitializationCheck(slow_path,
4189                                   check->GetLocations()->InAt(0).AsRegister<CpuRegister>());
4190}
4191
4192void LocationsBuilderX86_64::VisitLoadString(HLoadString* load) {
4193  LocationSummary* locations =
4194      new (GetGraph()->GetArena()) LocationSummary(load, LocationSummary::kCallOnSlowPath);
4195  locations->SetInAt(0, Location::RequiresRegister());
4196  locations->SetOut(Location::RequiresRegister());
4197}
4198
4199void InstructionCodeGeneratorX86_64::VisitLoadString(HLoadString* load) {
4200  SlowPathCodeX86_64* slow_path = new (GetGraph()->GetArena()) LoadStringSlowPathX86_64(load);
4201  codegen_->AddSlowPath(slow_path);
4202
4203  LocationSummary* locations = load->GetLocations();
4204  CpuRegister out = locations->Out().AsRegister<CpuRegister>();
4205  CpuRegister current_method = locations->InAt(0).AsRegister<CpuRegister>();
4206  __ movl(out, Address(current_method, ArtMethod::DeclaringClassOffset().Int32Value()));
4207  __ movl(out, Address(out, mirror::Class::DexCacheStringsOffset().Int32Value()));
4208  __ movl(out, Address(out, CodeGenerator::GetCacheOffset(load->GetStringIndex())));
4209  __ testl(out, out);
4210  __ j(kEqual, slow_path->GetEntryLabel());
4211  __ Bind(slow_path->GetExitLabel());
4212}
4213
4214void LocationsBuilderX86_64::VisitLoadException(HLoadException* load) {
4215  LocationSummary* locations =
4216      new (GetGraph()->GetArena()) LocationSummary(load, LocationSummary::kNoCall);
4217  locations->SetOut(Location::RequiresRegister());
4218}
4219
4220void InstructionCodeGeneratorX86_64::VisitLoadException(HLoadException* load) {
4221  Address address = Address::Absolute(
4222      Thread::ExceptionOffset<kX86_64WordSize>().Int32Value(), true);
4223  __ gs()->movl(load->GetLocations()->Out().AsRegister<CpuRegister>(), address);
4224  __ gs()->movl(address, Immediate(0));
4225}
4226
4227void LocationsBuilderX86_64::VisitThrow(HThrow* instruction) {
4228  LocationSummary* locations =
4229      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCall);
4230  InvokeRuntimeCallingConvention calling_convention;
4231  locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0)));
4232}
4233
4234void InstructionCodeGeneratorX86_64::VisitThrow(HThrow* instruction) {
4235  __ gs()->call(
4236        Address::Absolute(QUICK_ENTRYPOINT_OFFSET(kX86_64WordSize, pDeliverException), true));
4237  codegen_->RecordPcInfo(instruction, instruction->GetDexPc());
4238}
4239
4240void LocationsBuilderX86_64::VisitInstanceOf(HInstanceOf* instruction) {
4241  LocationSummary::CallKind call_kind = instruction->IsClassFinal()
4242      ? LocationSummary::kNoCall
4243      : LocationSummary::kCallOnSlowPath;
4244  LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, call_kind);
4245  locations->SetInAt(0, Location::RequiresRegister());
4246  locations->SetInAt(1, Location::Any());
4247  locations->SetOut(Location::RequiresRegister());
4248}
4249
4250void InstructionCodeGeneratorX86_64::VisitInstanceOf(HInstanceOf* instruction) {
4251  LocationSummary* locations = instruction->GetLocations();
4252  CpuRegister obj = locations->InAt(0).AsRegister<CpuRegister>();
4253  Location cls = locations->InAt(1);
4254  CpuRegister out = locations->Out().AsRegister<CpuRegister>();
4255  uint32_t class_offset = mirror::Object::ClassOffset().Int32Value();
4256  Label done, zero;
4257  SlowPathCodeX86_64* slow_path = nullptr;
4258
4259  // Return 0 if `obj` is null.
4260  // Avoid null check if we know obj is not null.
4261  if (instruction->MustDoNullCheck()) {
4262    __ testl(obj, obj);
4263    __ j(kEqual, &zero);
4264  }
4265  // Compare the class of `obj` with `cls`.
4266  __ movl(out, Address(obj, class_offset));
4267  if (cls.IsRegister()) {
4268    __ cmpl(out, cls.AsRegister<CpuRegister>());
4269  } else {
4270    DCHECK(cls.IsStackSlot()) << cls;
4271    __ cmpl(out, Address(CpuRegister(RSP), cls.GetStackIndex()));
4272  }
4273  if (instruction->IsClassFinal()) {
4274    // Classes must be equal for the instanceof to succeed.
4275    __ j(kNotEqual, &zero);
4276    __ movl(out, Immediate(1));
4277    __ jmp(&done);
4278  } else {
4279    // If the classes are not equal, we go into a slow path.
4280    DCHECK(locations->OnlyCallsOnSlowPath());
4281    slow_path = new (GetGraph()->GetArena()) TypeCheckSlowPathX86_64(
4282        instruction, locations->InAt(1), locations->Out(), instruction->GetDexPc());
4283    codegen_->AddSlowPath(slow_path);
4284    __ j(kNotEqual, slow_path->GetEntryLabel());
4285    __ movl(out, Immediate(1));
4286    __ jmp(&done);
4287  }
4288
4289  if (instruction->MustDoNullCheck() || instruction->IsClassFinal()) {
4290    __ Bind(&zero);
4291    __ movl(out, Immediate(0));
4292  }
4293
4294  if (slow_path != nullptr) {
4295    __ Bind(slow_path->GetExitLabel());
4296  }
4297  __ Bind(&done);
4298}
4299
4300void LocationsBuilderX86_64::VisitCheckCast(HCheckCast* instruction) {
4301  LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(
4302      instruction, LocationSummary::kCallOnSlowPath);
4303  locations->SetInAt(0, Location::RequiresRegister());
4304  locations->SetInAt(1, Location::Any());
4305  locations->AddTemp(Location::RequiresRegister());
4306}
4307
4308void InstructionCodeGeneratorX86_64::VisitCheckCast(HCheckCast* instruction) {
4309  LocationSummary* locations = instruction->GetLocations();
4310  CpuRegister obj = locations->InAt(0).AsRegister<CpuRegister>();
4311  Location cls = locations->InAt(1);
4312  CpuRegister temp = locations->GetTemp(0).AsRegister<CpuRegister>();
4313  uint32_t class_offset = mirror::Object::ClassOffset().Int32Value();
4314  SlowPathCodeX86_64* slow_path = new (GetGraph()->GetArena()) TypeCheckSlowPathX86_64(
4315      instruction, locations->InAt(1), locations->GetTemp(0), instruction->GetDexPc());
4316  codegen_->AddSlowPath(slow_path);
4317
4318  // Avoid null check if we know obj is not null.
4319  if (instruction->MustDoNullCheck()) {
4320    __ testl(obj, obj);
4321    __ j(kEqual, slow_path->GetExitLabel());
4322  }
4323  // Compare the class of `obj` with `cls`.
4324  __ movl(temp, Address(obj, class_offset));
4325  if (cls.IsRegister()) {
4326    __ cmpl(temp, cls.AsRegister<CpuRegister>());
4327  } else {
4328    DCHECK(cls.IsStackSlot()) << cls;
4329    __ cmpl(temp, Address(CpuRegister(RSP), cls.GetStackIndex()));
4330  }
4331  // Classes must be equal for the checkcast to succeed.
4332  __ j(kNotEqual, slow_path->GetEntryLabel());
4333  __ Bind(slow_path->GetExitLabel());
4334}
4335
4336void LocationsBuilderX86_64::VisitMonitorOperation(HMonitorOperation* instruction) {
4337  LocationSummary* locations =
4338      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCall);
4339  InvokeRuntimeCallingConvention calling_convention;
4340  locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0)));
4341}
4342
4343void InstructionCodeGeneratorX86_64::VisitMonitorOperation(HMonitorOperation* instruction) {
4344  __ gs()->call(Address::Absolute(instruction->IsEnter()
4345        ? QUICK_ENTRYPOINT_OFFSET(kX86_64WordSize, pLockObject)
4346        : QUICK_ENTRYPOINT_OFFSET(kX86_64WordSize, pUnlockObject),
4347      true));
4348  codegen_->RecordPcInfo(instruction, instruction->GetDexPc());
4349}
4350
4351void LocationsBuilderX86_64::VisitAnd(HAnd* instruction) { HandleBitwiseOperation(instruction); }
4352void LocationsBuilderX86_64::VisitOr(HOr* instruction) { HandleBitwiseOperation(instruction); }
4353void LocationsBuilderX86_64::VisitXor(HXor* instruction) { HandleBitwiseOperation(instruction); }
4354
4355void LocationsBuilderX86_64::HandleBitwiseOperation(HBinaryOperation* instruction) {
4356  LocationSummary* locations =
4357      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
4358  DCHECK(instruction->GetResultType() == Primitive::kPrimInt
4359         || instruction->GetResultType() == Primitive::kPrimLong);
4360  locations->SetInAt(0, Location::RequiresRegister());
4361  locations->SetInAt(1, Location::Any());
4362  locations->SetOut(Location::SameAsFirstInput());
4363}
4364
4365void InstructionCodeGeneratorX86_64::VisitAnd(HAnd* instruction) {
4366  HandleBitwiseOperation(instruction);
4367}
4368
4369void InstructionCodeGeneratorX86_64::VisitOr(HOr* instruction) {
4370  HandleBitwiseOperation(instruction);
4371}
4372
4373void InstructionCodeGeneratorX86_64::VisitXor(HXor* instruction) {
4374  HandleBitwiseOperation(instruction);
4375}
4376
4377void InstructionCodeGeneratorX86_64::HandleBitwiseOperation(HBinaryOperation* instruction) {
4378  LocationSummary* locations = instruction->GetLocations();
4379  Location first = locations->InAt(0);
4380  Location second = locations->InAt(1);
4381  DCHECK(first.Equals(locations->Out()));
4382
4383  if (instruction->GetResultType() == Primitive::kPrimInt) {
4384    if (second.IsRegister()) {
4385      if (instruction->IsAnd()) {
4386        __ andl(first.AsRegister<CpuRegister>(), second.AsRegister<CpuRegister>());
4387      } else if (instruction->IsOr()) {
4388        __ orl(first.AsRegister<CpuRegister>(), second.AsRegister<CpuRegister>());
4389      } else {
4390        DCHECK(instruction->IsXor());
4391        __ xorl(first.AsRegister<CpuRegister>(), second.AsRegister<CpuRegister>());
4392      }
4393    } else if (second.IsConstant()) {
4394      Immediate imm(second.GetConstant()->AsIntConstant()->GetValue());
4395      if (instruction->IsAnd()) {
4396        __ andl(first.AsRegister<CpuRegister>(), imm);
4397      } else if (instruction->IsOr()) {
4398        __ orl(first.AsRegister<CpuRegister>(), imm);
4399      } else {
4400        DCHECK(instruction->IsXor());
4401        __ xorl(first.AsRegister<CpuRegister>(), imm);
4402      }
4403    } else {
4404      Address address(CpuRegister(RSP), second.GetStackIndex());
4405      if (instruction->IsAnd()) {
4406        __ andl(first.AsRegister<CpuRegister>(), address);
4407      } else if (instruction->IsOr()) {
4408        __ orl(first.AsRegister<CpuRegister>(), address);
4409      } else {
4410        DCHECK(instruction->IsXor());
4411        __ xorl(first.AsRegister<CpuRegister>(), address);
4412      }
4413    }
4414  } else {
4415    DCHECK_EQ(instruction->GetResultType(), Primitive::kPrimLong);
4416    CpuRegister first_reg = first.AsRegister<CpuRegister>();
4417    bool second_is_constant = false;
4418    int64_t value = 0;
4419    if (second.IsConstant()) {
4420      second_is_constant = true;
4421      value = second.GetConstant()->AsLongConstant()->GetValue();
4422    }
4423    bool is_int32_value = IsInt<32>(value);
4424
4425    if (instruction->IsAnd()) {
4426      if (second_is_constant) {
4427        if (is_int32_value) {
4428          __ andq(first_reg, Immediate(static_cast<int32_t>(value)));
4429        } else {
4430          __ andq(first_reg, codegen_->LiteralInt64Address(value));
4431        }
4432      } else if (second.IsDoubleStackSlot()) {
4433        __ andq(first_reg, Address(CpuRegister(RSP), second.GetStackIndex()));
4434      } else {
4435        __ andq(first_reg, second.AsRegister<CpuRegister>());
4436      }
4437    } else if (instruction->IsOr()) {
4438      if (second_is_constant) {
4439        if (is_int32_value) {
4440          __ orq(first_reg, Immediate(static_cast<int32_t>(value)));
4441        } else {
4442          __ orq(first_reg, codegen_->LiteralInt64Address(value));
4443        }
4444      } else if (second.IsDoubleStackSlot()) {
4445        __ orq(first_reg, Address(CpuRegister(RSP), second.GetStackIndex()));
4446      } else {
4447        __ orq(first_reg, second.AsRegister<CpuRegister>());
4448      }
4449    } else {
4450      DCHECK(instruction->IsXor());
4451      if (second_is_constant) {
4452        if (is_int32_value) {
4453          __ xorq(first_reg, Immediate(static_cast<int32_t>(value)));
4454        } else {
4455          __ xorq(first_reg, codegen_->LiteralInt64Address(value));
4456        }
4457      } else if (second.IsDoubleStackSlot()) {
4458        __ xorq(first_reg, Address(CpuRegister(RSP), second.GetStackIndex()));
4459      } else {
4460        __ xorq(first_reg, second.AsRegister<CpuRegister>());
4461      }
4462    }
4463  }
4464}
4465
4466void LocationsBuilderX86_64::VisitBoundType(HBoundType* instruction) {
4467  // Nothing to do, this should be removed during prepare for register allocator.
4468  UNUSED(instruction);
4469  LOG(FATAL) << "Unreachable";
4470}
4471
4472void InstructionCodeGeneratorX86_64::VisitBoundType(HBoundType* instruction) {
4473  // Nothing to do, this should be removed during prepare for register allocator.
4474  UNUSED(instruction);
4475  LOG(FATAL) << "Unreachable";
4476}
4477
4478void CodeGeneratorX86_64::Load64BitValue(CpuRegister dest, int64_t value) {
4479  if (value == 0) {
4480    __ xorl(dest, dest);
4481  } else if (value > 0 && IsInt<32>(value)) {
4482    // We can use a 32 bit move, as it will zero-extend and is one byte shorter.
4483    __ movl(dest, Immediate(static_cast<int32_t>(value)));
4484  } else {
4485    __ movq(dest, Immediate(value));
4486  }
4487}
4488
4489void CodeGeneratorX86_64::Finalize(CodeAllocator* allocator) {
4490  // Generate the constant area if needed.
4491  X86_64Assembler* assembler = GetAssembler();
4492  if (!assembler->IsConstantAreaEmpty()) {
4493    // Align to 4 byte boundary to reduce cache misses, as the data is 4 and 8
4494    // byte values.  If used for vectors at a later time, this will need to be
4495    // updated to 16 bytes with the appropriate offset.
4496    assembler->Align(4, 0);
4497    constant_area_start_ = assembler->CodeSize();
4498    assembler->AddConstantArea();
4499  }
4500
4501  // And finish up.
4502  CodeGenerator::Finalize(allocator);
4503}
4504
4505/**
4506 * Class to handle late fixup of offsets into constant area.
4507 */
4508class RIPFixup : public AssemblerFixup, public ArenaObject<kArenaAllocMisc> {
4509  public:
4510    RIPFixup(const CodeGeneratorX86_64& codegen, int offset)
4511      : codegen_(codegen), offset_into_constant_area_(offset) {}
4512
4513  private:
4514    void Process(const MemoryRegion& region, int pos) OVERRIDE {
4515      // Patch the correct offset for the instruction.  We use the address of the
4516      // 'next' instruction, which is 'pos' (patch the 4 bytes before).
4517      int constant_offset = codegen_.ConstantAreaStart() + offset_into_constant_area_;
4518      int relative_position = constant_offset - pos;
4519
4520      // Patch in the right value.
4521      region.StoreUnaligned<int32_t>(pos - 4, relative_position);
4522    }
4523
4524    const CodeGeneratorX86_64& codegen_;
4525
4526    // Location in constant area that the fixup refers to.
4527    int offset_into_constant_area_;
4528};
4529
4530Address CodeGeneratorX86_64::LiteralDoubleAddress(double v) {
4531  AssemblerFixup* fixup = new (GetGraph()->GetArena()) RIPFixup(*this, __ AddDouble(v));
4532  return Address::RIP(fixup);
4533}
4534
4535Address CodeGeneratorX86_64::LiteralFloatAddress(float v) {
4536  AssemblerFixup* fixup = new (GetGraph()->GetArena()) RIPFixup(*this, __ AddFloat(v));
4537  return Address::RIP(fixup);
4538}
4539
4540Address CodeGeneratorX86_64::LiteralInt32Address(int32_t v) {
4541  AssemblerFixup* fixup = new (GetGraph()->GetArena()) RIPFixup(*this, __ AddInt32(v));
4542  return Address::RIP(fixup);
4543}
4544
4545Address CodeGeneratorX86_64::LiteralInt64Address(int64_t v) {
4546  AssemblerFixup* fixup = new (GetGraph()->GetArena()) RIPFixup(*this, __ AddInt64(v));
4547  return Address::RIP(fixup);
4548}
4549
4550}  // namespace x86_64
4551}  // namespace art
4552