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