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