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