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