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