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