1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "code_generator_x86.h"
18
19#include "art_method.h"
20#include "code_generator_utils.h"
21#include "compiled_method.h"
22#include "entrypoints/quick/quick_entrypoints.h"
23#include "entrypoints/quick/quick_entrypoints_enum.h"
24#include "gc/accounting/card_table.h"
25#include "intrinsics.h"
26#include "intrinsics_x86.h"
27#include "mirror/array-inl.h"
28#include "mirror/class-inl.h"
29#include "thread.h"
30#include "utils/assembler.h"
31#include "utils/stack_checks.h"
32#include "utils/x86/assembler_x86.h"
33#include "utils/x86/managed_register_x86.h"
34
35namespace art {
36
37template<class MirrorType>
38class GcRoot;
39
40namespace x86 {
41
42static constexpr int kCurrentMethodStackOffset = 0;
43static constexpr Register kMethodRegisterArgument = EAX;
44static constexpr Register kCoreCalleeSaves[] = { EBP, ESI, EDI };
45
46static constexpr int kC2ConditionMask = 0x400;
47
48static constexpr int kFakeReturnRegister = Register(8);
49
50#define __ down_cast<X86Assembler*>(codegen->GetAssembler())->
51#define QUICK_ENTRY_POINT(x) QUICK_ENTRYPOINT_OFFSET(kX86WordSize, x).Int32Value()
52
53class NullCheckSlowPathX86 : public SlowPathCode {
54 public:
55  explicit NullCheckSlowPathX86(HNullCheck* instruction) : SlowPathCode(instruction) {}
56
57  void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
58    CodeGeneratorX86* x86_codegen = down_cast<CodeGeneratorX86*>(codegen);
59    __ Bind(GetEntryLabel());
60    if (instruction_->CanThrowIntoCatchBlock()) {
61      // Live registers will be restored in the catch block if caught.
62      SaveLiveRegisters(codegen, instruction_->GetLocations());
63    }
64    x86_codegen->InvokeRuntime(QUICK_ENTRY_POINT(pThrowNullPointer),
65                               instruction_,
66                               instruction_->GetDexPc(),
67                               this);
68    CheckEntrypointTypes<kQuickThrowNullPointer, void, void>();
69  }
70
71  bool IsFatal() const OVERRIDE { return true; }
72
73  const char* GetDescription() const OVERRIDE { return "NullCheckSlowPathX86"; }
74
75 private:
76  DISALLOW_COPY_AND_ASSIGN(NullCheckSlowPathX86);
77};
78
79class DivZeroCheckSlowPathX86 : public SlowPathCode {
80 public:
81  explicit DivZeroCheckSlowPathX86(HDivZeroCheck* instruction) : SlowPathCode(instruction) {}
82
83  void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
84    CodeGeneratorX86* x86_codegen = down_cast<CodeGeneratorX86*>(codegen);
85    __ Bind(GetEntryLabel());
86    if (instruction_->CanThrowIntoCatchBlock()) {
87      // Live registers will be restored in the catch block if caught.
88      SaveLiveRegisters(codegen, instruction_->GetLocations());
89    }
90    x86_codegen->InvokeRuntime(QUICK_ENTRY_POINT(pThrowDivZero),
91                               instruction_,
92                               instruction_->GetDexPc(),
93                               this);
94    CheckEntrypointTypes<kQuickThrowDivZero, void, void>();
95  }
96
97  bool IsFatal() const OVERRIDE { return true; }
98
99  const char* GetDescription() const OVERRIDE { return "DivZeroCheckSlowPathX86"; }
100
101 private:
102  DISALLOW_COPY_AND_ASSIGN(DivZeroCheckSlowPathX86);
103};
104
105class DivRemMinusOneSlowPathX86 : public SlowPathCode {
106 public:
107  DivRemMinusOneSlowPathX86(HInstruction* instruction, Register reg, bool is_div)
108      : SlowPathCode(instruction), reg_(reg), is_div_(is_div) {}
109
110  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  const char* GetDescription() const OVERRIDE { return "DivRemMinusOneSlowPathX86"; }
121
122 private:
123  Register reg_;
124  bool is_div_;
125  DISALLOW_COPY_AND_ASSIGN(DivRemMinusOneSlowPathX86);
126};
127
128class BoundsCheckSlowPathX86 : public SlowPathCode {
129 public:
130  explicit BoundsCheckSlowPathX86(HBoundsCheck* instruction) : SlowPathCode(instruction) {}
131
132  void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
133    LocationSummary* locations = instruction_->GetLocations();
134    CodeGeneratorX86* x86_codegen = down_cast<CodeGeneratorX86*>(codegen);
135    __ Bind(GetEntryLabel());
136    // We're moving two locations to locations that could overlap, so we need a parallel
137    // move resolver.
138    if (instruction_->CanThrowIntoCatchBlock()) {
139      // Live registers will be restored in the catch block if caught.
140      SaveLiveRegisters(codegen, instruction_->GetLocations());
141    }
142    InvokeRuntimeCallingConvention calling_convention;
143    x86_codegen->EmitParallelMoves(
144        locations->InAt(0),
145        Location::RegisterLocation(calling_convention.GetRegisterAt(0)),
146        Primitive::kPrimInt,
147        locations->InAt(1),
148        Location::RegisterLocation(calling_convention.GetRegisterAt(1)),
149        Primitive::kPrimInt);
150    x86_codegen->InvokeRuntime(QUICK_ENTRY_POINT(pThrowArrayBounds),
151                               instruction_,
152                               instruction_->GetDexPc(),
153                               this);
154    CheckEntrypointTypes<kQuickThrowArrayBounds, void, int32_t, int32_t>();
155  }
156
157  bool IsFatal() const OVERRIDE { return true; }
158
159  const char* GetDescription() const OVERRIDE { return "BoundsCheckSlowPathX86"; }
160
161 private:
162  DISALLOW_COPY_AND_ASSIGN(BoundsCheckSlowPathX86);
163};
164
165class SuspendCheckSlowPathX86 : public SlowPathCode {
166 public:
167  SuspendCheckSlowPathX86(HSuspendCheck* instruction, HBasicBlock* successor)
168      : SlowPathCode(instruction), successor_(successor) {}
169
170  void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
171    CodeGeneratorX86* x86_codegen = down_cast<CodeGeneratorX86*>(codegen);
172    __ Bind(GetEntryLabel());
173    SaveLiveRegisters(codegen, instruction_->GetLocations());
174    x86_codegen->InvokeRuntime(QUICK_ENTRY_POINT(pTestSuspend),
175                               instruction_,
176                               instruction_->GetDexPc(),
177                               this);
178    CheckEntrypointTypes<kQuickTestSuspend, void, void>();
179    RestoreLiveRegisters(codegen, instruction_->GetLocations());
180    if (successor_ == nullptr) {
181      __ jmp(GetReturnLabel());
182    } else {
183      __ jmp(x86_codegen->GetLabelOf(successor_));
184    }
185  }
186
187  Label* GetReturnLabel() {
188    DCHECK(successor_ == nullptr);
189    return &return_label_;
190  }
191
192  HBasicBlock* GetSuccessor() const {
193    return successor_;
194  }
195
196  const char* GetDescription() const OVERRIDE { return "SuspendCheckSlowPathX86"; }
197
198 private:
199  HBasicBlock* const successor_;
200  Label return_label_;
201
202  DISALLOW_COPY_AND_ASSIGN(SuspendCheckSlowPathX86);
203};
204
205class LoadStringSlowPathX86 : public SlowPathCode {
206 public:
207  explicit LoadStringSlowPathX86(HLoadString* instruction): SlowPathCode(instruction) {}
208
209  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    SaveLiveRegisters(codegen, locations);
216
217    InvokeRuntimeCallingConvention calling_convention;
218    const uint32_t string_index = instruction_->AsLoadString()->GetStringIndex();
219    __ movl(calling_convention.GetRegisterAt(0), Immediate(string_index));
220    x86_codegen->InvokeRuntime(QUICK_ENTRY_POINT(pResolveString),
221                               instruction_,
222                               instruction_->GetDexPc(),
223                               this);
224    CheckEntrypointTypes<kQuickResolveString, void*, uint32_t>();
225    x86_codegen->Move32(locations->Out(), Location::RegisterLocation(EAX));
226    RestoreLiveRegisters(codegen, locations);
227
228    __ jmp(GetExitLabel());
229  }
230
231  const char* GetDescription() const OVERRIDE { return "LoadStringSlowPathX86"; }
232
233 private:
234  DISALLOW_COPY_AND_ASSIGN(LoadStringSlowPathX86);
235};
236
237class LoadClassSlowPathX86 : public SlowPathCode {
238 public:
239  LoadClassSlowPathX86(HLoadClass* cls,
240                       HInstruction* at,
241                       uint32_t dex_pc,
242                       bool do_clinit)
243      : SlowPathCode(at), cls_(cls), at_(at), dex_pc_(dex_pc), do_clinit_(do_clinit) {
244    DCHECK(at->IsLoadClass() || at->IsClinitCheck());
245  }
246
247  void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
248    LocationSummary* locations = at_->GetLocations();
249    CodeGeneratorX86* x86_codegen = down_cast<CodeGeneratorX86*>(codegen);
250    __ Bind(GetEntryLabel());
251    SaveLiveRegisters(codegen, locations);
252
253    InvokeRuntimeCallingConvention calling_convention;
254    __ movl(calling_convention.GetRegisterAt(0), Immediate(cls_->GetTypeIndex()));
255    x86_codegen->InvokeRuntime(do_clinit_ ? QUICK_ENTRY_POINT(pInitializeStaticStorage)
256                                          : QUICK_ENTRY_POINT(pInitializeType),
257                               at_, dex_pc_, this);
258    if (do_clinit_) {
259      CheckEntrypointTypes<kQuickInitializeStaticStorage, void*, uint32_t>();
260    } else {
261      CheckEntrypointTypes<kQuickInitializeType, void*, uint32_t>();
262    }
263
264    // Move the class to the desired location.
265    Location out = locations->Out();
266    if (out.IsValid()) {
267      DCHECK(out.IsRegister() && !locations->GetLiveRegisters()->ContainsCoreRegister(out.reg()));
268      x86_codegen->Move32(out, Location::RegisterLocation(EAX));
269    }
270
271    RestoreLiveRegisters(codegen, locations);
272    __ jmp(GetExitLabel());
273  }
274
275  const char* GetDescription() const OVERRIDE { return "LoadClassSlowPathX86"; }
276
277 private:
278  // The class this slow path will load.
279  HLoadClass* const cls_;
280
281  // The instruction where this slow path is happening.
282  // (Might be the load class or an initialization check).
283  HInstruction* const at_;
284
285  // The dex PC of `at_`.
286  const uint32_t dex_pc_;
287
288  // Whether to initialize the class.
289  const bool do_clinit_;
290
291  DISALLOW_COPY_AND_ASSIGN(LoadClassSlowPathX86);
292};
293
294class TypeCheckSlowPathX86 : public SlowPathCode {
295 public:
296  TypeCheckSlowPathX86(HInstruction* instruction, bool is_fatal)
297      : SlowPathCode(instruction), is_fatal_(is_fatal) {}
298
299  void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
300    LocationSummary* locations = instruction_->GetLocations();
301    Location object_class = instruction_->IsCheckCast() ? locations->GetTemp(0)
302                                                        : locations->Out();
303    DCHECK(instruction_->IsCheckCast()
304           || !locations->GetLiveRegisters()->ContainsCoreRegister(locations->Out().reg()));
305
306    CodeGeneratorX86* x86_codegen = down_cast<CodeGeneratorX86*>(codegen);
307    __ Bind(GetEntryLabel());
308
309    if (!is_fatal_) {
310      SaveLiveRegisters(codegen, locations);
311    }
312
313    // We're moving two locations to locations that could overlap, so we need a parallel
314    // move resolver.
315    InvokeRuntimeCallingConvention calling_convention;
316    x86_codegen->EmitParallelMoves(
317        locations->InAt(1),
318        Location::RegisterLocation(calling_convention.GetRegisterAt(0)),
319        Primitive::kPrimNot,
320        object_class,
321        Location::RegisterLocation(calling_convention.GetRegisterAt(1)),
322        Primitive::kPrimNot);
323
324    if (instruction_->IsInstanceOf()) {
325      x86_codegen->InvokeRuntime(QUICK_ENTRY_POINT(pInstanceofNonTrivial),
326                                 instruction_,
327                                 instruction_->GetDexPc(),
328                                 this);
329      CheckEntrypointTypes<
330          kQuickInstanceofNonTrivial, uint32_t, const mirror::Class*, const mirror::Class*>();
331    } else {
332      DCHECK(instruction_->IsCheckCast());
333      x86_codegen->InvokeRuntime(QUICK_ENTRY_POINT(pCheckCast),
334                                 instruction_,
335                                 instruction_->GetDexPc(),
336                                 this);
337      CheckEntrypointTypes<kQuickCheckCast, void, const mirror::Class*, const mirror::Class*>();
338    }
339
340    if (!is_fatal_) {
341      if (instruction_->IsInstanceOf()) {
342        x86_codegen->Move32(locations->Out(), Location::RegisterLocation(EAX));
343      }
344      RestoreLiveRegisters(codegen, locations);
345
346      __ jmp(GetExitLabel());
347    }
348  }
349
350  const char* GetDescription() const OVERRIDE { return "TypeCheckSlowPathX86"; }
351  bool IsFatal() const OVERRIDE { return is_fatal_; }
352
353 private:
354  const bool is_fatal_;
355
356  DISALLOW_COPY_AND_ASSIGN(TypeCheckSlowPathX86);
357};
358
359class DeoptimizationSlowPathX86 : public SlowPathCode {
360 public:
361  explicit DeoptimizationSlowPathX86(HDeoptimize* instruction)
362    : SlowPathCode(instruction) {}
363
364  void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
365    CodeGeneratorX86* x86_codegen = down_cast<CodeGeneratorX86*>(codegen);
366    __ Bind(GetEntryLabel());
367    SaveLiveRegisters(codegen, instruction_->GetLocations());
368    x86_codegen->InvokeRuntime(QUICK_ENTRY_POINT(pDeoptimize),
369                               instruction_,
370                               instruction_->GetDexPc(),
371                               this);
372    CheckEntrypointTypes<kQuickDeoptimize, void, void>();
373  }
374
375  const char* GetDescription() const OVERRIDE { return "DeoptimizationSlowPathX86"; }
376
377 private:
378  DISALLOW_COPY_AND_ASSIGN(DeoptimizationSlowPathX86);
379};
380
381class ArraySetSlowPathX86 : public SlowPathCode {
382 public:
383  explicit ArraySetSlowPathX86(HInstruction* instruction) : SlowPathCode(instruction) {}
384
385  void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
386    LocationSummary* locations = instruction_->GetLocations();
387    __ Bind(GetEntryLabel());
388    SaveLiveRegisters(codegen, locations);
389
390    InvokeRuntimeCallingConvention calling_convention;
391    HParallelMove parallel_move(codegen->GetGraph()->GetArena());
392    parallel_move.AddMove(
393        locations->InAt(0),
394        Location::RegisterLocation(calling_convention.GetRegisterAt(0)),
395        Primitive::kPrimNot,
396        nullptr);
397    parallel_move.AddMove(
398        locations->InAt(1),
399        Location::RegisterLocation(calling_convention.GetRegisterAt(1)),
400        Primitive::kPrimInt,
401        nullptr);
402    parallel_move.AddMove(
403        locations->InAt(2),
404        Location::RegisterLocation(calling_convention.GetRegisterAt(2)),
405        Primitive::kPrimNot,
406        nullptr);
407    codegen->GetMoveResolver()->EmitNativeCode(&parallel_move);
408
409    CodeGeneratorX86* x86_codegen = down_cast<CodeGeneratorX86*>(codegen);
410    x86_codegen->InvokeRuntime(QUICK_ENTRY_POINT(pAputObject),
411                               instruction_,
412                               instruction_->GetDexPc(),
413                               this);
414    CheckEntrypointTypes<kQuickAputObject, void, mirror::Array*, int32_t, mirror::Object*>();
415    RestoreLiveRegisters(codegen, locations);
416    __ jmp(GetExitLabel());
417  }
418
419  const char* GetDescription() const OVERRIDE { return "ArraySetSlowPathX86"; }
420
421 private:
422  DISALLOW_COPY_AND_ASSIGN(ArraySetSlowPathX86);
423};
424
425// Slow path marking an object during a read barrier.
426class ReadBarrierMarkSlowPathX86 : public SlowPathCode {
427 public:
428  ReadBarrierMarkSlowPathX86(HInstruction* instruction, Location out, Location obj)
429      : SlowPathCode(instruction), out_(out), obj_(obj) {
430    DCHECK(kEmitCompilerReadBarrier);
431  }
432
433  const char* GetDescription() const OVERRIDE { return "ReadBarrierMarkSlowPathX86"; }
434
435  void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
436    LocationSummary* locations = instruction_->GetLocations();
437    Register reg_out = out_.AsRegister<Register>();
438    DCHECK(locations->CanCall());
439    DCHECK(!locations->GetLiveRegisters()->ContainsCoreRegister(reg_out));
440    DCHECK(instruction_->IsInstanceFieldGet() ||
441           instruction_->IsStaticFieldGet() ||
442           instruction_->IsArrayGet() ||
443           instruction_->IsLoadClass() ||
444           instruction_->IsLoadString() ||
445           instruction_->IsInstanceOf() ||
446           instruction_->IsCheckCast())
447        << "Unexpected instruction in read barrier marking slow path: "
448        << instruction_->DebugName();
449
450    __ Bind(GetEntryLabel());
451    SaveLiveRegisters(codegen, locations);
452
453    InvokeRuntimeCallingConvention calling_convention;
454    CodeGeneratorX86* x86_codegen = down_cast<CodeGeneratorX86*>(codegen);
455    x86_codegen->Move32(Location::RegisterLocation(calling_convention.GetRegisterAt(0)), obj_);
456    x86_codegen->InvokeRuntime(QUICK_ENTRY_POINT(pReadBarrierMark),
457                               instruction_,
458                               instruction_->GetDexPc(),
459                               this);
460    CheckEntrypointTypes<kQuickReadBarrierMark, mirror::Object*, mirror::Object*>();
461    x86_codegen->Move32(out_, Location::RegisterLocation(EAX));
462
463    RestoreLiveRegisters(codegen, locations);
464    __ jmp(GetExitLabel());
465  }
466
467 private:
468  const Location out_;
469  const Location obj_;
470
471  DISALLOW_COPY_AND_ASSIGN(ReadBarrierMarkSlowPathX86);
472};
473
474// Slow path generating a read barrier for a heap reference.
475class ReadBarrierForHeapReferenceSlowPathX86 : public SlowPathCode {
476 public:
477  ReadBarrierForHeapReferenceSlowPathX86(HInstruction* instruction,
478                                         Location out,
479                                         Location ref,
480                                         Location obj,
481                                         uint32_t offset,
482                                         Location index)
483      : SlowPathCode(instruction),
484        out_(out),
485        ref_(ref),
486        obj_(obj),
487        offset_(offset),
488        index_(index) {
489    DCHECK(kEmitCompilerReadBarrier);
490    // If `obj` is equal to `out` or `ref`, it means the initial object
491    // has been overwritten by (or after) the heap object reference load
492    // to be instrumented, e.g.:
493    //
494    //   __ movl(out, Address(out, offset));
495    //   codegen_->GenerateReadBarrierSlow(instruction, out_loc, out_loc, out_loc, offset);
496    //
497    // In that case, we have lost the information about the original
498    // object, and the emitted read barrier cannot work properly.
499    DCHECK(!obj.Equals(out)) << "obj=" << obj << " out=" << out;
500    DCHECK(!obj.Equals(ref)) << "obj=" << obj << " ref=" << ref;
501  }
502
503  void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
504    CodeGeneratorX86* x86_codegen = down_cast<CodeGeneratorX86*>(codegen);
505    LocationSummary* locations = instruction_->GetLocations();
506    Register reg_out = out_.AsRegister<Register>();
507    DCHECK(locations->CanCall());
508    DCHECK(!locations->GetLiveRegisters()->ContainsCoreRegister(reg_out));
509    DCHECK(!instruction_->IsInvoke() ||
510           (instruction_->IsInvokeStaticOrDirect() &&
511            instruction_->GetLocations()->Intrinsified()))
512        << "Unexpected instruction in read barrier for heap reference slow path: "
513        << instruction_->DebugName();
514
515    __ Bind(GetEntryLabel());
516    SaveLiveRegisters(codegen, locations);
517
518    // We may have to change the index's value, but as `index_` is a
519    // constant member (like other "inputs" of this slow path),
520    // introduce a copy of it, `index`.
521    Location index = index_;
522    if (index_.IsValid()) {
523      // Handle `index_` for HArrayGet and intrinsic UnsafeGetObject.
524      if (instruction_->IsArrayGet()) {
525        // Compute the actual memory offset and store it in `index`.
526        Register index_reg = index_.AsRegister<Register>();
527        DCHECK(locations->GetLiveRegisters()->ContainsCoreRegister(index_reg));
528        if (codegen->IsCoreCalleeSaveRegister(index_reg)) {
529          // We are about to change the value of `index_reg` (see the
530          // calls to art::x86::X86Assembler::shll and
531          // art::x86::X86Assembler::AddImmediate below), but it has
532          // not been saved by the previous call to
533          // art::SlowPathCode::SaveLiveRegisters, as it is a
534          // callee-save register --
535          // art::SlowPathCode::SaveLiveRegisters does not consider
536          // callee-save registers, as it has been designed with the
537          // assumption that callee-save registers are supposed to be
538          // handled by the called function.  So, as a callee-save
539          // register, `index_reg` _would_ eventually be saved onto
540          // the stack, but it would be too late: we would have
541          // changed its value earlier.  Therefore, we manually save
542          // it here into another freely available register,
543          // `free_reg`, chosen of course among the caller-save
544          // registers (as a callee-save `free_reg` register would
545          // exhibit the same problem).
546          //
547          // Note we could have requested a temporary register from
548          // the register allocator instead; but we prefer not to, as
549          // this is a slow path, and we know we can find a
550          // caller-save register that is available.
551          Register free_reg = FindAvailableCallerSaveRegister(codegen);
552          __ movl(free_reg, index_reg);
553          index_reg = free_reg;
554          index = Location::RegisterLocation(index_reg);
555        } else {
556          // The initial register stored in `index_` has already been
557          // saved in the call to art::SlowPathCode::SaveLiveRegisters
558          // (as it is not a callee-save register), so we can freely
559          // use it.
560        }
561        // Shifting the index value contained in `index_reg` by the scale
562        // factor (2) cannot overflow in practice, as the runtime is
563        // unable to allocate object arrays with a size larger than
564        // 2^26 - 1 (that is, 2^28 - 4 bytes).
565        __ shll(index_reg, Immediate(TIMES_4));
566        static_assert(
567            sizeof(mirror::HeapReference<mirror::Object>) == sizeof(int32_t),
568            "art::mirror::HeapReference<art::mirror::Object> and int32_t have different sizes.");
569        __ AddImmediate(index_reg, Immediate(offset_));
570      } else {
571        DCHECK(instruction_->IsInvoke());
572        DCHECK(instruction_->GetLocations()->Intrinsified());
573        DCHECK((instruction_->AsInvoke()->GetIntrinsic() == Intrinsics::kUnsafeGetObject) ||
574               (instruction_->AsInvoke()->GetIntrinsic() == Intrinsics::kUnsafeGetObjectVolatile))
575            << instruction_->AsInvoke()->GetIntrinsic();
576        DCHECK_EQ(offset_, 0U);
577        DCHECK(index_.IsRegisterPair());
578        // UnsafeGet's offset location is a register pair, the low
579        // part contains the correct offset.
580        index = index_.ToLow();
581      }
582    }
583
584    // We're moving two or three locations to locations that could
585    // overlap, so we need a parallel move resolver.
586    InvokeRuntimeCallingConvention calling_convention;
587    HParallelMove parallel_move(codegen->GetGraph()->GetArena());
588    parallel_move.AddMove(ref_,
589                          Location::RegisterLocation(calling_convention.GetRegisterAt(0)),
590                          Primitive::kPrimNot,
591                          nullptr);
592    parallel_move.AddMove(obj_,
593                          Location::RegisterLocation(calling_convention.GetRegisterAt(1)),
594                          Primitive::kPrimNot,
595                          nullptr);
596    if (index.IsValid()) {
597      parallel_move.AddMove(index,
598                            Location::RegisterLocation(calling_convention.GetRegisterAt(2)),
599                            Primitive::kPrimInt,
600                            nullptr);
601      codegen->GetMoveResolver()->EmitNativeCode(&parallel_move);
602    } else {
603      codegen->GetMoveResolver()->EmitNativeCode(&parallel_move);
604      __ movl(calling_convention.GetRegisterAt(2), Immediate(offset_));
605    }
606    x86_codegen->InvokeRuntime(QUICK_ENTRY_POINT(pReadBarrierSlow),
607                               instruction_,
608                               instruction_->GetDexPc(),
609                               this);
610    CheckEntrypointTypes<
611        kQuickReadBarrierSlow, mirror::Object*, mirror::Object*, mirror::Object*, uint32_t>();
612    x86_codegen->Move32(out_, Location::RegisterLocation(EAX));
613
614    RestoreLiveRegisters(codegen, locations);
615    __ jmp(GetExitLabel());
616  }
617
618  const char* GetDescription() const OVERRIDE { return "ReadBarrierForHeapReferenceSlowPathX86"; }
619
620 private:
621  Register FindAvailableCallerSaveRegister(CodeGenerator* codegen) {
622    size_t ref = static_cast<int>(ref_.AsRegister<Register>());
623    size_t obj = static_cast<int>(obj_.AsRegister<Register>());
624    for (size_t i = 0, e = codegen->GetNumberOfCoreRegisters(); i < e; ++i) {
625      if (i != ref && i != obj && !codegen->IsCoreCalleeSaveRegister(i)) {
626        return static_cast<Register>(i);
627      }
628    }
629    // We shall never fail to find a free caller-save register, as
630    // there are more than two core caller-save registers on x86
631    // (meaning it is possible to find one which is different from
632    // `ref` and `obj`).
633    DCHECK_GT(codegen->GetNumberOfCoreCallerSaveRegisters(), 2u);
634    LOG(FATAL) << "Could not find a free caller-save register";
635    UNREACHABLE();
636  }
637
638  const Location out_;
639  const Location ref_;
640  const Location obj_;
641  const uint32_t offset_;
642  // An additional location containing an index to an array.
643  // Only used for HArrayGet and the UnsafeGetObject &
644  // UnsafeGetObjectVolatile intrinsics.
645  const Location index_;
646
647  DISALLOW_COPY_AND_ASSIGN(ReadBarrierForHeapReferenceSlowPathX86);
648};
649
650// Slow path generating a read barrier for a GC root.
651class ReadBarrierForRootSlowPathX86 : public SlowPathCode {
652 public:
653  ReadBarrierForRootSlowPathX86(HInstruction* instruction, Location out, Location root)
654      : SlowPathCode(instruction), out_(out), root_(root) {
655    DCHECK(kEmitCompilerReadBarrier);
656  }
657
658  void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
659    LocationSummary* locations = instruction_->GetLocations();
660    Register reg_out = out_.AsRegister<Register>();
661    DCHECK(locations->CanCall());
662    DCHECK(!locations->GetLiveRegisters()->ContainsCoreRegister(reg_out));
663    DCHECK(instruction_->IsLoadClass() || instruction_->IsLoadString())
664        << "Unexpected instruction in read barrier for GC root slow path: "
665        << instruction_->DebugName();
666
667    __ Bind(GetEntryLabel());
668    SaveLiveRegisters(codegen, locations);
669
670    InvokeRuntimeCallingConvention calling_convention;
671    CodeGeneratorX86* x86_codegen = down_cast<CodeGeneratorX86*>(codegen);
672    x86_codegen->Move32(Location::RegisterLocation(calling_convention.GetRegisterAt(0)), root_);
673    x86_codegen->InvokeRuntime(QUICK_ENTRY_POINT(pReadBarrierForRootSlow),
674                               instruction_,
675                               instruction_->GetDexPc(),
676                               this);
677    CheckEntrypointTypes<kQuickReadBarrierForRootSlow, mirror::Object*, GcRoot<mirror::Object>*>();
678    x86_codegen->Move32(out_, Location::RegisterLocation(EAX));
679
680    RestoreLiveRegisters(codegen, locations);
681    __ jmp(GetExitLabel());
682  }
683
684  const char* GetDescription() const OVERRIDE { return "ReadBarrierForRootSlowPathX86"; }
685
686 private:
687  const Location out_;
688  const Location root_;
689
690  DISALLOW_COPY_AND_ASSIGN(ReadBarrierForRootSlowPathX86);
691};
692
693#undef __
694#define __ down_cast<X86Assembler*>(GetAssembler())->
695
696inline Condition X86Condition(IfCondition cond) {
697  switch (cond) {
698    case kCondEQ: return kEqual;
699    case kCondNE: return kNotEqual;
700    case kCondLT: return kLess;
701    case kCondLE: return kLessEqual;
702    case kCondGT: return kGreater;
703    case kCondGE: return kGreaterEqual;
704    case kCondB:  return kBelow;
705    case kCondBE: return kBelowEqual;
706    case kCondA:  return kAbove;
707    case kCondAE: return kAboveEqual;
708  }
709  LOG(FATAL) << "Unreachable";
710  UNREACHABLE();
711}
712
713// Maps signed condition to unsigned condition and FP condition to x86 name.
714inline Condition X86UnsignedOrFPCondition(IfCondition cond) {
715  switch (cond) {
716    case kCondEQ: return kEqual;
717    case kCondNE: return kNotEqual;
718    // Signed to unsigned, and FP to x86 name.
719    case kCondLT: return kBelow;
720    case kCondLE: return kBelowEqual;
721    case kCondGT: return kAbove;
722    case kCondGE: return kAboveEqual;
723    // Unsigned remain unchanged.
724    case kCondB:  return kBelow;
725    case kCondBE: return kBelowEqual;
726    case kCondA:  return kAbove;
727    case kCondAE: return kAboveEqual;
728  }
729  LOG(FATAL) << "Unreachable";
730  UNREACHABLE();
731}
732
733void CodeGeneratorX86::DumpCoreRegister(std::ostream& stream, int reg) const {
734  stream << Register(reg);
735}
736
737void CodeGeneratorX86::DumpFloatingPointRegister(std::ostream& stream, int reg) const {
738  stream << XmmRegister(reg);
739}
740
741size_t CodeGeneratorX86::SaveCoreRegister(size_t stack_index, uint32_t reg_id) {
742  __ movl(Address(ESP, stack_index), static_cast<Register>(reg_id));
743  return kX86WordSize;
744}
745
746size_t CodeGeneratorX86::RestoreCoreRegister(size_t stack_index, uint32_t reg_id) {
747  __ movl(static_cast<Register>(reg_id), Address(ESP, stack_index));
748  return kX86WordSize;
749}
750
751size_t CodeGeneratorX86::SaveFloatingPointRegister(size_t stack_index, uint32_t reg_id) {
752  __ movsd(Address(ESP, stack_index), XmmRegister(reg_id));
753  return GetFloatingPointSpillSlotSize();
754}
755
756size_t CodeGeneratorX86::RestoreFloatingPointRegister(size_t stack_index, uint32_t reg_id) {
757  __ movsd(XmmRegister(reg_id), Address(ESP, stack_index));
758  return GetFloatingPointSpillSlotSize();
759}
760
761void CodeGeneratorX86::InvokeRuntime(QuickEntrypointEnum entrypoint,
762                                     HInstruction* instruction,
763                                     uint32_t dex_pc,
764                                     SlowPathCode* slow_path) {
765  InvokeRuntime(GetThreadOffset<kX86WordSize>(entrypoint).Int32Value(),
766                instruction,
767                dex_pc,
768                slow_path);
769}
770
771void CodeGeneratorX86::InvokeRuntime(int32_t entry_point_offset,
772                                     HInstruction* instruction,
773                                     uint32_t dex_pc,
774                                     SlowPathCode* slow_path) {
775  ValidateInvokeRuntime(instruction, slow_path);
776  __ fs()->call(Address::Absolute(entry_point_offset));
777  RecordPcInfo(instruction, dex_pc, slow_path);
778}
779
780CodeGeneratorX86::CodeGeneratorX86(HGraph* graph,
781                                   const X86InstructionSetFeatures& isa_features,
782                                   const CompilerOptions& compiler_options,
783                                   OptimizingCompilerStats* stats)
784    : CodeGenerator(graph,
785                    kNumberOfCpuRegisters,
786                    kNumberOfXmmRegisters,
787                    kNumberOfRegisterPairs,
788                    ComputeRegisterMask(reinterpret_cast<const int*>(kCoreCalleeSaves),
789                                        arraysize(kCoreCalleeSaves))
790                        | (1 << kFakeReturnRegister),
791                    0,
792                    compiler_options,
793                    stats),
794      block_labels_(nullptr),
795      location_builder_(graph, this),
796      instruction_visitor_(graph, this),
797      move_resolver_(graph->GetArena(), this),
798      assembler_(graph->GetArena()),
799      isa_features_(isa_features),
800      method_patches_(graph->GetArena()->Adapter(kArenaAllocCodeGenerator)),
801      relative_call_patches_(graph->GetArena()->Adapter(kArenaAllocCodeGenerator)),
802      pc_relative_dex_cache_patches_(graph->GetArena()->Adapter(kArenaAllocCodeGenerator)),
803      simple_patches_(graph->GetArena()->Adapter(kArenaAllocCodeGenerator)),
804      string_patches_(graph->GetArena()->Adapter(kArenaAllocCodeGenerator)),
805      constant_area_start_(-1),
806      fixups_to_jump_tables_(graph->GetArena()->Adapter(kArenaAllocCodeGenerator)),
807      method_address_offset_(-1) {
808  // Use a fake return address register to mimic Quick.
809  AddAllocatedRegister(Location::RegisterLocation(kFakeReturnRegister));
810}
811
812void CodeGeneratorX86::SetupBlockedRegisters() const {
813  // Don't allocate the dalvik style register pair passing.
814  blocked_register_pairs_[ECX_EDX] = true;
815
816  // Stack register is always reserved.
817  blocked_core_registers_[ESP] = true;
818
819  UpdateBlockedPairRegisters();
820}
821
822void CodeGeneratorX86::UpdateBlockedPairRegisters() const {
823  for (int i = 0; i < kNumberOfRegisterPairs; i++) {
824    X86ManagedRegister current =
825        X86ManagedRegister::FromRegisterPair(static_cast<RegisterPair>(i));
826    if (blocked_core_registers_[current.AsRegisterPairLow()]
827        || blocked_core_registers_[current.AsRegisterPairHigh()]) {
828      blocked_register_pairs_[i] = true;
829    }
830  }
831}
832
833InstructionCodeGeneratorX86::InstructionCodeGeneratorX86(HGraph* graph, CodeGeneratorX86* codegen)
834      : InstructionCodeGenerator(graph, codegen),
835        assembler_(codegen->GetAssembler()),
836        codegen_(codegen) {}
837
838static dwarf::Reg DWARFReg(Register reg) {
839  return dwarf::Reg::X86Core(static_cast<int>(reg));
840}
841
842void CodeGeneratorX86::GenerateFrameEntry() {
843  __ cfi().SetCurrentCFAOffset(kX86WordSize);  // return address
844  __ Bind(&frame_entry_label_);
845  bool skip_overflow_check =
846      IsLeafMethod() && !FrameNeedsStackCheck(GetFrameSize(), InstructionSet::kX86);
847  DCHECK(GetCompilerOptions().GetImplicitStackOverflowChecks());
848
849  if (!skip_overflow_check) {
850    __ testl(EAX, Address(ESP, -static_cast<int32_t>(GetStackOverflowReservedBytes(kX86))));
851    RecordPcInfo(nullptr, 0);
852  }
853
854  if (HasEmptyFrame()) {
855    return;
856  }
857
858  for (int i = arraysize(kCoreCalleeSaves) - 1; i >= 0; --i) {
859    Register reg = kCoreCalleeSaves[i];
860    if (allocated_registers_.ContainsCoreRegister(reg)) {
861      __ pushl(reg);
862      __ cfi().AdjustCFAOffset(kX86WordSize);
863      __ cfi().RelOffset(DWARFReg(reg), 0);
864    }
865  }
866
867  int adjust = GetFrameSize() - FrameEntrySpillSize();
868  __ subl(ESP, Immediate(adjust));
869  __ cfi().AdjustCFAOffset(adjust);
870  __ movl(Address(ESP, kCurrentMethodStackOffset), kMethodRegisterArgument);
871}
872
873void CodeGeneratorX86::GenerateFrameExit() {
874  __ cfi().RememberState();
875  if (!HasEmptyFrame()) {
876    int adjust = GetFrameSize() - FrameEntrySpillSize();
877    __ addl(ESP, Immediate(adjust));
878    __ cfi().AdjustCFAOffset(-adjust);
879
880    for (size_t i = 0; i < arraysize(kCoreCalleeSaves); ++i) {
881      Register reg = kCoreCalleeSaves[i];
882      if (allocated_registers_.ContainsCoreRegister(reg)) {
883        __ popl(reg);
884        __ cfi().AdjustCFAOffset(-static_cast<int>(kX86WordSize));
885        __ cfi().Restore(DWARFReg(reg));
886      }
887    }
888  }
889  __ ret();
890  __ cfi().RestoreState();
891  __ cfi().DefCFAOffset(GetFrameSize());
892}
893
894void CodeGeneratorX86::Bind(HBasicBlock* block) {
895  __ Bind(GetLabelOf(block));
896}
897
898Location InvokeDexCallingConventionVisitorX86::GetReturnLocation(Primitive::Type type) const {
899  switch (type) {
900    case Primitive::kPrimBoolean:
901    case Primitive::kPrimByte:
902    case Primitive::kPrimChar:
903    case Primitive::kPrimShort:
904    case Primitive::kPrimInt:
905    case Primitive::kPrimNot:
906      return Location::RegisterLocation(EAX);
907
908    case Primitive::kPrimLong:
909      return Location::RegisterPairLocation(EAX, EDX);
910
911    case Primitive::kPrimVoid:
912      return Location::NoLocation();
913
914    case Primitive::kPrimDouble:
915    case Primitive::kPrimFloat:
916      return Location::FpuRegisterLocation(XMM0);
917  }
918
919  UNREACHABLE();
920}
921
922Location InvokeDexCallingConventionVisitorX86::GetMethodLocation() const {
923  return Location::RegisterLocation(kMethodRegisterArgument);
924}
925
926Location InvokeDexCallingConventionVisitorX86::GetNextLocation(Primitive::Type type) {
927  switch (type) {
928    case Primitive::kPrimBoolean:
929    case Primitive::kPrimByte:
930    case Primitive::kPrimChar:
931    case Primitive::kPrimShort:
932    case Primitive::kPrimInt:
933    case Primitive::kPrimNot: {
934      uint32_t index = gp_index_++;
935      stack_index_++;
936      if (index < calling_convention.GetNumberOfRegisters()) {
937        return Location::RegisterLocation(calling_convention.GetRegisterAt(index));
938      } else {
939        return Location::StackSlot(calling_convention.GetStackOffsetOf(stack_index_ - 1));
940      }
941    }
942
943    case Primitive::kPrimLong: {
944      uint32_t index = gp_index_;
945      gp_index_ += 2;
946      stack_index_ += 2;
947      if (index + 1 < calling_convention.GetNumberOfRegisters()) {
948        X86ManagedRegister pair = X86ManagedRegister::FromRegisterPair(
949            calling_convention.GetRegisterPairAt(index));
950        return Location::RegisterPairLocation(pair.AsRegisterPairLow(), pair.AsRegisterPairHigh());
951      } else {
952        return Location::DoubleStackSlot(calling_convention.GetStackOffsetOf(stack_index_ - 2));
953      }
954    }
955
956    case Primitive::kPrimFloat: {
957      uint32_t index = float_index_++;
958      stack_index_++;
959      if (index < calling_convention.GetNumberOfFpuRegisters()) {
960        return Location::FpuRegisterLocation(calling_convention.GetFpuRegisterAt(index));
961      } else {
962        return Location::StackSlot(calling_convention.GetStackOffsetOf(stack_index_ - 1));
963      }
964    }
965
966    case Primitive::kPrimDouble: {
967      uint32_t index = float_index_++;
968      stack_index_ += 2;
969      if (index < calling_convention.GetNumberOfFpuRegisters()) {
970        return Location::FpuRegisterLocation(calling_convention.GetFpuRegisterAt(index));
971      } else {
972        return Location::DoubleStackSlot(calling_convention.GetStackOffsetOf(stack_index_ - 2));
973      }
974    }
975
976    case Primitive::kPrimVoid:
977      LOG(FATAL) << "Unexpected parameter type " << type;
978      break;
979  }
980  return Location::NoLocation();
981}
982
983void CodeGeneratorX86::Move32(Location destination, Location source) {
984  if (source.Equals(destination)) {
985    return;
986  }
987  if (destination.IsRegister()) {
988    if (source.IsRegister()) {
989      __ movl(destination.AsRegister<Register>(), source.AsRegister<Register>());
990    } else if (source.IsFpuRegister()) {
991      __ movd(destination.AsRegister<Register>(), source.AsFpuRegister<XmmRegister>());
992    } else {
993      DCHECK(source.IsStackSlot());
994      __ movl(destination.AsRegister<Register>(), Address(ESP, source.GetStackIndex()));
995    }
996  } else if (destination.IsFpuRegister()) {
997    if (source.IsRegister()) {
998      __ movd(destination.AsFpuRegister<XmmRegister>(), source.AsRegister<Register>());
999    } else if (source.IsFpuRegister()) {
1000      __ movaps(destination.AsFpuRegister<XmmRegister>(), source.AsFpuRegister<XmmRegister>());
1001    } else {
1002      DCHECK(source.IsStackSlot());
1003      __ movss(destination.AsFpuRegister<XmmRegister>(), Address(ESP, source.GetStackIndex()));
1004    }
1005  } else {
1006    DCHECK(destination.IsStackSlot()) << destination;
1007    if (source.IsRegister()) {
1008      __ movl(Address(ESP, destination.GetStackIndex()), source.AsRegister<Register>());
1009    } else if (source.IsFpuRegister()) {
1010      __ movss(Address(ESP, destination.GetStackIndex()), source.AsFpuRegister<XmmRegister>());
1011    } else if (source.IsConstant()) {
1012      HConstant* constant = source.GetConstant();
1013      int32_t value = GetInt32ValueOf(constant);
1014      __ movl(Address(ESP, destination.GetStackIndex()), Immediate(value));
1015    } else {
1016      DCHECK(source.IsStackSlot());
1017      __ pushl(Address(ESP, source.GetStackIndex()));
1018      __ popl(Address(ESP, destination.GetStackIndex()));
1019    }
1020  }
1021}
1022
1023void CodeGeneratorX86::Move64(Location destination, Location source) {
1024  if (source.Equals(destination)) {
1025    return;
1026  }
1027  if (destination.IsRegisterPair()) {
1028    if (source.IsRegisterPair()) {
1029      EmitParallelMoves(
1030          Location::RegisterLocation(source.AsRegisterPairHigh<Register>()),
1031          Location::RegisterLocation(destination.AsRegisterPairHigh<Register>()),
1032          Primitive::kPrimInt,
1033          Location::RegisterLocation(source.AsRegisterPairLow<Register>()),
1034          Location::RegisterLocation(destination.AsRegisterPairLow<Register>()),
1035          Primitive::kPrimInt);
1036    } else if (source.IsFpuRegister()) {
1037      XmmRegister src_reg = source.AsFpuRegister<XmmRegister>();
1038      __ movd(destination.AsRegisterPairLow<Register>(), src_reg);
1039      __ psrlq(src_reg, Immediate(32));
1040      __ movd(destination.AsRegisterPairHigh<Register>(), src_reg);
1041    } else {
1042      // No conflict possible, so just do the moves.
1043      DCHECK(source.IsDoubleStackSlot());
1044      __ movl(destination.AsRegisterPairLow<Register>(), Address(ESP, source.GetStackIndex()));
1045      __ movl(destination.AsRegisterPairHigh<Register>(),
1046              Address(ESP, source.GetHighStackIndex(kX86WordSize)));
1047    }
1048  } else if (destination.IsFpuRegister()) {
1049    if (source.IsFpuRegister()) {
1050      __ movaps(destination.AsFpuRegister<XmmRegister>(), source.AsFpuRegister<XmmRegister>());
1051    } else if (source.IsDoubleStackSlot()) {
1052      __ movsd(destination.AsFpuRegister<XmmRegister>(), Address(ESP, source.GetStackIndex()));
1053    } else if (source.IsRegisterPair()) {
1054      size_t elem_size = Primitive::ComponentSize(Primitive::kPrimInt);
1055      // Create stack space for 2 elements.
1056      __ subl(ESP, Immediate(2 * elem_size));
1057      __ movl(Address(ESP, 0), source.AsRegisterPairLow<Register>());
1058      __ movl(Address(ESP, elem_size), source.AsRegisterPairHigh<Register>());
1059      __ movsd(destination.AsFpuRegister<XmmRegister>(), Address(ESP, 0));
1060      // And remove the temporary stack space we allocated.
1061      __ addl(ESP, Immediate(2 * elem_size));
1062    } else {
1063      LOG(FATAL) << "Unimplemented";
1064    }
1065  } else {
1066    DCHECK(destination.IsDoubleStackSlot()) << destination;
1067    if (source.IsRegisterPair()) {
1068      // No conflict possible, so just do the moves.
1069      __ movl(Address(ESP, destination.GetStackIndex()), source.AsRegisterPairLow<Register>());
1070      __ movl(Address(ESP, destination.GetHighStackIndex(kX86WordSize)),
1071              source.AsRegisterPairHigh<Register>());
1072    } else if (source.IsFpuRegister()) {
1073      __ movsd(Address(ESP, destination.GetStackIndex()), source.AsFpuRegister<XmmRegister>());
1074    } else if (source.IsConstant()) {
1075      HConstant* constant = source.GetConstant();
1076      int64_t value;
1077      if (constant->IsLongConstant()) {
1078        value = constant->AsLongConstant()->GetValue();
1079      } else {
1080        DCHECK(constant->IsDoubleConstant());
1081        value = bit_cast<int64_t, double>(constant->AsDoubleConstant()->GetValue());
1082      }
1083      __ movl(Address(ESP, destination.GetStackIndex()), Immediate(Low32Bits(value)));
1084      __ movl(Address(ESP, destination.GetHighStackIndex(kX86WordSize)), Immediate(High32Bits(value)));
1085    } else {
1086      DCHECK(source.IsDoubleStackSlot()) << source;
1087      EmitParallelMoves(
1088          Location::StackSlot(source.GetStackIndex()),
1089          Location::StackSlot(destination.GetStackIndex()),
1090          Primitive::kPrimInt,
1091          Location::StackSlot(source.GetHighStackIndex(kX86WordSize)),
1092          Location::StackSlot(destination.GetHighStackIndex(kX86WordSize)),
1093          Primitive::kPrimInt);
1094    }
1095  }
1096}
1097
1098void CodeGeneratorX86::MoveConstant(Location location, int32_t value) {
1099  DCHECK(location.IsRegister());
1100  __ movl(location.AsRegister<Register>(), Immediate(value));
1101}
1102
1103void CodeGeneratorX86::MoveLocation(Location dst, Location src, Primitive::Type dst_type) {
1104  HParallelMove move(GetGraph()->GetArena());
1105  if (dst_type == Primitive::kPrimLong && !src.IsConstant() && !src.IsFpuRegister()) {
1106    move.AddMove(src.ToLow(), dst.ToLow(), Primitive::kPrimInt, nullptr);
1107    move.AddMove(src.ToHigh(), dst.ToHigh(), Primitive::kPrimInt, nullptr);
1108  } else {
1109    move.AddMove(src, dst, dst_type, nullptr);
1110  }
1111  GetMoveResolver()->EmitNativeCode(&move);
1112}
1113
1114void CodeGeneratorX86::AddLocationAsTemp(Location location, LocationSummary* locations) {
1115  if (location.IsRegister()) {
1116    locations->AddTemp(location);
1117  } else if (location.IsRegisterPair()) {
1118    locations->AddTemp(Location::RegisterLocation(location.AsRegisterPairLow<Register>()));
1119    locations->AddTemp(Location::RegisterLocation(location.AsRegisterPairHigh<Register>()));
1120  } else {
1121    UNIMPLEMENTED(FATAL) << "AddLocationAsTemp not implemented for location " << location;
1122  }
1123}
1124
1125void InstructionCodeGeneratorX86::HandleGoto(HInstruction* got, HBasicBlock* successor) {
1126  DCHECK(!successor->IsExitBlock());
1127
1128  HBasicBlock* block = got->GetBlock();
1129  HInstruction* previous = got->GetPrevious();
1130
1131  HLoopInformation* info = block->GetLoopInformation();
1132  if (info != nullptr && info->IsBackEdge(*block) && info->HasSuspendCheck()) {
1133    GenerateSuspendCheck(info->GetSuspendCheck(), successor);
1134    return;
1135  }
1136
1137  if (block->IsEntryBlock() && (previous != nullptr) && previous->IsSuspendCheck()) {
1138    GenerateSuspendCheck(previous->AsSuspendCheck(), nullptr);
1139  }
1140  if (!codegen_->GoesToNextBlock(got->GetBlock(), successor)) {
1141    __ jmp(codegen_->GetLabelOf(successor));
1142  }
1143}
1144
1145void LocationsBuilderX86::VisitGoto(HGoto* got) {
1146  got->SetLocations(nullptr);
1147}
1148
1149void InstructionCodeGeneratorX86::VisitGoto(HGoto* got) {
1150  HandleGoto(got, got->GetSuccessor());
1151}
1152
1153void LocationsBuilderX86::VisitTryBoundary(HTryBoundary* try_boundary) {
1154  try_boundary->SetLocations(nullptr);
1155}
1156
1157void InstructionCodeGeneratorX86::VisitTryBoundary(HTryBoundary* try_boundary) {
1158  HBasicBlock* successor = try_boundary->GetNormalFlowSuccessor();
1159  if (!successor->IsExitBlock()) {
1160    HandleGoto(try_boundary, successor);
1161  }
1162}
1163
1164void LocationsBuilderX86::VisitExit(HExit* exit) {
1165  exit->SetLocations(nullptr);
1166}
1167
1168void InstructionCodeGeneratorX86::VisitExit(HExit* exit ATTRIBUTE_UNUSED) {
1169}
1170
1171template<class LabelType>
1172void InstructionCodeGeneratorX86::GenerateFPJumps(HCondition* cond,
1173                                                  LabelType* true_label,
1174                                                  LabelType* false_label) {
1175  if (cond->IsFPConditionTrueIfNaN()) {
1176    __ j(kUnordered, true_label);
1177  } else if (cond->IsFPConditionFalseIfNaN()) {
1178    __ j(kUnordered, false_label);
1179  }
1180  __ j(X86UnsignedOrFPCondition(cond->GetCondition()), true_label);
1181}
1182
1183template<class LabelType>
1184void InstructionCodeGeneratorX86::GenerateLongComparesAndJumps(HCondition* cond,
1185                                                               LabelType* true_label,
1186                                                               LabelType* false_label) {
1187  LocationSummary* locations = cond->GetLocations();
1188  Location left = locations->InAt(0);
1189  Location right = locations->InAt(1);
1190  IfCondition if_cond = cond->GetCondition();
1191
1192  Register left_high = left.AsRegisterPairHigh<Register>();
1193  Register left_low = left.AsRegisterPairLow<Register>();
1194  IfCondition true_high_cond = if_cond;
1195  IfCondition false_high_cond = cond->GetOppositeCondition();
1196  Condition final_condition = X86UnsignedOrFPCondition(if_cond);  // unsigned on lower part
1197
1198  // Set the conditions for the test, remembering that == needs to be
1199  // decided using the low words.
1200  switch (if_cond) {
1201    case kCondEQ:
1202    case kCondNE:
1203      // Nothing to do.
1204      break;
1205    case kCondLT:
1206      false_high_cond = kCondGT;
1207      break;
1208    case kCondLE:
1209      true_high_cond = kCondLT;
1210      break;
1211    case kCondGT:
1212      false_high_cond = kCondLT;
1213      break;
1214    case kCondGE:
1215      true_high_cond = kCondGT;
1216      break;
1217    case kCondB:
1218      false_high_cond = kCondA;
1219      break;
1220    case kCondBE:
1221      true_high_cond = kCondB;
1222      break;
1223    case kCondA:
1224      false_high_cond = kCondB;
1225      break;
1226    case kCondAE:
1227      true_high_cond = kCondA;
1228      break;
1229  }
1230
1231  if (right.IsConstant()) {
1232    int64_t value = right.GetConstant()->AsLongConstant()->GetValue();
1233    int32_t val_high = High32Bits(value);
1234    int32_t val_low = Low32Bits(value);
1235
1236    codegen_->Compare32BitValue(left_high, val_high);
1237    if (if_cond == kCondNE) {
1238      __ j(X86Condition(true_high_cond), true_label);
1239    } else if (if_cond == kCondEQ) {
1240      __ j(X86Condition(false_high_cond), false_label);
1241    } else {
1242      __ j(X86Condition(true_high_cond), true_label);
1243      __ j(X86Condition(false_high_cond), false_label);
1244    }
1245    // Must be equal high, so compare the lows.
1246    codegen_->Compare32BitValue(left_low, val_low);
1247  } else if (right.IsRegisterPair()) {
1248    Register right_high = right.AsRegisterPairHigh<Register>();
1249    Register right_low = right.AsRegisterPairLow<Register>();
1250
1251    __ cmpl(left_high, right_high);
1252    if (if_cond == kCondNE) {
1253      __ j(X86Condition(true_high_cond), true_label);
1254    } else if (if_cond == kCondEQ) {
1255      __ j(X86Condition(false_high_cond), false_label);
1256    } else {
1257      __ j(X86Condition(true_high_cond), true_label);
1258      __ j(X86Condition(false_high_cond), false_label);
1259    }
1260    // Must be equal high, so compare the lows.
1261    __ cmpl(left_low, right_low);
1262  } else {
1263    DCHECK(right.IsDoubleStackSlot());
1264    __ cmpl(left_high, Address(ESP, right.GetHighStackIndex(kX86WordSize)));
1265    if (if_cond == kCondNE) {
1266      __ j(X86Condition(true_high_cond), true_label);
1267    } else if (if_cond == kCondEQ) {
1268      __ j(X86Condition(false_high_cond), false_label);
1269    } else {
1270      __ j(X86Condition(true_high_cond), true_label);
1271      __ j(X86Condition(false_high_cond), false_label);
1272    }
1273    // Must be equal high, so compare the lows.
1274    __ cmpl(left_low, Address(ESP, right.GetStackIndex()));
1275  }
1276  // The last comparison might be unsigned.
1277  __ j(final_condition, true_label);
1278}
1279
1280void InstructionCodeGeneratorX86::GenerateFPCompare(Location lhs,
1281                                                    Location rhs,
1282                                                    HInstruction* insn,
1283                                                    bool is_double) {
1284  HX86LoadFromConstantTable* const_area = insn->InputAt(1)->AsX86LoadFromConstantTable();
1285  if (is_double) {
1286    if (rhs.IsFpuRegister()) {
1287      __ ucomisd(lhs.AsFpuRegister<XmmRegister>(), rhs.AsFpuRegister<XmmRegister>());
1288    } else if (const_area != nullptr) {
1289      DCHECK(const_area->IsEmittedAtUseSite());
1290      __ ucomisd(lhs.AsFpuRegister<XmmRegister>(),
1291                 codegen_->LiteralDoubleAddress(
1292                   const_area->GetConstant()->AsDoubleConstant()->GetValue(),
1293                   const_area->GetLocations()->InAt(0).AsRegister<Register>()));
1294    } else {
1295      DCHECK(rhs.IsDoubleStackSlot());
1296      __ ucomisd(lhs.AsFpuRegister<XmmRegister>(), Address(ESP, rhs.GetStackIndex()));
1297    }
1298  } else {
1299    if (rhs.IsFpuRegister()) {
1300      __ ucomiss(lhs.AsFpuRegister<XmmRegister>(), rhs.AsFpuRegister<XmmRegister>());
1301    } else if (const_area != nullptr) {
1302      DCHECK(const_area->IsEmittedAtUseSite());
1303      __ ucomiss(lhs.AsFpuRegister<XmmRegister>(),
1304                 codegen_->LiteralFloatAddress(
1305                   const_area->GetConstant()->AsFloatConstant()->GetValue(),
1306                   const_area->GetLocations()->InAt(0).AsRegister<Register>()));
1307    } else {
1308      DCHECK(rhs.IsStackSlot());
1309      __ ucomiss(lhs.AsFpuRegister<XmmRegister>(), Address(ESP, rhs.GetStackIndex()));
1310    }
1311  }
1312}
1313
1314template<class LabelType>
1315void InstructionCodeGeneratorX86::GenerateCompareTestAndBranch(HCondition* condition,
1316                                                               LabelType* true_target_in,
1317                                                               LabelType* false_target_in) {
1318  // Generated branching requires both targets to be explicit. If either of the
1319  // targets is nullptr (fallthrough) use and bind `fallthrough_target` instead.
1320  LabelType fallthrough_target;
1321  LabelType* true_target = true_target_in == nullptr ? &fallthrough_target : true_target_in;
1322  LabelType* false_target = false_target_in == nullptr ? &fallthrough_target : false_target_in;
1323
1324  LocationSummary* locations = condition->GetLocations();
1325  Location left = locations->InAt(0);
1326  Location right = locations->InAt(1);
1327
1328  Primitive::Type type = condition->InputAt(0)->GetType();
1329  switch (type) {
1330    case Primitive::kPrimLong:
1331      GenerateLongComparesAndJumps(condition, true_target, false_target);
1332      break;
1333    case Primitive::kPrimFloat:
1334      GenerateFPCompare(left, right, condition, false);
1335      GenerateFPJumps(condition, true_target, false_target);
1336      break;
1337    case Primitive::kPrimDouble:
1338      GenerateFPCompare(left, right, condition, true);
1339      GenerateFPJumps(condition, true_target, false_target);
1340      break;
1341    default:
1342      LOG(FATAL) << "Unexpected compare type " << type;
1343  }
1344
1345  if (false_target != &fallthrough_target) {
1346    __ jmp(false_target);
1347  }
1348
1349  if (fallthrough_target.IsLinked()) {
1350    __ Bind(&fallthrough_target);
1351  }
1352}
1353
1354static bool AreEflagsSetFrom(HInstruction* cond, HInstruction* branch) {
1355  // Moves may affect the eflags register (move zero uses xorl), so the EFLAGS
1356  // are set only strictly before `branch`. We can't use the eflags on long/FP
1357  // conditions if they are materialized due to the complex branching.
1358  return cond->IsCondition() &&
1359         cond->GetNext() == branch &&
1360         cond->InputAt(0)->GetType() != Primitive::kPrimLong &&
1361         !Primitive::IsFloatingPointType(cond->InputAt(0)->GetType());
1362}
1363
1364template<class LabelType>
1365void InstructionCodeGeneratorX86::GenerateTestAndBranch(HInstruction* instruction,
1366                                                        size_t condition_input_index,
1367                                                        LabelType* true_target,
1368                                                        LabelType* false_target) {
1369  HInstruction* cond = instruction->InputAt(condition_input_index);
1370
1371  if (true_target == nullptr && false_target == nullptr) {
1372    // Nothing to do. The code always falls through.
1373    return;
1374  } else if (cond->IsIntConstant()) {
1375    // Constant condition, statically compared against "true" (integer value 1).
1376    if (cond->AsIntConstant()->IsTrue()) {
1377      if (true_target != nullptr) {
1378        __ jmp(true_target);
1379      }
1380    } else {
1381      DCHECK(cond->AsIntConstant()->IsFalse()) << cond->AsIntConstant()->GetValue();
1382      if (false_target != nullptr) {
1383        __ jmp(false_target);
1384      }
1385    }
1386    return;
1387  }
1388
1389  // The following code generates these patterns:
1390  //  (1) true_target == nullptr && false_target != nullptr
1391  //        - opposite condition true => branch to false_target
1392  //  (2) true_target != nullptr && false_target == nullptr
1393  //        - condition true => branch to true_target
1394  //  (3) true_target != nullptr && false_target != nullptr
1395  //        - condition true => branch to true_target
1396  //        - branch to false_target
1397  if (IsBooleanValueOrMaterializedCondition(cond)) {
1398    if (AreEflagsSetFrom(cond, instruction)) {
1399      if (true_target == nullptr) {
1400        __ j(X86Condition(cond->AsCondition()->GetOppositeCondition()), false_target);
1401      } else {
1402        __ j(X86Condition(cond->AsCondition()->GetCondition()), true_target);
1403      }
1404    } else {
1405      // Materialized condition, compare against 0.
1406      Location lhs = instruction->GetLocations()->InAt(condition_input_index);
1407      if (lhs.IsRegister()) {
1408        __ testl(lhs.AsRegister<Register>(), lhs.AsRegister<Register>());
1409      } else {
1410        __ cmpl(Address(ESP, lhs.GetStackIndex()), Immediate(0));
1411      }
1412      if (true_target == nullptr) {
1413        __ j(kEqual, false_target);
1414      } else {
1415        __ j(kNotEqual, true_target);
1416      }
1417    }
1418  } else {
1419    // Condition has not been materialized, use its inputs as the comparison and
1420    // its condition as the branch condition.
1421    HCondition* condition = cond->AsCondition();
1422
1423    // If this is a long or FP comparison that has been folded into
1424    // the HCondition, generate the comparison directly.
1425    Primitive::Type type = condition->InputAt(0)->GetType();
1426    if (type == Primitive::kPrimLong || Primitive::IsFloatingPointType(type)) {
1427      GenerateCompareTestAndBranch(condition, true_target, false_target);
1428      return;
1429    }
1430
1431    Location lhs = condition->GetLocations()->InAt(0);
1432    Location rhs = condition->GetLocations()->InAt(1);
1433    // LHS is guaranteed to be in a register (see LocationsBuilderX86::HandleCondition).
1434    if (rhs.IsRegister()) {
1435      __ cmpl(lhs.AsRegister<Register>(), rhs.AsRegister<Register>());
1436    } else if (rhs.IsConstant()) {
1437      int32_t constant = CodeGenerator::GetInt32ValueOf(rhs.GetConstant());
1438      codegen_->Compare32BitValue(lhs.AsRegister<Register>(), constant);
1439    } else {
1440      __ cmpl(lhs.AsRegister<Register>(), Address(ESP, rhs.GetStackIndex()));
1441    }
1442    if (true_target == nullptr) {
1443      __ j(X86Condition(condition->GetOppositeCondition()), false_target);
1444    } else {
1445      __ j(X86Condition(condition->GetCondition()), true_target);
1446    }
1447  }
1448
1449  // If neither branch falls through (case 3), the conditional branch to `true_target`
1450  // was already emitted (case 2) and we need to emit a jump to `false_target`.
1451  if (true_target != nullptr && false_target != nullptr) {
1452    __ jmp(false_target);
1453  }
1454}
1455
1456void LocationsBuilderX86::VisitIf(HIf* if_instr) {
1457  LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(if_instr);
1458  if (IsBooleanValueOrMaterializedCondition(if_instr->InputAt(0))) {
1459    locations->SetInAt(0, Location::Any());
1460  }
1461}
1462
1463void InstructionCodeGeneratorX86::VisitIf(HIf* if_instr) {
1464  HBasicBlock* true_successor = if_instr->IfTrueSuccessor();
1465  HBasicBlock* false_successor = if_instr->IfFalseSuccessor();
1466  Label* true_target = codegen_->GoesToNextBlock(if_instr->GetBlock(), true_successor) ?
1467      nullptr : codegen_->GetLabelOf(true_successor);
1468  Label* false_target = codegen_->GoesToNextBlock(if_instr->GetBlock(), false_successor) ?
1469      nullptr : codegen_->GetLabelOf(false_successor);
1470  GenerateTestAndBranch(if_instr, /* condition_input_index */ 0, true_target, false_target);
1471}
1472
1473void LocationsBuilderX86::VisitDeoptimize(HDeoptimize* deoptimize) {
1474  LocationSummary* locations = new (GetGraph()->GetArena())
1475      LocationSummary(deoptimize, LocationSummary::kCallOnSlowPath);
1476  if (IsBooleanValueOrMaterializedCondition(deoptimize->InputAt(0))) {
1477    locations->SetInAt(0, Location::Any());
1478  }
1479}
1480
1481void InstructionCodeGeneratorX86::VisitDeoptimize(HDeoptimize* deoptimize) {
1482  SlowPathCode* slow_path = deopt_slow_paths_.NewSlowPath<DeoptimizationSlowPathX86>(deoptimize);
1483  GenerateTestAndBranch<Label>(deoptimize,
1484                               /* condition_input_index */ 0,
1485                               slow_path->GetEntryLabel(),
1486                               /* false_target */ nullptr);
1487}
1488
1489static bool SelectCanUseCMOV(HSelect* select) {
1490  // There are no conditional move instructions for XMMs.
1491  if (Primitive::IsFloatingPointType(select->GetType())) {
1492    return false;
1493  }
1494
1495  // A FP condition doesn't generate the single CC that we need.
1496  // In 32 bit mode, a long condition doesn't generate a single CC either.
1497  HInstruction* condition = select->GetCondition();
1498  if (condition->IsCondition()) {
1499    Primitive::Type compare_type = condition->InputAt(0)->GetType();
1500    if (compare_type == Primitive::kPrimLong ||
1501        Primitive::IsFloatingPointType(compare_type)) {
1502      return false;
1503    }
1504  }
1505
1506  // We can generate a CMOV for this Select.
1507  return true;
1508}
1509
1510void LocationsBuilderX86::VisitSelect(HSelect* select) {
1511  LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(select);
1512  if (Primitive::IsFloatingPointType(select->GetType())) {
1513    locations->SetInAt(0, Location::RequiresFpuRegister());
1514    locations->SetInAt(1, Location::Any());
1515  } else {
1516    locations->SetInAt(0, Location::RequiresRegister());
1517    if (SelectCanUseCMOV(select)) {
1518      if (select->InputAt(1)->IsConstant()) {
1519        // Cmov can't handle a constant value.
1520        locations->SetInAt(1, Location::RequiresRegister());
1521      } else {
1522        locations->SetInAt(1, Location::Any());
1523      }
1524    } else {
1525      locations->SetInAt(1, Location::Any());
1526    }
1527  }
1528  if (IsBooleanValueOrMaterializedCondition(select->GetCondition())) {
1529    locations->SetInAt(2, Location::RequiresRegister());
1530  }
1531  locations->SetOut(Location::SameAsFirstInput());
1532}
1533
1534void InstructionCodeGeneratorX86::GenerateIntCompare(Location lhs, Location rhs) {
1535  Register lhs_reg = lhs.AsRegister<Register>();
1536  if (rhs.IsConstant()) {
1537    int32_t value = CodeGenerator::GetInt32ValueOf(rhs.GetConstant());
1538    codegen_->Compare32BitValue(lhs_reg, value);
1539  } else if (rhs.IsStackSlot()) {
1540    __ cmpl(lhs_reg, Address(ESP, rhs.GetStackIndex()));
1541  } else {
1542    __ cmpl(lhs_reg, rhs.AsRegister<Register>());
1543  }
1544}
1545
1546void InstructionCodeGeneratorX86::VisitSelect(HSelect* select) {
1547  LocationSummary* locations = select->GetLocations();
1548  DCHECK(locations->InAt(0).Equals(locations->Out()));
1549  if (SelectCanUseCMOV(select)) {
1550    // If both the condition and the source types are integer, we can generate
1551    // a CMOV to implement Select.
1552
1553    HInstruction* select_condition = select->GetCondition();
1554    Condition cond = kNotEqual;
1555
1556    // Figure out how to test the 'condition'.
1557    if (select_condition->IsCondition()) {
1558      HCondition* condition = select_condition->AsCondition();
1559      if (!condition->IsEmittedAtUseSite()) {
1560        // This was a previously materialized condition.
1561        // Can we use the existing condition code?
1562        if (AreEflagsSetFrom(condition, select)) {
1563          // Materialization was the previous instruction. Condition codes are right.
1564          cond = X86Condition(condition->GetCondition());
1565        } else {
1566          // No, we have to recreate the condition code.
1567          Register cond_reg = locations->InAt(2).AsRegister<Register>();
1568          __ testl(cond_reg, cond_reg);
1569        }
1570      } else {
1571        // We can't handle FP or long here.
1572        DCHECK_NE(condition->InputAt(0)->GetType(), Primitive::kPrimLong);
1573        DCHECK(!Primitive::IsFloatingPointType(condition->InputAt(0)->GetType()));
1574        LocationSummary* cond_locations = condition->GetLocations();
1575        GenerateIntCompare(cond_locations->InAt(0), cond_locations->InAt(1));
1576        cond = X86Condition(condition->GetCondition());
1577      }
1578    } else {
1579      // Must be a boolean condition, which needs to be compared to 0.
1580      Register cond_reg = locations->InAt(2).AsRegister<Register>();
1581      __ testl(cond_reg, cond_reg);
1582    }
1583
1584    // If the condition is true, overwrite the output, which already contains false.
1585    Location false_loc = locations->InAt(0);
1586    Location true_loc = locations->InAt(1);
1587    if (select->GetType() == Primitive::kPrimLong) {
1588      // 64 bit conditional move.
1589      Register false_high = false_loc.AsRegisterPairHigh<Register>();
1590      Register false_low = false_loc.AsRegisterPairLow<Register>();
1591      if (true_loc.IsRegisterPair()) {
1592        __ cmovl(cond, false_high, true_loc.AsRegisterPairHigh<Register>());
1593        __ cmovl(cond, false_low, true_loc.AsRegisterPairLow<Register>());
1594      } else {
1595        __ cmovl(cond, false_high, Address(ESP, true_loc.GetHighStackIndex(kX86WordSize)));
1596        __ cmovl(cond, false_low, Address(ESP, true_loc.GetStackIndex()));
1597      }
1598    } else {
1599      // 32 bit conditional move.
1600      Register false_reg = false_loc.AsRegister<Register>();
1601      if (true_loc.IsRegister()) {
1602        __ cmovl(cond, false_reg, true_loc.AsRegister<Register>());
1603      } else {
1604        __ cmovl(cond, false_reg, Address(ESP, true_loc.GetStackIndex()));
1605      }
1606    }
1607  } else {
1608    NearLabel false_target;
1609    GenerateTestAndBranch<NearLabel>(
1610        select, /* condition_input_index */ 2, /* true_target */ nullptr, &false_target);
1611    codegen_->MoveLocation(locations->Out(), locations->InAt(1), select->GetType());
1612    __ Bind(&false_target);
1613  }
1614}
1615
1616void LocationsBuilderX86::VisitNativeDebugInfo(HNativeDebugInfo* info) {
1617  new (GetGraph()->GetArena()) LocationSummary(info);
1618}
1619
1620void InstructionCodeGeneratorX86::VisitNativeDebugInfo(HNativeDebugInfo*) {
1621  // MaybeRecordNativeDebugInfo is already called implicitly in CodeGenerator::Compile.
1622}
1623
1624void CodeGeneratorX86::GenerateNop() {
1625  __ nop();
1626}
1627
1628void LocationsBuilderX86::HandleCondition(HCondition* cond) {
1629  LocationSummary* locations =
1630      new (GetGraph()->GetArena()) LocationSummary(cond, LocationSummary::kNoCall);
1631  // Handle the long/FP comparisons made in instruction simplification.
1632  switch (cond->InputAt(0)->GetType()) {
1633    case Primitive::kPrimLong: {
1634      locations->SetInAt(0, Location::RequiresRegister());
1635      locations->SetInAt(1, Location::Any());
1636      if (!cond->IsEmittedAtUseSite()) {
1637        locations->SetOut(Location::RequiresRegister());
1638      }
1639      break;
1640    }
1641    case Primitive::kPrimFloat:
1642    case Primitive::kPrimDouble: {
1643      locations->SetInAt(0, Location::RequiresFpuRegister());
1644      if (cond->InputAt(1)->IsX86LoadFromConstantTable()) {
1645        DCHECK(cond->InputAt(1)->IsEmittedAtUseSite());
1646      } else if (cond->InputAt(1)->IsConstant()) {
1647        locations->SetInAt(1, Location::RequiresFpuRegister());
1648      } else {
1649        locations->SetInAt(1, Location::Any());
1650      }
1651      if (!cond->IsEmittedAtUseSite()) {
1652        locations->SetOut(Location::RequiresRegister());
1653      }
1654      break;
1655    }
1656    default:
1657      locations->SetInAt(0, Location::RequiresRegister());
1658      locations->SetInAt(1, Location::Any());
1659      if (!cond->IsEmittedAtUseSite()) {
1660        // We need a byte register.
1661        locations->SetOut(Location::RegisterLocation(ECX));
1662      }
1663      break;
1664  }
1665}
1666
1667void InstructionCodeGeneratorX86::HandleCondition(HCondition* cond) {
1668  if (cond->IsEmittedAtUseSite()) {
1669    return;
1670  }
1671
1672  LocationSummary* locations = cond->GetLocations();
1673  Location lhs = locations->InAt(0);
1674  Location rhs = locations->InAt(1);
1675  Register reg = locations->Out().AsRegister<Register>();
1676  NearLabel true_label, false_label;
1677
1678  switch (cond->InputAt(0)->GetType()) {
1679    default: {
1680      // Integer case.
1681
1682      // Clear output register: setb only sets the low byte.
1683      __ xorl(reg, reg);
1684      GenerateIntCompare(lhs, rhs);
1685      __ setb(X86Condition(cond->GetCondition()), reg);
1686      return;
1687    }
1688    case Primitive::kPrimLong:
1689      GenerateLongComparesAndJumps(cond, &true_label, &false_label);
1690      break;
1691    case Primitive::kPrimFloat:
1692      GenerateFPCompare(lhs, rhs, cond, false);
1693      GenerateFPJumps(cond, &true_label, &false_label);
1694      break;
1695    case Primitive::kPrimDouble:
1696      GenerateFPCompare(lhs, rhs, cond, true);
1697      GenerateFPJumps(cond, &true_label, &false_label);
1698      break;
1699  }
1700
1701  // Convert the jumps into the result.
1702  NearLabel done_label;
1703
1704  // False case: result = 0.
1705  __ Bind(&false_label);
1706  __ xorl(reg, reg);
1707  __ jmp(&done_label);
1708
1709  // True case: result = 1.
1710  __ Bind(&true_label);
1711  __ movl(reg, Immediate(1));
1712  __ Bind(&done_label);
1713}
1714
1715void LocationsBuilderX86::VisitEqual(HEqual* comp) {
1716  HandleCondition(comp);
1717}
1718
1719void InstructionCodeGeneratorX86::VisitEqual(HEqual* comp) {
1720  HandleCondition(comp);
1721}
1722
1723void LocationsBuilderX86::VisitNotEqual(HNotEqual* comp) {
1724  HandleCondition(comp);
1725}
1726
1727void InstructionCodeGeneratorX86::VisitNotEqual(HNotEqual* comp) {
1728  HandleCondition(comp);
1729}
1730
1731void LocationsBuilderX86::VisitLessThan(HLessThan* comp) {
1732  HandleCondition(comp);
1733}
1734
1735void InstructionCodeGeneratorX86::VisitLessThan(HLessThan* comp) {
1736  HandleCondition(comp);
1737}
1738
1739void LocationsBuilderX86::VisitLessThanOrEqual(HLessThanOrEqual* comp) {
1740  HandleCondition(comp);
1741}
1742
1743void InstructionCodeGeneratorX86::VisitLessThanOrEqual(HLessThanOrEqual* comp) {
1744  HandleCondition(comp);
1745}
1746
1747void LocationsBuilderX86::VisitGreaterThan(HGreaterThan* comp) {
1748  HandleCondition(comp);
1749}
1750
1751void InstructionCodeGeneratorX86::VisitGreaterThan(HGreaterThan* comp) {
1752  HandleCondition(comp);
1753}
1754
1755void LocationsBuilderX86::VisitGreaterThanOrEqual(HGreaterThanOrEqual* comp) {
1756  HandleCondition(comp);
1757}
1758
1759void InstructionCodeGeneratorX86::VisitGreaterThanOrEqual(HGreaterThanOrEqual* comp) {
1760  HandleCondition(comp);
1761}
1762
1763void LocationsBuilderX86::VisitBelow(HBelow* comp) {
1764  HandleCondition(comp);
1765}
1766
1767void InstructionCodeGeneratorX86::VisitBelow(HBelow* comp) {
1768  HandleCondition(comp);
1769}
1770
1771void LocationsBuilderX86::VisitBelowOrEqual(HBelowOrEqual* comp) {
1772  HandleCondition(comp);
1773}
1774
1775void InstructionCodeGeneratorX86::VisitBelowOrEqual(HBelowOrEqual* comp) {
1776  HandleCondition(comp);
1777}
1778
1779void LocationsBuilderX86::VisitAbove(HAbove* comp) {
1780  HandleCondition(comp);
1781}
1782
1783void InstructionCodeGeneratorX86::VisitAbove(HAbove* comp) {
1784  HandleCondition(comp);
1785}
1786
1787void LocationsBuilderX86::VisitAboveOrEqual(HAboveOrEqual* comp) {
1788  HandleCondition(comp);
1789}
1790
1791void InstructionCodeGeneratorX86::VisitAboveOrEqual(HAboveOrEqual* comp) {
1792  HandleCondition(comp);
1793}
1794
1795void LocationsBuilderX86::VisitIntConstant(HIntConstant* constant) {
1796  LocationSummary* locations =
1797      new (GetGraph()->GetArena()) LocationSummary(constant, LocationSummary::kNoCall);
1798  locations->SetOut(Location::ConstantLocation(constant));
1799}
1800
1801void InstructionCodeGeneratorX86::VisitIntConstant(HIntConstant* constant ATTRIBUTE_UNUSED) {
1802  // Will be generated at use site.
1803}
1804
1805void LocationsBuilderX86::VisitNullConstant(HNullConstant* constant) {
1806  LocationSummary* locations =
1807      new (GetGraph()->GetArena()) LocationSummary(constant, LocationSummary::kNoCall);
1808  locations->SetOut(Location::ConstantLocation(constant));
1809}
1810
1811void InstructionCodeGeneratorX86::VisitNullConstant(HNullConstant* constant ATTRIBUTE_UNUSED) {
1812  // Will be generated at use site.
1813}
1814
1815void LocationsBuilderX86::VisitLongConstant(HLongConstant* constant) {
1816  LocationSummary* locations =
1817      new (GetGraph()->GetArena()) LocationSummary(constant, LocationSummary::kNoCall);
1818  locations->SetOut(Location::ConstantLocation(constant));
1819}
1820
1821void InstructionCodeGeneratorX86::VisitLongConstant(HLongConstant* constant ATTRIBUTE_UNUSED) {
1822  // Will be generated at use site.
1823}
1824
1825void LocationsBuilderX86::VisitFloatConstant(HFloatConstant* constant) {
1826  LocationSummary* locations =
1827      new (GetGraph()->GetArena()) LocationSummary(constant, LocationSummary::kNoCall);
1828  locations->SetOut(Location::ConstantLocation(constant));
1829}
1830
1831void InstructionCodeGeneratorX86::VisitFloatConstant(HFloatConstant* constant ATTRIBUTE_UNUSED) {
1832  // Will be generated at use site.
1833}
1834
1835void LocationsBuilderX86::VisitDoubleConstant(HDoubleConstant* constant) {
1836  LocationSummary* locations =
1837      new (GetGraph()->GetArena()) LocationSummary(constant, LocationSummary::kNoCall);
1838  locations->SetOut(Location::ConstantLocation(constant));
1839}
1840
1841void InstructionCodeGeneratorX86::VisitDoubleConstant(HDoubleConstant* constant ATTRIBUTE_UNUSED) {
1842  // Will be generated at use site.
1843}
1844
1845void LocationsBuilderX86::VisitMemoryBarrier(HMemoryBarrier* memory_barrier) {
1846  memory_barrier->SetLocations(nullptr);
1847}
1848
1849void InstructionCodeGeneratorX86::VisitMemoryBarrier(HMemoryBarrier* memory_barrier) {
1850  codegen_->GenerateMemoryBarrier(memory_barrier->GetBarrierKind());
1851}
1852
1853void LocationsBuilderX86::VisitReturnVoid(HReturnVoid* ret) {
1854  ret->SetLocations(nullptr);
1855}
1856
1857void InstructionCodeGeneratorX86::VisitReturnVoid(HReturnVoid* ret ATTRIBUTE_UNUSED) {
1858  codegen_->GenerateFrameExit();
1859}
1860
1861void LocationsBuilderX86::VisitReturn(HReturn* ret) {
1862  LocationSummary* locations =
1863      new (GetGraph()->GetArena()) LocationSummary(ret, LocationSummary::kNoCall);
1864  switch (ret->InputAt(0)->GetType()) {
1865    case Primitive::kPrimBoolean:
1866    case Primitive::kPrimByte:
1867    case Primitive::kPrimChar:
1868    case Primitive::kPrimShort:
1869    case Primitive::kPrimInt:
1870    case Primitive::kPrimNot:
1871      locations->SetInAt(0, Location::RegisterLocation(EAX));
1872      break;
1873
1874    case Primitive::kPrimLong:
1875      locations->SetInAt(
1876          0, Location::RegisterPairLocation(EAX, EDX));
1877      break;
1878
1879    case Primitive::kPrimFloat:
1880    case Primitive::kPrimDouble:
1881      locations->SetInAt(
1882          0, Location::FpuRegisterLocation(XMM0));
1883      break;
1884
1885    default:
1886      LOG(FATAL) << "Unknown return type " << ret->InputAt(0)->GetType();
1887  }
1888}
1889
1890void InstructionCodeGeneratorX86::VisitReturn(HReturn* ret) {
1891  if (kIsDebugBuild) {
1892    switch (ret->InputAt(0)->GetType()) {
1893      case Primitive::kPrimBoolean:
1894      case Primitive::kPrimByte:
1895      case Primitive::kPrimChar:
1896      case Primitive::kPrimShort:
1897      case Primitive::kPrimInt:
1898      case Primitive::kPrimNot:
1899        DCHECK_EQ(ret->GetLocations()->InAt(0).AsRegister<Register>(), EAX);
1900        break;
1901
1902      case Primitive::kPrimLong:
1903        DCHECK_EQ(ret->GetLocations()->InAt(0).AsRegisterPairLow<Register>(), EAX);
1904        DCHECK_EQ(ret->GetLocations()->InAt(0).AsRegisterPairHigh<Register>(), EDX);
1905        break;
1906
1907      case Primitive::kPrimFloat:
1908      case Primitive::kPrimDouble:
1909        DCHECK_EQ(ret->GetLocations()->InAt(0).AsFpuRegister<XmmRegister>(), XMM0);
1910        break;
1911
1912      default:
1913        LOG(FATAL) << "Unknown return type " << ret->InputAt(0)->GetType();
1914    }
1915  }
1916  codegen_->GenerateFrameExit();
1917}
1918
1919void LocationsBuilderX86::VisitInvokeUnresolved(HInvokeUnresolved* invoke) {
1920  // The trampoline uses the same calling convention as dex calling conventions,
1921  // except instead of loading arg0/r0 with the target Method*, arg0/r0 will contain
1922  // the method_idx.
1923  HandleInvoke(invoke);
1924}
1925
1926void InstructionCodeGeneratorX86::VisitInvokeUnresolved(HInvokeUnresolved* invoke) {
1927  codegen_->GenerateInvokeUnresolvedRuntimeCall(invoke);
1928}
1929
1930void LocationsBuilderX86::VisitInvokeStaticOrDirect(HInvokeStaticOrDirect* invoke) {
1931  // Explicit clinit checks triggered by static invokes must have been pruned by
1932  // art::PrepareForRegisterAllocation.
1933  DCHECK(!invoke->IsStaticWithExplicitClinitCheck());
1934
1935  IntrinsicLocationsBuilderX86 intrinsic(codegen_);
1936  if (intrinsic.TryDispatch(invoke)) {
1937    if (invoke->GetLocations()->CanCall() && invoke->HasPcRelativeDexCache()) {
1938      invoke->GetLocations()->SetInAt(invoke->GetSpecialInputIndex(), Location::Any());
1939    }
1940    return;
1941  }
1942
1943  HandleInvoke(invoke);
1944
1945  // For PC-relative dex cache the invoke has an extra input, the PC-relative address base.
1946  if (invoke->HasPcRelativeDexCache()) {
1947    invoke->GetLocations()->SetInAt(invoke->GetSpecialInputIndex(), Location::RequiresRegister());
1948  }
1949}
1950
1951static bool TryGenerateIntrinsicCode(HInvoke* invoke, CodeGeneratorX86* codegen) {
1952  if (invoke->GetLocations()->Intrinsified()) {
1953    IntrinsicCodeGeneratorX86 intrinsic(codegen);
1954    intrinsic.Dispatch(invoke);
1955    return true;
1956  }
1957  return false;
1958}
1959
1960void InstructionCodeGeneratorX86::VisitInvokeStaticOrDirect(HInvokeStaticOrDirect* invoke) {
1961  // Explicit clinit checks triggered by static invokes must have been pruned by
1962  // art::PrepareForRegisterAllocation.
1963  DCHECK(!invoke->IsStaticWithExplicitClinitCheck());
1964
1965  if (TryGenerateIntrinsicCode(invoke, codegen_)) {
1966    return;
1967  }
1968
1969  LocationSummary* locations = invoke->GetLocations();
1970  codegen_->GenerateStaticOrDirectCall(
1971      invoke, locations->HasTemps() ? locations->GetTemp(0) : Location::NoLocation());
1972  codegen_->RecordPcInfo(invoke, invoke->GetDexPc());
1973}
1974
1975void LocationsBuilderX86::VisitInvokeVirtual(HInvokeVirtual* invoke) {
1976  IntrinsicLocationsBuilderX86 intrinsic(codegen_);
1977  if (intrinsic.TryDispatch(invoke)) {
1978    return;
1979  }
1980
1981  HandleInvoke(invoke);
1982}
1983
1984void LocationsBuilderX86::HandleInvoke(HInvoke* invoke) {
1985  InvokeDexCallingConventionVisitorX86 calling_convention_visitor;
1986  CodeGenerator::CreateCommonInvokeLocationSummary(invoke, &calling_convention_visitor);
1987}
1988
1989void InstructionCodeGeneratorX86::VisitInvokeVirtual(HInvokeVirtual* invoke) {
1990  if (TryGenerateIntrinsicCode(invoke, codegen_)) {
1991    return;
1992  }
1993
1994  codegen_->GenerateVirtualCall(invoke, invoke->GetLocations()->GetTemp(0));
1995  DCHECK(!codegen_->IsLeafMethod());
1996  codegen_->RecordPcInfo(invoke, invoke->GetDexPc());
1997}
1998
1999void LocationsBuilderX86::VisitInvokeInterface(HInvokeInterface* invoke) {
2000  // This call to HandleInvoke allocates a temporary (core) register
2001  // which is also used to transfer the hidden argument from FP to
2002  // core register.
2003  HandleInvoke(invoke);
2004  // Add the hidden argument.
2005  invoke->GetLocations()->AddTemp(Location::FpuRegisterLocation(XMM7));
2006}
2007
2008void InstructionCodeGeneratorX86::VisitInvokeInterface(HInvokeInterface* invoke) {
2009  // TODO: b/18116999, our IMTs can miss an IncompatibleClassChangeError.
2010  LocationSummary* locations = invoke->GetLocations();
2011  Register temp = locations->GetTemp(0).AsRegister<Register>();
2012  XmmRegister hidden_reg = locations->GetTemp(1).AsFpuRegister<XmmRegister>();
2013  Location receiver = locations->InAt(0);
2014  uint32_t class_offset = mirror::Object::ClassOffset().Int32Value();
2015
2016  // Set the hidden argument. This is safe to do this here, as XMM7
2017  // won't be modified thereafter, before the `call` instruction.
2018  DCHECK_EQ(XMM7, hidden_reg);
2019  __ movl(temp, Immediate(invoke->GetDexMethodIndex()));
2020  __ movd(hidden_reg, temp);
2021
2022  if (receiver.IsStackSlot()) {
2023    __ movl(temp, Address(ESP, receiver.GetStackIndex()));
2024    // /* HeapReference<Class> */ temp = temp->klass_
2025    __ movl(temp, Address(temp, class_offset));
2026  } else {
2027    // /* HeapReference<Class> */ temp = receiver->klass_
2028    __ movl(temp, Address(receiver.AsRegister<Register>(), class_offset));
2029  }
2030  codegen_->MaybeRecordImplicitNullCheck(invoke);
2031  // Instead of simply (possibly) unpoisoning `temp` here, we should
2032  // emit a read barrier for the previous class reference load.
2033  // However this is not required in practice, as this is an
2034  // intermediate/temporary reference and because the current
2035  // concurrent copying collector keeps the from-space memory
2036  // intact/accessible until the end of the marking phase (the
2037  // concurrent copying collector may not in the future).
2038  __ MaybeUnpoisonHeapReference(temp);
2039  // temp = temp->GetAddressOfIMT()
2040  __ movl(temp,
2041      Address(temp, mirror::Class::ImtPtrOffset(kX86PointerSize).Uint32Value()));
2042  // temp = temp->GetImtEntryAt(method_offset);
2043  uint32_t method_offset = static_cast<uint32_t>(ImTable::OffsetOfElement(
2044      invoke->GetImtIndex() % ImTable::kSize, kX86PointerSize));
2045  __ movl(temp, Address(temp, method_offset));
2046  // call temp->GetEntryPoint();
2047  __ call(Address(temp,
2048                  ArtMethod::EntryPointFromQuickCompiledCodeOffset(kX86WordSize).Int32Value()));
2049
2050  DCHECK(!codegen_->IsLeafMethod());
2051  codegen_->RecordPcInfo(invoke, invoke->GetDexPc());
2052}
2053
2054void LocationsBuilderX86::VisitNeg(HNeg* neg) {
2055  LocationSummary* locations =
2056      new (GetGraph()->GetArena()) LocationSummary(neg, LocationSummary::kNoCall);
2057  switch (neg->GetResultType()) {
2058    case Primitive::kPrimInt:
2059    case Primitive::kPrimLong:
2060      locations->SetInAt(0, Location::RequiresRegister());
2061      locations->SetOut(Location::SameAsFirstInput());
2062      break;
2063
2064    case Primitive::kPrimFloat:
2065      locations->SetInAt(0, Location::RequiresFpuRegister());
2066      locations->SetOut(Location::SameAsFirstInput());
2067      locations->AddTemp(Location::RequiresRegister());
2068      locations->AddTemp(Location::RequiresFpuRegister());
2069      break;
2070
2071    case Primitive::kPrimDouble:
2072      locations->SetInAt(0, Location::RequiresFpuRegister());
2073      locations->SetOut(Location::SameAsFirstInput());
2074      locations->AddTemp(Location::RequiresFpuRegister());
2075      break;
2076
2077    default:
2078      LOG(FATAL) << "Unexpected neg type " << neg->GetResultType();
2079  }
2080}
2081
2082void InstructionCodeGeneratorX86::VisitNeg(HNeg* neg) {
2083  LocationSummary* locations = neg->GetLocations();
2084  Location out = locations->Out();
2085  Location in = locations->InAt(0);
2086  switch (neg->GetResultType()) {
2087    case Primitive::kPrimInt:
2088      DCHECK(in.IsRegister());
2089      DCHECK(in.Equals(out));
2090      __ negl(out.AsRegister<Register>());
2091      break;
2092
2093    case Primitive::kPrimLong:
2094      DCHECK(in.IsRegisterPair());
2095      DCHECK(in.Equals(out));
2096      __ negl(out.AsRegisterPairLow<Register>());
2097      // Negation is similar to subtraction from zero.  The least
2098      // significant byte triggers a borrow when it is different from
2099      // zero; to take it into account, add 1 to the most significant
2100      // byte if the carry flag (CF) is set to 1 after the first NEGL
2101      // operation.
2102      __ adcl(out.AsRegisterPairHigh<Register>(), Immediate(0));
2103      __ negl(out.AsRegisterPairHigh<Register>());
2104      break;
2105
2106    case Primitive::kPrimFloat: {
2107      DCHECK(in.Equals(out));
2108      Register constant = locations->GetTemp(0).AsRegister<Register>();
2109      XmmRegister mask = locations->GetTemp(1).AsFpuRegister<XmmRegister>();
2110      // Implement float negation with an exclusive or with value
2111      // 0x80000000 (mask for bit 31, representing the sign of a
2112      // single-precision floating-point number).
2113      __ movl(constant, Immediate(INT32_C(0x80000000)));
2114      __ movd(mask, constant);
2115      __ xorps(out.AsFpuRegister<XmmRegister>(), mask);
2116      break;
2117    }
2118
2119    case Primitive::kPrimDouble: {
2120      DCHECK(in.Equals(out));
2121      XmmRegister mask = locations->GetTemp(0).AsFpuRegister<XmmRegister>();
2122      // Implement double negation with an exclusive or with value
2123      // 0x8000000000000000 (mask for bit 63, representing the sign of
2124      // a double-precision floating-point number).
2125      __ LoadLongConstant(mask, INT64_C(0x8000000000000000));
2126      __ xorpd(out.AsFpuRegister<XmmRegister>(), mask);
2127      break;
2128    }
2129
2130    default:
2131      LOG(FATAL) << "Unexpected neg type " << neg->GetResultType();
2132  }
2133}
2134
2135void LocationsBuilderX86::VisitX86FPNeg(HX86FPNeg* neg) {
2136  LocationSummary* locations =
2137      new (GetGraph()->GetArena()) LocationSummary(neg, LocationSummary::kNoCall);
2138  DCHECK(Primitive::IsFloatingPointType(neg->GetType()));
2139  locations->SetInAt(0, Location::RequiresFpuRegister());
2140  locations->SetInAt(1, Location::RequiresRegister());
2141  locations->SetOut(Location::SameAsFirstInput());
2142  locations->AddTemp(Location::RequiresFpuRegister());
2143}
2144
2145void InstructionCodeGeneratorX86::VisitX86FPNeg(HX86FPNeg* neg) {
2146  LocationSummary* locations = neg->GetLocations();
2147  Location out = locations->Out();
2148  DCHECK(locations->InAt(0).Equals(out));
2149
2150  Register constant_area = locations->InAt(1).AsRegister<Register>();
2151  XmmRegister mask = locations->GetTemp(0).AsFpuRegister<XmmRegister>();
2152  if (neg->GetType() == Primitive::kPrimFloat) {
2153    __ movss(mask, codegen_->LiteralInt32Address(INT32_C(0x80000000), constant_area));
2154    __ xorps(out.AsFpuRegister<XmmRegister>(), mask);
2155  } else {
2156     __ movsd(mask, codegen_->LiteralInt64Address(INT64_C(0x8000000000000000), constant_area));
2157     __ xorpd(out.AsFpuRegister<XmmRegister>(), mask);
2158  }
2159}
2160
2161void LocationsBuilderX86::VisitTypeConversion(HTypeConversion* conversion) {
2162  Primitive::Type result_type = conversion->GetResultType();
2163  Primitive::Type input_type = conversion->GetInputType();
2164  DCHECK_NE(result_type, input_type);
2165
2166  // The float-to-long and double-to-long type conversions rely on a
2167  // call to the runtime.
2168  LocationSummary::CallKind call_kind =
2169      ((input_type == Primitive::kPrimFloat || input_type == Primitive::kPrimDouble)
2170       && result_type == Primitive::kPrimLong)
2171      ? LocationSummary::kCall
2172      : LocationSummary::kNoCall;
2173  LocationSummary* locations =
2174      new (GetGraph()->GetArena()) LocationSummary(conversion, call_kind);
2175
2176  // The Java language does not allow treating boolean as an integral type but
2177  // our bit representation makes it safe.
2178
2179  switch (result_type) {
2180    case Primitive::kPrimByte:
2181      switch (input_type) {
2182        case Primitive::kPrimLong: {
2183          // Type conversion from long to byte is a result of code transformations.
2184          HInstruction* input = conversion->InputAt(0);
2185          Location input_location = input->IsConstant()
2186              ? Location::ConstantLocation(input->AsConstant())
2187              : Location::RegisterPairLocation(EAX, EDX);
2188          locations->SetInAt(0, input_location);
2189          // Make the output overlap to please the register allocator. This greatly simplifies
2190          // the validation of the linear scan implementation
2191          locations->SetOut(Location::RequiresRegister(), Location::kOutputOverlap);
2192          break;
2193        }
2194        case Primitive::kPrimBoolean:
2195          // Boolean input is a result of code transformations.
2196        case Primitive::kPrimShort:
2197        case Primitive::kPrimInt:
2198        case Primitive::kPrimChar:
2199          // Processing a Dex `int-to-byte' instruction.
2200          locations->SetInAt(0, Location::ByteRegisterOrConstant(ECX, conversion->InputAt(0)));
2201          // Make the output overlap to please the register allocator. This greatly simplifies
2202          // the validation of the linear scan implementation
2203          locations->SetOut(Location::RequiresRegister(), Location::kOutputOverlap);
2204          break;
2205
2206        default:
2207          LOG(FATAL) << "Unexpected type conversion from " << input_type
2208                     << " to " << result_type;
2209      }
2210      break;
2211
2212    case Primitive::kPrimShort:
2213      switch (input_type) {
2214        case Primitive::kPrimLong:
2215          // Type conversion from long to short is a result of code transformations.
2216        case Primitive::kPrimBoolean:
2217          // Boolean input is a result of code transformations.
2218        case Primitive::kPrimByte:
2219        case Primitive::kPrimInt:
2220        case Primitive::kPrimChar:
2221          // Processing a Dex `int-to-short' instruction.
2222          locations->SetInAt(0, Location::Any());
2223          locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
2224          break;
2225
2226        default:
2227          LOG(FATAL) << "Unexpected type conversion from " << input_type
2228                     << " to " << result_type;
2229      }
2230      break;
2231
2232    case Primitive::kPrimInt:
2233      switch (input_type) {
2234        case Primitive::kPrimLong:
2235          // Processing a Dex `long-to-int' instruction.
2236          locations->SetInAt(0, Location::Any());
2237          locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
2238          break;
2239
2240        case Primitive::kPrimFloat:
2241          // Processing a Dex `float-to-int' instruction.
2242          locations->SetInAt(0, Location::RequiresFpuRegister());
2243          locations->SetOut(Location::RequiresRegister());
2244          locations->AddTemp(Location::RequiresFpuRegister());
2245          break;
2246
2247        case Primitive::kPrimDouble:
2248          // Processing a Dex `double-to-int' instruction.
2249          locations->SetInAt(0, Location::RequiresFpuRegister());
2250          locations->SetOut(Location::RequiresRegister());
2251          locations->AddTemp(Location::RequiresFpuRegister());
2252          break;
2253
2254        default:
2255          LOG(FATAL) << "Unexpected type conversion from " << input_type
2256                     << " to " << result_type;
2257      }
2258      break;
2259
2260    case Primitive::kPrimLong:
2261      switch (input_type) {
2262        case Primitive::kPrimBoolean:
2263          // Boolean input is a result of code transformations.
2264        case Primitive::kPrimByte:
2265        case Primitive::kPrimShort:
2266        case Primitive::kPrimInt:
2267        case Primitive::kPrimChar:
2268          // Processing a Dex `int-to-long' instruction.
2269          locations->SetInAt(0, Location::RegisterLocation(EAX));
2270          locations->SetOut(Location::RegisterPairLocation(EAX, EDX));
2271          break;
2272
2273        case Primitive::kPrimFloat:
2274        case Primitive::kPrimDouble: {
2275          // Processing a Dex `float-to-long' or 'double-to-long' instruction.
2276          InvokeRuntimeCallingConvention calling_convention;
2277          XmmRegister parameter = calling_convention.GetFpuRegisterAt(0);
2278          locations->SetInAt(0, Location::FpuRegisterLocation(parameter));
2279
2280          // The runtime helper puts the result in EAX, EDX.
2281          locations->SetOut(Location::RegisterPairLocation(EAX, EDX));
2282        }
2283        break;
2284
2285        default:
2286          LOG(FATAL) << "Unexpected type conversion from " << input_type
2287                     << " to " << result_type;
2288      }
2289      break;
2290
2291    case Primitive::kPrimChar:
2292      switch (input_type) {
2293        case Primitive::kPrimLong:
2294          // Type conversion from long to char is a result of code transformations.
2295        case Primitive::kPrimBoolean:
2296          // Boolean input is a result of code transformations.
2297        case Primitive::kPrimByte:
2298        case Primitive::kPrimShort:
2299        case Primitive::kPrimInt:
2300          // Processing a Dex `int-to-char' instruction.
2301          locations->SetInAt(0, Location::Any());
2302          locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
2303          break;
2304
2305        default:
2306          LOG(FATAL) << "Unexpected type conversion from " << input_type
2307                     << " to " << result_type;
2308      }
2309      break;
2310
2311    case Primitive::kPrimFloat:
2312      switch (input_type) {
2313        case Primitive::kPrimBoolean:
2314          // Boolean input is a result of code transformations.
2315        case Primitive::kPrimByte:
2316        case Primitive::kPrimShort:
2317        case Primitive::kPrimInt:
2318        case Primitive::kPrimChar:
2319          // Processing a Dex `int-to-float' instruction.
2320          locations->SetInAt(0, Location::RequiresRegister());
2321          locations->SetOut(Location::RequiresFpuRegister());
2322          break;
2323
2324        case Primitive::kPrimLong:
2325          // Processing a Dex `long-to-float' instruction.
2326          locations->SetInAt(0, Location::Any());
2327          locations->SetOut(Location::Any());
2328          break;
2329
2330        case Primitive::kPrimDouble:
2331          // Processing a Dex `double-to-float' instruction.
2332          locations->SetInAt(0, Location::RequiresFpuRegister());
2333          locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
2334          break;
2335
2336        default:
2337          LOG(FATAL) << "Unexpected type conversion from " << input_type
2338                     << " to " << result_type;
2339      };
2340      break;
2341
2342    case Primitive::kPrimDouble:
2343      switch (input_type) {
2344        case Primitive::kPrimBoolean:
2345          // Boolean input is a result of code transformations.
2346        case Primitive::kPrimByte:
2347        case Primitive::kPrimShort:
2348        case Primitive::kPrimInt:
2349        case Primitive::kPrimChar:
2350          // Processing a Dex `int-to-double' instruction.
2351          locations->SetInAt(0, Location::RequiresRegister());
2352          locations->SetOut(Location::RequiresFpuRegister());
2353          break;
2354
2355        case Primitive::kPrimLong:
2356          // Processing a Dex `long-to-double' instruction.
2357          locations->SetInAt(0, Location::Any());
2358          locations->SetOut(Location::Any());
2359          break;
2360
2361        case Primitive::kPrimFloat:
2362          // Processing a Dex `float-to-double' instruction.
2363          locations->SetInAt(0, Location::RequiresFpuRegister());
2364          locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
2365          break;
2366
2367        default:
2368          LOG(FATAL) << "Unexpected type conversion from " << input_type
2369                     << " to " << result_type;
2370      }
2371      break;
2372
2373    default:
2374      LOG(FATAL) << "Unexpected type conversion from " << input_type
2375                 << " to " << result_type;
2376  }
2377}
2378
2379void InstructionCodeGeneratorX86::VisitTypeConversion(HTypeConversion* conversion) {
2380  LocationSummary* locations = conversion->GetLocations();
2381  Location out = locations->Out();
2382  Location in = locations->InAt(0);
2383  Primitive::Type result_type = conversion->GetResultType();
2384  Primitive::Type input_type = conversion->GetInputType();
2385  DCHECK_NE(result_type, input_type);
2386  switch (result_type) {
2387    case Primitive::kPrimByte:
2388      switch (input_type) {
2389        case Primitive::kPrimLong:
2390          // Type conversion from long to byte is a result of code transformations.
2391          if (in.IsRegisterPair()) {
2392            __ movsxb(out.AsRegister<Register>(), in.AsRegisterPairLow<ByteRegister>());
2393          } else {
2394            DCHECK(in.GetConstant()->IsLongConstant());
2395            int64_t value = in.GetConstant()->AsLongConstant()->GetValue();
2396            __ movl(out.AsRegister<Register>(), Immediate(static_cast<int8_t>(value)));
2397          }
2398          break;
2399        case Primitive::kPrimBoolean:
2400          // Boolean input is a result of code transformations.
2401        case Primitive::kPrimShort:
2402        case Primitive::kPrimInt:
2403        case Primitive::kPrimChar:
2404          // Processing a Dex `int-to-byte' instruction.
2405          if (in.IsRegister()) {
2406            __ movsxb(out.AsRegister<Register>(), in.AsRegister<ByteRegister>());
2407          } else {
2408            DCHECK(in.GetConstant()->IsIntConstant());
2409            int32_t value = in.GetConstant()->AsIntConstant()->GetValue();
2410            __ movl(out.AsRegister<Register>(), Immediate(static_cast<int8_t>(value)));
2411          }
2412          break;
2413
2414        default:
2415          LOG(FATAL) << "Unexpected type conversion from " << input_type
2416                     << " to " << result_type;
2417      }
2418      break;
2419
2420    case Primitive::kPrimShort:
2421      switch (input_type) {
2422        case Primitive::kPrimLong:
2423          // Type conversion from long to short is a result of code transformations.
2424          if (in.IsRegisterPair()) {
2425            __ movsxw(out.AsRegister<Register>(), in.AsRegisterPairLow<Register>());
2426          } else if (in.IsDoubleStackSlot()) {
2427            __ movsxw(out.AsRegister<Register>(), Address(ESP, in.GetStackIndex()));
2428          } else {
2429            DCHECK(in.GetConstant()->IsLongConstant());
2430            int64_t value = in.GetConstant()->AsLongConstant()->GetValue();
2431            __ movl(out.AsRegister<Register>(), Immediate(static_cast<int16_t>(value)));
2432          }
2433          break;
2434        case Primitive::kPrimBoolean:
2435          // Boolean input is a result of code transformations.
2436        case Primitive::kPrimByte:
2437        case Primitive::kPrimInt:
2438        case Primitive::kPrimChar:
2439          // Processing a Dex `int-to-short' instruction.
2440          if (in.IsRegister()) {
2441            __ movsxw(out.AsRegister<Register>(), in.AsRegister<Register>());
2442          } else if (in.IsStackSlot()) {
2443            __ movsxw(out.AsRegister<Register>(), Address(ESP, in.GetStackIndex()));
2444          } else {
2445            DCHECK(in.GetConstant()->IsIntConstant());
2446            int32_t value = in.GetConstant()->AsIntConstant()->GetValue();
2447            __ movl(out.AsRegister<Register>(), Immediate(static_cast<int16_t>(value)));
2448          }
2449          break;
2450
2451        default:
2452          LOG(FATAL) << "Unexpected type conversion from " << input_type
2453                     << " to " << result_type;
2454      }
2455      break;
2456
2457    case Primitive::kPrimInt:
2458      switch (input_type) {
2459        case Primitive::kPrimLong:
2460          // Processing a Dex `long-to-int' instruction.
2461          if (in.IsRegisterPair()) {
2462            __ movl(out.AsRegister<Register>(), in.AsRegisterPairLow<Register>());
2463          } else if (in.IsDoubleStackSlot()) {
2464            __ movl(out.AsRegister<Register>(), Address(ESP, in.GetStackIndex()));
2465          } else {
2466            DCHECK(in.IsConstant());
2467            DCHECK(in.GetConstant()->IsLongConstant());
2468            int64_t value = in.GetConstant()->AsLongConstant()->GetValue();
2469            __ movl(out.AsRegister<Register>(), Immediate(static_cast<int32_t>(value)));
2470          }
2471          break;
2472
2473        case Primitive::kPrimFloat: {
2474          // Processing a Dex `float-to-int' instruction.
2475          XmmRegister input = in.AsFpuRegister<XmmRegister>();
2476          Register output = out.AsRegister<Register>();
2477          XmmRegister temp = locations->GetTemp(0).AsFpuRegister<XmmRegister>();
2478          NearLabel done, nan;
2479
2480          __ movl(output, Immediate(kPrimIntMax));
2481          // temp = int-to-float(output)
2482          __ cvtsi2ss(temp, output);
2483          // if input >= temp goto done
2484          __ comiss(input, temp);
2485          __ j(kAboveEqual, &done);
2486          // if input == NaN goto nan
2487          __ j(kUnordered, &nan);
2488          // output = float-to-int-truncate(input)
2489          __ cvttss2si(output, input);
2490          __ jmp(&done);
2491          __ Bind(&nan);
2492          //  output = 0
2493          __ xorl(output, output);
2494          __ Bind(&done);
2495          break;
2496        }
2497
2498        case Primitive::kPrimDouble: {
2499          // Processing a Dex `double-to-int' instruction.
2500          XmmRegister input = in.AsFpuRegister<XmmRegister>();
2501          Register output = out.AsRegister<Register>();
2502          XmmRegister temp = locations->GetTemp(0).AsFpuRegister<XmmRegister>();
2503          NearLabel done, nan;
2504
2505          __ movl(output, Immediate(kPrimIntMax));
2506          // temp = int-to-double(output)
2507          __ cvtsi2sd(temp, output);
2508          // if input >= temp goto done
2509          __ comisd(input, temp);
2510          __ j(kAboveEqual, &done);
2511          // if input == NaN goto nan
2512          __ j(kUnordered, &nan);
2513          // output = double-to-int-truncate(input)
2514          __ cvttsd2si(output, input);
2515          __ jmp(&done);
2516          __ Bind(&nan);
2517          //  output = 0
2518          __ xorl(output, output);
2519          __ Bind(&done);
2520          break;
2521        }
2522
2523        default:
2524          LOG(FATAL) << "Unexpected type conversion from " << input_type
2525                     << " to " << result_type;
2526      }
2527      break;
2528
2529    case Primitive::kPrimLong:
2530      switch (input_type) {
2531        case Primitive::kPrimBoolean:
2532          // Boolean input is a result of code transformations.
2533        case Primitive::kPrimByte:
2534        case Primitive::kPrimShort:
2535        case Primitive::kPrimInt:
2536        case Primitive::kPrimChar:
2537          // Processing a Dex `int-to-long' instruction.
2538          DCHECK_EQ(out.AsRegisterPairLow<Register>(), EAX);
2539          DCHECK_EQ(out.AsRegisterPairHigh<Register>(), EDX);
2540          DCHECK_EQ(in.AsRegister<Register>(), EAX);
2541          __ cdq();
2542          break;
2543
2544        case Primitive::kPrimFloat:
2545          // Processing a Dex `float-to-long' instruction.
2546          codegen_->InvokeRuntime(QUICK_ENTRY_POINT(pF2l),
2547                                  conversion,
2548                                  conversion->GetDexPc(),
2549                                  nullptr);
2550          CheckEntrypointTypes<kQuickF2l, int64_t, float>();
2551          break;
2552
2553        case Primitive::kPrimDouble:
2554          // Processing a Dex `double-to-long' instruction.
2555          codegen_->InvokeRuntime(QUICK_ENTRY_POINT(pD2l),
2556                                  conversion,
2557                                  conversion->GetDexPc(),
2558                                  nullptr);
2559          CheckEntrypointTypes<kQuickD2l, int64_t, double>();
2560          break;
2561
2562        default:
2563          LOG(FATAL) << "Unexpected type conversion from " << input_type
2564                     << " to " << result_type;
2565      }
2566      break;
2567
2568    case Primitive::kPrimChar:
2569      switch (input_type) {
2570        case Primitive::kPrimLong:
2571          // Type conversion from long to short is a result of code transformations.
2572          if (in.IsRegisterPair()) {
2573            __ movzxw(out.AsRegister<Register>(), in.AsRegisterPairLow<Register>());
2574          } else if (in.IsDoubleStackSlot()) {
2575            __ movzxw(out.AsRegister<Register>(), Address(ESP, in.GetStackIndex()));
2576          } else {
2577            DCHECK(in.GetConstant()->IsLongConstant());
2578            int64_t value = in.GetConstant()->AsLongConstant()->GetValue();
2579            __ movl(out.AsRegister<Register>(), Immediate(static_cast<uint16_t>(value)));
2580          }
2581          break;
2582        case Primitive::kPrimBoolean:
2583          // Boolean input is a result of code transformations.
2584        case Primitive::kPrimByte:
2585        case Primitive::kPrimShort:
2586        case Primitive::kPrimInt:
2587          // Processing a Dex `Process a Dex `int-to-char'' instruction.
2588          if (in.IsRegister()) {
2589            __ movzxw(out.AsRegister<Register>(), in.AsRegister<Register>());
2590          } else if (in.IsStackSlot()) {
2591            __ movzxw(out.AsRegister<Register>(), Address(ESP, in.GetStackIndex()));
2592          } else {
2593            DCHECK(in.GetConstant()->IsIntConstant());
2594            int32_t value = in.GetConstant()->AsIntConstant()->GetValue();
2595            __ movl(out.AsRegister<Register>(), Immediate(static_cast<uint16_t>(value)));
2596          }
2597          break;
2598
2599        default:
2600          LOG(FATAL) << "Unexpected type conversion from " << input_type
2601                     << " to " << result_type;
2602      }
2603      break;
2604
2605    case Primitive::kPrimFloat:
2606      switch (input_type) {
2607        case Primitive::kPrimBoolean:
2608          // Boolean input is a result of code transformations.
2609        case Primitive::kPrimByte:
2610        case Primitive::kPrimShort:
2611        case Primitive::kPrimInt:
2612        case Primitive::kPrimChar:
2613          // Processing a Dex `int-to-float' instruction.
2614          __ cvtsi2ss(out.AsFpuRegister<XmmRegister>(), in.AsRegister<Register>());
2615          break;
2616
2617        case Primitive::kPrimLong: {
2618          // Processing a Dex `long-to-float' instruction.
2619          size_t adjustment = 0;
2620
2621          // Create stack space for the call to
2622          // InstructionCodeGeneratorX86::PushOntoFPStack and/or X86Assembler::fstps below.
2623          // TODO: enhance register allocator to ask for stack temporaries.
2624          if (!in.IsDoubleStackSlot() || !out.IsStackSlot()) {
2625            adjustment = Primitive::ComponentSize(Primitive::kPrimLong);
2626            __ subl(ESP, Immediate(adjustment));
2627          }
2628
2629          // Load the value to the FP stack, using temporaries if needed.
2630          PushOntoFPStack(in, 0, adjustment, false, true);
2631
2632          if (out.IsStackSlot()) {
2633            __ fstps(Address(ESP, out.GetStackIndex() + adjustment));
2634          } else {
2635            __ fstps(Address(ESP, 0));
2636            Location stack_temp = Location::StackSlot(0);
2637            codegen_->Move32(out, stack_temp);
2638          }
2639
2640          // Remove the temporary stack space we allocated.
2641          if (adjustment != 0) {
2642            __ addl(ESP, Immediate(adjustment));
2643          }
2644          break;
2645        }
2646
2647        case Primitive::kPrimDouble:
2648          // Processing a Dex `double-to-float' instruction.
2649          __ cvtsd2ss(out.AsFpuRegister<XmmRegister>(), in.AsFpuRegister<XmmRegister>());
2650          break;
2651
2652        default:
2653          LOG(FATAL) << "Unexpected type conversion from " << input_type
2654                     << " to " << result_type;
2655      };
2656      break;
2657
2658    case Primitive::kPrimDouble:
2659      switch (input_type) {
2660        case Primitive::kPrimBoolean:
2661          // Boolean input is a result of code transformations.
2662        case Primitive::kPrimByte:
2663        case Primitive::kPrimShort:
2664        case Primitive::kPrimInt:
2665        case Primitive::kPrimChar:
2666          // Processing a Dex `int-to-double' instruction.
2667          __ cvtsi2sd(out.AsFpuRegister<XmmRegister>(), in.AsRegister<Register>());
2668          break;
2669
2670        case Primitive::kPrimLong: {
2671          // Processing a Dex `long-to-double' instruction.
2672          size_t adjustment = 0;
2673
2674          // Create stack space for the call to
2675          // InstructionCodeGeneratorX86::PushOntoFPStack and/or X86Assembler::fstpl below.
2676          // TODO: enhance register allocator to ask for stack temporaries.
2677          if (!in.IsDoubleStackSlot() || !out.IsDoubleStackSlot()) {
2678            adjustment = Primitive::ComponentSize(Primitive::kPrimLong);
2679            __ subl(ESP, Immediate(adjustment));
2680          }
2681
2682          // Load the value to the FP stack, using temporaries if needed.
2683          PushOntoFPStack(in, 0, adjustment, false, true);
2684
2685          if (out.IsDoubleStackSlot()) {
2686            __ fstpl(Address(ESP, out.GetStackIndex() + adjustment));
2687          } else {
2688            __ fstpl(Address(ESP, 0));
2689            Location stack_temp = Location::DoubleStackSlot(0);
2690            codegen_->Move64(out, stack_temp);
2691          }
2692
2693          // Remove the temporary stack space we allocated.
2694          if (adjustment != 0) {
2695            __ addl(ESP, Immediate(adjustment));
2696          }
2697          break;
2698        }
2699
2700        case Primitive::kPrimFloat:
2701          // Processing a Dex `float-to-double' instruction.
2702          __ cvtss2sd(out.AsFpuRegister<XmmRegister>(), in.AsFpuRegister<XmmRegister>());
2703          break;
2704
2705        default:
2706          LOG(FATAL) << "Unexpected type conversion from " << input_type
2707                     << " to " << result_type;
2708      };
2709      break;
2710
2711    default:
2712      LOG(FATAL) << "Unexpected type conversion from " << input_type
2713                 << " to " << result_type;
2714  }
2715}
2716
2717void LocationsBuilderX86::VisitAdd(HAdd* add) {
2718  LocationSummary* locations =
2719      new (GetGraph()->GetArena()) LocationSummary(add, LocationSummary::kNoCall);
2720  switch (add->GetResultType()) {
2721    case Primitive::kPrimInt: {
2722      locations->SetInAt(0, Location::RequiresRegister());
2723      locations->SetInAt(1, Location::RegisterOrConstant(add->InputAt(1)));
2724      locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
2725      break;
2726    }
2727
2728    case Primitive::kPrimLong: {
2729      locations->SetInAt(0, Location::RequiresRegister());
2730      locations->SetInAt(1, Location::Any());
2731      locations->SetOut(Location::SameAsFirstInput());
2732      break;
2733    }
2734
2735    case Primitive::kPrimFloat:
2736    case Primitive::kPrimDouble: {
2737      locations->SetInAt(0, Location::RequiresFpuRegister());
2738      if (add->InputAt(1)->IsX86LoadFromConstantTable()) {
2739        DCHECK(add->InputAt(1)->IsEmittedAtUseSite());
2740      } else if (add->InputAt(1)->IsConstant()) {
2741        locations->SetInAt(1, Location::RequiresFpuRegister());
2742      } else {
2743        locations->SetInAt(1, Location::Any());
2744      }
2745      locations->SetOut(Location::SameAsFirstInput());
2746      break;
2747    }
2748
2749    default:
2750      LOG(FATAL) << "Unexpected add type " << add->GetResultType();
2751      break;
2752  }
2753}
2754
2755void InstructionCodeGeneratorX86::VisitAdd(HAdd* add) {
2756  LocationSummary* locations = add->GetLocations();
2757  Location first = locations->InAt(0);
2758  Location second = locations->InAt(1);
2759  Location out = locations->Out();
2760
2761  switch (add->GetResultType()) {
2762    case Primitive::kPrimInt: {
2763      if (second.IsRegister()) {
2764        if (out.AsRegister<Register>() == first.AsRegister<Register>()) {
2765          __ addl(out.AsRegister<Register>(), second.AsRegister<Register>());
2766        } else if (out.AsRegister<Register>() == second.AsRegister<Register>()) {
2767          __ addl(out.AsRegister<Register>(), first.AsRegister<Register>());
2768        } else {
2769          __ leal(out.AsRegister<Register>(), Address(
2770              first.AsRegister<Register>(), second.AsRegister<Register>(), TIMES_1, 0));
2771          }
2772      } else if (second.IsConstant()) {
2773        int32_t value = second.GetConstant()->AsIntConstant()->GetValue();
2774        if (out.AsRegister<Register>() == first.AsRegister<Register>()) {
2775          __ addl(out.AsRegister<Register>(), Immediate(value));
2776        } else {
2777          __ leal(out.AsRegister<Register>(), Address(first.AsRegister<Register>(), value));
2778        }
2779      } else {
2780        DCHECK(first.Equals(locations->Out()));
2781        __ addl(first.AsRegister<Register>(), Address(ESP, second.GetStackIndex()));
2782      }
2783      break;
2784    }
2785
2786    case Primitive::kPrimLong: {
2787      if (second.IsRegisterPair()) {
2788        __ addl(first.AsRegisterPairLow<Register>(), second.AsRegisterPairLow<Register>());
2789        __ adcl(first.AsRegisterPairHigh<Register>(), second.AsRegisterPairHigh<Register>());
2790      } else if (second.IsDoubleStackSlot()) {
2791        __ addl(first.AsRegisterPairLow<Register>(), Address(ESP, second.GetStackIndex()));
2792        __ adcl(first.AsRegisterPairHigh<Register>(),
2793                Address(ESP, second.GetHighStackIndex(kX86WordSize)));
2794      } else {
2795        DCHECK(second.IsConstant()) << second;
2796        int64_t value = second.GetConstant()->AsLongConstant()->GetValue();
2797        __ addl(first.AsRegisterPairLow<Register>(), Immediate(Low32Bits(value)));
2798        __ adcl(first.AsRegisterPairHigh<Register>(), Immediate(High32Bits(value)));
2799      }
2800      break;
2801    }
2802
2803    case Primitive::kPrimFloat: {
2804      if (second.IsFpuRegister()) {
2805        __ addss(first.AsFpuRegister<XmmRegister>(), second.AsFpuRegister<XmmRegister>());
2806      } else if (add->InputAt(1)->IsX86LoadFromConstantTable()) {
2807        HX86LoadFromConstantTable* const_area = add->InputAt(1)->AsX86LoadFromConstantTable();
2808        DCHECK(const_area->IsEmittedAtUseSite());
2809        __ addss(first.AsFpuRegister<XmmRegister>(),
2810                 codegen_->LiteralFloatAddress(
2811                   const_area->GetConstant()->AsFloatConstant()->GetValue(),
2812                   const_area->GetLocations()->InAt(0).AsRegister<Register>()));
2813      } else {
2814        DCHECK(second.IsStackSlot());
2815        __ addss(first.AsFpuRegister<XmmRegister>(), Address(ESP, second.GetStackIndex()));
2816      }
2817      break;
2818    }
2819
2820    case Primitive::kPrimDouble: {
2821      if (second.IsFpuRegister()) {
2822        __ addsd(first.AsFpuRegister<XmmRegister>(), second.AsFpuRegister<XmmRegister>());
2823      } else if (add->InputAt(1)->IsX86LoadFromConstantTable()) {
2824        HX86LoadFromConstantTable* const_area = add->InputAt(1)->AsX86LoadFromConstantTable();
2825        DCHECK(const_area->IsEmittedAtUseSite());
2826        __ addsd(first.AsFpuRegister<XmmRegister>(),
2827                 codegen_->LiteralDoubleAddress(
2828                   const_area->GetConstant()->AsDoubleConstant()->GetValue(),
2829                   const_area->GetLocations()->InAt(0).AsRegister<Register>()));
2830      } else {
2831        DCHECK(second.IsDoubleStackSlot());
2832        __ addsd(first.AsFpuRegister<XmmRegister>(), Address(ESP, second.GetStackIndex()));
2833      }
2834      break;
2835    }
2836
2837    default:
2838      LOG(FATAL) << "Unexpected add type " << add->GetResultType();
2839  }
2840}
2841
2842void LocationsBuilderX86::VisitSub(HSub* sub) {
2843  LocationSummary* locations =
2844      new (GetGraph()->GetArena()) LocationSummary(sub, LocationSummary::kNoCall);
2845  switch (sub->GetResultType()) {
2846    case Primitive::kPrimInt:
2847    case Primitive::kPrimLong: {
2848      locations->SetInAt(0, Location::RequiresRegister());
2849      locations->SetInAt(1, Location::Any());
2850      locations->SetOut(Location::SameAsFirstInput());
2851      break;
2852    }
2853    case Primitive::kPrimFloat:
2854    case Primitive::kPrimDouble: {
2855      locations->SetInAt(0, Location::RequiresFpuRegister());
2856      if (sub->InputAt(1)->IsX86LoadFromConstantTable()) {
2857        DCHECK(sub->InputAt(1)->IsEmittedAtUseSite());
2858      } else if (sub->InputAt(1)->IsConstant()) {
2859        locations->SetInAt(1, Location::RequiresFpuRegister());
2860      } else {
2861        locations->SetInAt(1, Location::Any());
2862      }
2863      locations->SetOut(Location::SameAsFirstInput());
2864      break;
2865    }
2866
2867    default:
2868      LOG(FATAL) << "Unexpected sub type " << sub->GetResultType();
2869  }
2870}
2871
2872void InstructionCodeGeneratorX86::VisitSub(HSub* sub) {
2873  LocationSummary* locations = sub->GetLocations();
2874  Location first = locations->InAt(0);
2875  Location second = locations->InAt(1);
2876  DCHECK(first.Equals(locations->Out()));
2877  switch (sub->GetResultType()) {
2878    case Primitive::kPrimInt: {
2879      if (second.IsRegister()) {
2880        __ subl(first.AsRegister<Register>(), second.AsRegister<Register>());
2881      } else if (second.IsConstant()) {
2882        __ subl(first.AsRegister<Register>(),
2883                Immediate(second.GetConstant()->AsIntConstant()->GetValue()));
2884      } else {
2885        __ subl(first.AsRegister<Register>(), Address(ESP, second.GetStackIndex()));
2886      }
2887      break;
2888    }
2889
2890    case Primitive::kPrimLong: {
2891      if (second.IsRegisterPair()) {
2892        __ subl(first.AsRegisterPairLow<Register>(), second.AsRegisterPairLow<Register>());
2893        __ sbbl(first.AsRegisterPairHigh<Register>(), second.AsRegisterPairHigh<Register>());
2894      } else if (second.IsDoubleStackSlot()) {
2895        __ subl(first.AsRegisterPairLow<Register>(), Address(ESP, second.GetStackIndex()));
2896        __ sbbl(first.AsRegisterPairHigh<Register>(),
2897                Address(ESP, second.GetHighStackIndex(kX86WordSize)));
2898      } else {
2899        DCHECK(second.IsConstant()) << second;
2900        int64_t value = second.GetConstant()->AsLongConstant()->GetValue();
2901        __ subl(first.AsRegisterPairLow<Register>(), Immediate(Low32Bits(value)));
2902        __ sbbl(first.AsRegisterPairHigh<Register>(), Immediate(High32Bits(value)));
2903      }
2904      break;
2905    }
2906
2907    case Primitive::kPrimFloat: {
2908      if (second.IsFpuRegister()) {
2909        __ subss(first.AsFpuRegister<XmmRegister>(), second.AsFpuRegister<XmmRegister>());
2910      } else if (sub->InputAt(1)->IsX86LoadFromConstantTable()) {
2911        HX86LoadFromConstantTable* const_area = sub->InputAt(1)->AsX86LoadFromConstantTable();
2912        DCHECK(const_area->IsEmittedAtUseSite());
2913        __ subss(first.AsFpuRegister<XmmRegister>(),
2914                 codegen_->LiteralFloatAddress(
2915                   const_area->GetConstant()->AsFloatConstant()->GetValue(),
2916                   const_area->GetLocations()->InAt(0).AsRegister<Register>()));
2917      } else {
2918        DCHECK(second.IsStackSlot());
2919        __ subss(first.AsFpuRegister<XmmRegister>(), Address(ESP, second.GetStackIndex()));
2920      }
2921      break;
2922    }
2923
2924    case Primitive::kPrimDouble: {
2925      if (second.IsFpuRegister()) {
2926        __ subsd(first.AsFpuRegister<XmmRegister>(), second.AsFpuRegister<XmmRegister>());
2927      } else if (sub->InputAt(1)->IsX86LoadFromConstantTable()) {
2928        HX86LoadFromConstantTable* const_area = sub->InputAt(1)->AsX86LoadFromConstantTable();
2929        DCHECK(const_area->IsEmittedAtUseSite());
2930        __ subsd(first.AsFpuRegister<XmmRegister>(),
2931                 codegen_->LiteralDoubleAddress(
2932                     const_area->GetConstant()->AsDoubleConstant()->GetValue(),
2933                     const_area->GetLocations()->InAt(0).AsRegister<Register>()));
2934      } else {
2935        DCHECK(second.IsDoubleStackSlot());
2936        __ subsd(first.AsFpuRegister<XmmRegister>(), Address(ESP, second.GetStackIndex()));
2937      }
2938      break;
2939    }
2940
2941    default:
2942      LOG(FATAL) << "Unexpected sub type " << sub->GetResultType();
2943  }
2944}
2945
2946void LocationsBuilderX86::VisitMul(HMul* mul) {
2947  LocationSummary* locations =
2948      new (GetGraph()->GetArena()) LocationSummary(mul, LocationSummary::kNoCall);
2949  switch (mul->GetResultType()) {
2950    case Primitive::kPrimInt:
2951      locations->SetInAt(0, Location::RequiresRegister());
2952      locations->SetInAt(1, Location::Any());
2953      if (mul->InputAt(1)->IsIntConstant()) {
2954        // Can use 3 operand multiply.
2955        locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
2956      } else {
2957        locations->SetOut(Location::SameAsFirstInput());
2958      }
2959      break;
2960    case Primitive::kPrimLong: {
2961      locations->SetInAt(0, Location::RequiresRegister());
2962      locations->SetInAt(1, Location::Any());
2963      locations->SetOut(Location::SameAsFirstInput());
2964      // Needed for imul on 32bits with 64bits output.
2965      locations->AddTemp(Location::RegisterLocation(EAX));
2966      locations->AddTemp(Location::RegisterLocation(EDX));
2967      break;
2968    }
2969    case Primitive::kPrimFloat:
2970    case Primitive::kPrimDouble: {
2971      locations->SetInAt(0, Location::RequiresFpuRegister());
2972      if (mul->InputAt(1)->IsX86LoadFromConstantTable()) {
2973        DCHECK(mul->InputAt(1)->IsEmittedAtUseSite());
2974      } else if (mul->InputAt(1)->IsConstant()) {
2975        locations->SetInAt(1, Location::RequiresFpuRegister());
2976      } else {
2977        locations->SetInAt(1, Location::Any());
2978      }
2979      locations->SetOut(Location::SameAsFirstInput());
2980      break;
2981    }
2982
2983    default:
2984      LOG(FATAL) << "Unexpected mul type " << mul->GetResultType();
2985  }
2986}
2987
2988void InstructionCodeGeneratorX86::VisitMul(HMul* mul) {
2989  LocationSummary* locations = mul->GetLocations();
2990  Location first = locations->InAt(0);
2991  Location second = locations->InAt(1);
2992  Location out = locations->Out();
2993
2994  switch (mul->GetResultType()) {
2995    case Primitive::kPrimInt:
2996      // The constant may have ended up in a register, so test explicitly to avoid
2997      // problems where the output may not be the same as the first operand.
2998      if (mul->InputAt(1)->IsIntConstant()) {
2999        Immediate imm(mul->InputAt(1)->AsIntConstant()->GetValue());
3000        __ imull(out.AsRegister<Register>(), first.AsRegister<Register>(), imm);
3001      } else if (second.IsRegister()) {
3002        DCHECK(first.Equals(out));
3003        __ imull(first.AsRegister<Register>(), second.AsRegister<Register>());
3004      } else {
3005        DCHECK(second.IsStackSlot());
3006        DCHECK(first.Equals(out));
3007        __ imull(first.AsRegister<Register>(), Address(ESP, second.GetStackIndex()));
3008      }
3009      break;
3010
3011    case Primitive::kPrimLong: {
3012      Register in1_hi = first.AsRegisterPairHigh<Register>();
3013      Register in1_lo = first.AsRegisterPairLow<Register>();
3014      Register eax = locations->GetTemp(0).AsRegister<Register>();
3015      Register edx = locations->GetTemp(1).AsRegister<Register>();
3016
3017      DCHECK_EQ(EAX, eax);
3018      DCHECK_EQ(EDX, edx);
3019
3020      // input: in1 - 64 bits, in2 - 64 bits.
3021      // output: in1
3022      // formula: in1.hi : in1.lo = (in1.lo * in2.hi + in1.hi * in2.lo)* 2^32 + in1.lo * in2.lo
3023      // parts: in1.hi = in1.lo * in2.hi + in1.hi * in2.lo + (in1.lo * in2.lo)[63:32]
3024      // parts: in1.lo = (in1.lo * in2.lo)[31:0]
3025      if (second.IsConstant()) {
3026        DCHECK(second.GetConstant()->IsLongConstant());
3027
3028        int64_t value = second.GetConstant()->AsLongConstant()->GetValue();
3029        int32_t low_value = Low32Bits(value);
3030        int32_t high_value = High32Bits(value);
3031        Immediate low(low_value);
3032        Immediate high(high_value);
3033
3034        __ movl(eax, high);
3035        // eax <- in1.lo * in2.hi
3036        __ imull(eax, in1_lo);
3037        // in1.hi <- in1.hi * in2.lo
3038        __ imull(in1_hi, low);
3039        // in1.hi <- in1.lo * in2.hi + in1.hi * in2.lo
3040        __ addl(in1_hi, eax);
3041        // move in2_lo to eax to prepare for double precision
3042        __ movl(eax, low);
3043        // edx:eax <- in1.lo * in2.lo
3044        __ mull(in1_lo);
3045        // in1.hi <- in2.hi * in1.lo +  in2.lo * in1.hi + (in1.lo * in2.lo)[63:32]
3046        __ addl(in1_hi, edx);
3047        // in1.lo <- (in1.lo * in2.lo)[31:0];
3048        __ movl(in1_lo, eax);
3049      } else if (second.IsRegisterPair()) {
3050        Register in2_hi = second.AsRegisterPairHigh<Register>();
3051        Register in2_lo = second.AsRegisterPairLow<Register>();
3052
3053        __ movl(eax, in2_hi);
3054        // eax <- in1.lo * in2.hi
3055        __ imull(eax, in1_lo);
3056        // in1.hi <- in1.hi * in2.lo
3057        __ imull(in1_hi, in2_lo);
3058        // in1.hi <- in1.lo * in2.hi + in1.hi * in2.lo
3059        __ addl(in1_hi, eax);
3060        // move in1_lo to eax to prepare for double precision
3061        __ movl(eax, in1_lo);
3062        // edx:eax <- in1.lo * in2.lo
3063        __ mull(in2_lo);
3064        // in1.hi <- in2.hi * in1.lo +  in2.lo * in1.hi + (in1.lo * in2.lo)[63:32]
3065        __ addl(in1_hi, edx);
3066        // in1.lo <- (in1.lo * in2.lo)[31:0];
3067        __ movl(in1_lo, eax);
3068      } else {
3069        DCHECK(second.IsDoubleStackSlot()) << second;
3070        Address in2_hi(ESP, second.GetHighStackIndex(kX86WordSize));
3071        Address in2_lo(ESP, second.GetStackIndex());
3072
3073        __ movl(eax, in2_hi);
3074        // eax <- in1.lo * in2.hi
3075        __ imull(eax, in1_lo);
3076        // in1.hi <- in1.hi * in2.lo
3077        __ imull(in1_hi, in2_lo);
3078        // in1.hi <- in1.lo * in2.hi + in1.hi * in2.lo
3079        __ addl(in1_hi, eax);
3080        // move in1_lo to eax to prepare for double precision
3081        __ movl(eax, in1_lo);
3082        // edx:eax <- in1.lo * in2.lo
3083        __ mull(in2_lo);
3084        // in1.hi <- in2.hi * in1.lo +  in2.lo * in1.hi + (in1.lo * in2.lo)[63:32]
3085        __ addl(in1_hi, edx);
3086        // in1.lo <- (in1.lo * in2.lo)[31:0];
3087        __ movl(in1_lo, eax);
3088      }
3089
3090      break;
3091    }
3092
3093    case Primitive::kPrimFloat: {
3094      DCHECK(first.Equals(locations->Out()));
3095      if (second.IsFpuRegister()) {
3096        __ mulss(first.AsFpuRegister<XmmRegister>(), second.AsFpuRegister<XmmRegister>());
3097      } else if (mul->InputAt(1)->IsX86LoadFromConstantTable()) {
3098        HX86LoadFromConstantTable* const_area = mul->InputAt(1)->AsX86LoadFromConstantTable();
3099        DCHECK(const_area->IsEmittedAtUseSite());
3100        __ mulss(first.AsFpuRegister<XmmRegister>(),
3101                 codegen_->LiteralFloatAddress(
3102                     const_area->GetConstant()->AsFloatConstant()->GetValue(),
3103                     const_area->GetLocations()->InAt(0).AsRegister<Register>()));
3104      } else {
3105        DCHECK(second.IsStackSlot());
3106        __ mulss(first.AsFpuRegister<XmmRegister>(), Address(ESP, second.GetStackIndex()));
3107      }
3108      break;
3109    }
3110
3111    case Primitive::kPrimDouble: {
3112      DCHECK(first.Equals(locations->Out()));
3113      if (second.IsFpuRegister()) {
3114        __ mulsd(first.AsFpuRegister<XmmRegister>(), second.AsFpuRegister<XmmRegister>());
3115      } else if (mul->InputAt(1)->IsX86LoadFromConstantTable()) {
3116        HX86LoadFromConstantTable* const_area = mul->InputAt(1)->AsX86LoadFromConstantTable();
3117        DCHECK(const_area->IsEmittedAtUseSite());
3118        __ mulsd(first.AsFpuRegister<XmmRegister>(),
3119                 codegen_->LiteralDoubleAddress(
3120                     const_area->GetConstant()->AsDoubleConstant()->GetValue(),
3121                     const_area->GetLocations()->InAt(0).AsRegister<Register>()));
3122      } else {
3123        DCHECK(second.IsDoubleStackSlot());
3124        __ mulsd(first.AsFpuRegister<XmmRegister>(), Address(ESP, second.GetStackIndex()));
3125      }
3126      break;
3127    }
3128
3129    default:
3130      LOG(FATAL) << "Unexpected mul type " << mul->GetResultType();
3131  }
3132}
3133
3134void InstructionCodeGeneratorX86::PushOntoFPStack(Location source,
3135                                                  uint32_t temp_offset,
3136                                                  uint32_t stack_adjustment,
3137                                                  bool is_fp,
3138                                                  bool is_wide) {
3139  if (source.IsStackSlot()) {
3140    DCHECK(!is_wide);
3141    if (is_fp) {
3142      __ flds(Address(ESP, source.GetStackIndex() + stack_adjustment));
3143    } else {
3144      __ filds(Address(ESP, source.GetStackIndex() + stack_adjustment));
3145    }
3146  } else if (source.IsDoubleStackSlot()) {
3147    DCHECK(is_wide);
3148    if (is_fp) {
3149      __ fldl(Address(ESP, source.GetStackIndex() + stack_adjustment));
3150    } else {
3151      __ fildl(Address(ESP, source.GetStackIndex() + stack_adjustment));
3152    }
3153  } else {
3154    // Write the value to the temporary location on the stack and load to FP stack.
3155    if (!is_wide) {
3156      Location stack_temp = Location::StackSlot(temp_offset);
3157      codegen_->Move32(stack_temp, source);
3158      if (is_fp) {
3159        __ flds(Address(ESP, temp_offset));
3160      } else {
3161        __ filds(Address(ESP, temp_offset));
3162      }
3163    } else {
3164      Location stack_temp = Location::DoubleStackSlot(temp_offset);
3165      codegen_->Move64(stack_temp, source);
3166      if (is_fp) {
3167        __ fldl(Address(ESP, temp_offset));
3168      } else {
3169        __ fildl(Address(ESP, temp_offset));
3170      }
3171    }
3172  }
3173}
3174
3175void InstructionCodeGeneratorX86::GenerateRemFP(HRem *rem) {
3176  Primitive::Type type = rem->GetResultType();
3177  bool is_float = type == Primitive::kPrimFloat;
3178  size_t elem_size = Primitive::ComponentSize(type);
3179  LocationSummary* locations = rem->GetLocations();
3180  Location first = locations->InAt(0);
3181  Location second = locations->InAt(1);
3182  Location out = locations->Out();
3183
3184  // Create stack space for 2 elements.
3185  // TODO: enhance register allocator to ask for stack temporaries.
3186  __ subl(ESP, Immediate(2 * elem_size));
3187
3188  // Load the values to the FP stack in reverse order, using temporaries if needed.
3189  const bool is_wide = !is_float;
3190  PushOntoFPStack(second, elem_size, 2 * elem_size, /* is_fp */ true, is_wide);
3191  PushOntoFPStack(first, 0, 2 * elem_size, /* is_fp */ true, is_wide);
3192
3193  // Loop doing FPREM until we stabilize.
3194  NearLabel retry;
3195  __ Bind(&retry);
3196  __ fprem();
3197
3198  // Move FP status to AX.
3199  __ fstsw();
3200
3201  // And see if the argument reduction is complete. This is signaled by the
3202  // C2 FPU flag bit set to 0.
3203  __ andl(EAX, Immediate(kC2ConditionMask));
3204  __ j(kNotEqual, &retry);
3205
3206  // We have settled on the final value. Retrieve it into an XMM register.
3207  // Store FP top of stack to real stack.
3208  if (is_float) {
3209    __ fsts(Address(ESP, 0));
3210  } else {
3211    __ fstl(Address(ESP, 0));
3212  }
3213
3214  // Pop the 2 items from the FP stack.
3215  __ fucompp();
3216
3217  // Load the value from the stack into an XMM register.
3218  DCHECK(out.IsFpuRegister()) << out;
3219  if (is_float) {
3220    __ movss(out.AsFpuRegister<XmmRegister>(), Address(ESP, 0));
3221  } else {
3222    __ movsd(out.AsFpuRegister<XmmRegister>(), Address(ESP, 0));
3223  }
3224
3225  // And remove the temporary stack space we allocated.
3226  __ addl(ESP, Immediate(2 * elem_size));
3227}
3228
3229
3230void InstructionCodeGeneratorX86::DivRemOneOrMinusOne(HBinaryOperation* instruction) {
3231  DCHECK(instruction->IsDiv() || instruction->IsRem());
3232
3233  LocationSummary* locations = instruction->GetLocations();
3234  DCHECK(locations->InAt(1).IsConstant());
3235  DCHECK(locations->InAt(1).GetConstant()->IsIntConstant());
3236
3237  Register out_register = locations->Out().AsRegister<Register>();
3238  Register input_register = locations->InAt(0).AsRegister<Register>();
3239  int32_t imm = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
3240
3241  DCHECK(imm == 1 || imm == -1);
3242
3243  if (instruction->IsRem()) {
3244    __ xorl(out_register, out_register);
3245  } else {
3246    __ movl(out_register, input_register);
3247    if (imm == -1) {
3248      __ negl(out_register);
3249    }
3250  }
3251}
3252
3253
3254void InstructionCodeGeneratorX86::DivByPowerOfTwo(HDiv* instruction) {
3255  LocationSummary* locations = instruction->GetLocations();
3256
3257  Register out_register = locations->Out().AsRegister<Register>();
3258  Register input_register = locations->InAt(0).AsRegister<Register>();
3259  int32_t imm = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
3260  DCHECK(IsPowerOfTwo(AbsOrMin(imm)));
3261  uint32_t abs_imm = static_cast<uint32_t>(AbsOrMin(imm));
3262
3263  Register num = locations->GetTemp(0).AsRegister<Register>();
3264
3265  __ leal(num, Address(input_register, abs_imm - 1));
3266  __ testl(input_register, input_register);
3267  __ cmovl(kGreaterEqual, num, input_register);
3268  int shift = CTZ(imm);
3269  __ sarl(num, Immediate(shift));
3270
3271  if (imm < 0) {
3272    __ negl(num);
3273  }
3274
3275  __ movl(out_register, num);
3276}
3277
3278void InstructionCodeGeneratorX86::GenerateDivRemWithAnyConstant(HBinaryOperation* instruction) {
3279  DCHECK(instruction->IsDiv() || instruction->IsRem());
3280
3281  LocationSummary* locations = instruction->GetLocations();
3282  int imm = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
3283
3284  Register eax = locations->InAt(0).AsRegister<Register>();
3285  Register out = locations->Out().AsRegister<Register>();
3286  Register num;
3287  Register edx;
3288
3289  if (instruction->IsDiv()) {
3290    edx = locations->GetTemp(0).AsRegister<Register>();
3291    num = locations->GetTemp(1).AsRegister<Register>();
3292  } else {
3293    edx = locations->Out().AsRegister<Register>();
3294    num = locations->GetTemp(0).AsRegister<Register>();
3295  }
3296
3297  DCHECK_EQ(EAX, eax);
3298  DCHECK_EQ(EDX, edx);
3299  if (instruction->IsDiv()) {
3300    DCHECK_EQ(EAX, out);
3301  } else {
3302    DCHECK_EQ(EDX, out);
3303  }
3304
3305  int64_t magic;
3306  int shift;
3307  CalculateMagicAndShiftForDivRem(imm, false /* is_long */, &magic, &shift);
3308
3309  NearLabel ndiv;
3310  NearLabel end;
3311  // If numerator is 0, the result is 0, no computation needed.
3312  __ testl(eax, eax);
3313  __ j(kNotEqual, &ndiv);
3314
3315  __ xorl(out, out);
3316  __ jmp(&end);
3317
3318  __ Bind(&ndiv);
3319
3320  // Save the numerator.
3321  __ movl(num, eax);
3322
3323  // EAX = magic
3324  __ movl(eax, Immediate(magic));
3325
3326  // EDX:EAX = magic * numerator
3327  __ imull(num);
3328
3329  if (imm > 0 && magic < 0) {
3330    // EDX += num
3331    __ addl(edx, num);
3332  } else if (imm < 0 && magic > 0) {
3333    __ subl(edx, num);
3334  }
3335
3336  // Shift if needed.
3337  if (shift != 0) {
3338    __ sarl(edx, Immediate(shift));
3339  }
3340
3341  // EDX += 1 if EDX < 0
3342  __ movl(eax, edx);
3343  __ shrl(edx, Immediate(31));
3344  __ addl(edx, eax);
3345
3346  if (instruction->IsRem()) {
3347    __ movl(eax, num);
3348    __ imull(edx, Immediate(imm));
3349    __ subl(eax, edx);
3350    __ movl(edx, eax);
3351  } else {
3352    __ movl(eax, edx);
3353  }
3354  __ Bind(&end);
3355}
3356
3357void InstructionCodeGeneratorX86::GenerateDivRemIntegral(HBinaryOperation* instruction) {
3358  DCHECK(instruction->IsDiv() || instruction->IsRem());
3359
3360  LocationSummary* locations = instruction->GetLocations();
3361  Location out = locations->Out();
3362  Location first = locations->InAt(0);
3363  Location second = locations->InAt(1);
3364  bool is_div = instruction->IsDiv();
3365
3366  switch (instruction->GetResultType()) {
3367    case Primitive::kPrimInt: {
3368      DCHECK_EQ(EAX, first.AsRegister<Register>());
3369      DCHECK_EQ(is_div ? EAX : EDX, out.AsRegister<Register>());
3370
3371      if (second.IsConstant()) {
3372        int32_t imm = second.GetConstant()->AsIntConstant()->GetValue();
3373
3374        if (imm == 0) {
3375          // Do not generate anything for 0. DivZeroCheck would forbid any generated code.
3376        } else if (imm == 1 || imm == -1) {
3377          DivRemOneOrMinusOne(instruction);
3378        } else if (is_div && IsPowerOfTwo(AbsOrMin(imm))) {
3379          DivByPowerOfTwo(instruction->AsDiv());
3380        } else {
3381          DCHECK(imm <= -2 || imm >= 2);
3382          GenerateDivRemWithAnyConstant(instruction);
3383        }
3384      } else {
3385        SlowPathCode* slow_path = new (GetGraph()->GetArena()) DivRemMinusOneSlowPathX86(
3386            instruction, out.AsRegister<Register>(), is_div);
3387        codegen_->AddSlowPath(slow_path);
3388
3389        Register second_reg = second.AsRegister<Register>();
3390        // 0x80000000/-1 triggers an arithmetic exception!
3391        // Dividing by -1 is actually negation and -0x800000000 = 0x80000000 so
3392        // it's safe to just use negl instead of more complex comparisons.
3393
3394        __ cmpl(second_reg, Immediate(-1));
3395        __ j(kEqual, slow_path->GetEntryLabel());
3396
3397        // edx:eax <- sign-extended of eax
3398        __ cdq();
3399        // eax = quotient, edx = remainder
3400        __ idivl(second_reg);
3401        __ Bind(slow_path->GetExitLabel());
3402      }
3403      break;
3404    }
3405
3406    case Primitive::kPrimLong: {
3407      InvokeRuntimeCallingConvention calling_convention;
3408      DCHECK_EQ(calling_convention.GetRegisterAt(0), first.AsRegisterPairLow<Register>());
3409      DCHECK_EQ(calling_convention.GetRegisterAt(1), first.AsRegisterPairHigh<Register>());
3410      DCHECK_EQ(calling_convention.GetRegisterAt(2), second.AsRegisterPairLow<Register>());
3411      DCHECK_EQ(calling_convention.GetRegisterAt(3), second.AsRegisterPairHigh<Register>());
3412      DCHECK_EQ(EAX, out.AsRegisterPairLow<Register>());
3413      DCHECK_EQ(EDX, out.AsRegisterPairHigh<Register>());
3414
3415      if (is_div) {
3416        codegen_->InvokeRuntime(QUICK_ENTRY_POINT(pLdiv),
3417                                instruction,
3418                                instruction->GetDexPc(),
3419                                nullptr);
3420        CheckEntrypointTypes<kQuickLdiv, int64_t, int64_t, int64_t>();
3421      } else {
3422        codegen_->InvokeRuntime(QUICK_ENTRY_POINT(pLmod),
3423                                instruction,
3424                                instruction->GetDexPc(),
3425                                nullptr);
3426        CheckEntrypointTypes<kQuickLmod, int64_t, int64_t, int64_t>();
3427      }
3428      break;
3429    }
3430
3431    default:
3432      LOG(FATAL) << "Unexpected type for GenerateDivRemIntegral " << instruction->GetResultType();
3433  }
3434}
3435
3436void LocationsBuilderX86::VisitDiv(HDiv* div) {
3437  LocationSummary::CallKind call_kind = (div->GetResultType() == Primitive::kPrimLong)
3438      ? LocationSummary::kCall
3439      : LocationSummary::kNoCall;
3440  LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(div, call_kind);
3441
3442  switch (div->GetResultType()) {
3443    case Primitive::kPrimInt: {
3444      locations->SetInAt(0, Location::RegisterLocation(EAX));
3445      locations->SetInAt(1, Location::RegisterOrConstant(div->InputAt(1)));
3446      locations->SetOut(Location::SameAsFirstInput());
3447      // Intel uses edx:eax as the dividend.
3448      locations->AddTemp(Location::RegisterLocation(EDX));
3449      // We need to save the numerator while we tweak eax and edx. As we are using imul in a way
3450      // which enforces results to be in EAX and EDX, things are simpler if we use EAX also as
3451      // output and request another temp.
3452      if (div->InputAt(1)->IsIntConstant()) {
3453        locations->AddTemp(Location::RequiresRegister());
3454      }
3455      break;
3456    }
3457    case Primitive::kPrimLong: {
3458      InvokeRuntimeCallingConvention calling_convention;
3459      locations->SetInAt(0, Location::RegisterPairLocation(
3460          calling_convention.GetRegisterAt(0), calling_convention.GetRegisterAt(1)));
3461      locations->SetInAt(1, Location::RegisterPairLocation(
3462          calling_convention.GetRegisterAt(2), calling_convention.GetRegisterAt(3)));
3463      // Runtime helper puts the result in EAX, EDX.
3464      locations->SetOut(Location::RegisterPairLocation(EAX, EDX));
3465      break;
3466    }
3467    case Primitive::kPrimFloat:
3468    case Primitive::kPrimDouble: {
3469      locations->SetInAt(0, Location::RequiresFpuRegister());
3470      if (div->InputAt(1)->IsX86LoadFromConstantTable()) {
3471        DCHECK(div->InputAt(1)->IsEmittedAtUseSite());
3472      } else if (div->InputAt(1)->IsConstant()) {
3473        locations->SetInAt(1, Location::RequiresFpuRegister());
3474      } else {
3475        locations->SetInAt(1, Location::Any());
3476      }
3477      locations->SetOut(Location::SameAsFirstInput());
3478      break;
3479    }
3480
3481    default:
3482      LOG(FATAL) << "Unexpected div type " << div->GetResultType();
3483  }
3484}
3485
3486void InstructionCodeGeneratorX86::VisitDiv(HDiv* div) {
3487  LocationSummary* locations = div->GetLocations();
3488  Location first = locations->InAt(0);
3489  Location second = locations->InAt(1);
3490
3491  switch (div->GetResultType()) {
3492    case Primitive::kPrimInt:
3493    case Primitive::kPrimLong: {
3494      GenerateDivRemIntegral(div);
3495      break;
3496    }
3497
3498    case Primitive::kPrimFloat: {
3499      if (second.IsFpuRegister()) {
3500        __ divss(first.AsFpuRegister<XmmRegister>(), second.AsFpuRegister<XmmRegister>());
3501      } else if (div->InputAt(1)->IsX86LoadFromConstantTable()) {
3502        HX86LoadFromConstantTable* const_area = div->InputAt(1)->AsX86LoadFromConstantTable();
3503        DCHECK(const_area->IsEmittedAtUseSite());
3504        __ divss(first.AsFpuRegister<XmmRegister>(),
3505                 codegen_->LiteralFloatAddress(
3506                   const_area->GetConstant()->AsFloatConstant()->GetValue(),
3507                   const_area->GetLocations()->InAt(0).AsRegister<Register>()));
3508      } else {
3509        DCHECK(second.IsStackSlot());
3510        __ divss(first.AsFpuRegister<XmmRegister>(), Address(ESP, second.GetStackIndex()));
3511      }
3512      break;
3513    }
3514
3515    case Primitive::kPrimDouble: {
3516      if (second.IsFpuRegister()) {
3517        __ divsd(first.AsFpuRegister<XmmRegister>(), second.AsFpuRegister<XmmRegister>());
3518      } else if (div->InputAt(1)->IsX86LoadFromConstantTable()) {
3519        HX86LoadFromConstantTable* const_area = div->InputAt(1)->AsX86LoadFromConstantTable();
3520        DCHECK(const_area->IsEmittedAtUseSite());
3521        __ divsd(first.AsFpuRegister<XmmRegister>(),
3522                 codegen_->LiteralDoubleAddress(
3523                   const_area->GetConstant()->AsDoubleConstant()->GetValue(),
3524                   const_area->GetLocations()->InAt(0).AsRegister<Register>()));
3525      } else {
3526        DCHECK(second.IsDoubleStackSlot());
3527        __ divsd(first.AsFpuRegister<XmmRegister>(), Address(ESP, second.GetStackIndex()));
3528      }
3529      break;
3530    }
3531
3532    default:
3533      LOG(FATAL) << "Unexpected div type " << div->GetResultType();
3534  }
3535}
3536
3537void LocationsBuilderX86::VisitRem(HRem* rem) {
3538  Primitive::Type type = rem->GetResultType();
3539
3540  LocationSummary::CallKind call_kind = (rem->GetResultType() == Primitive::kPrimLong)
3541      ? LocationSummary::kCall
3542      : LocationSummary::kNoCall;
3543  LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(rem, call_kind);
3544
3545  switch (type) {
3546    case Primitive::kPrimInt: {
3547      locations->SetInAt(0, Location::RegisterLocation(EAX));
3548      locations->SetInAt(1, Location::RegisterOrConstant(rem->InputAt(1)));
3549      locations->SetOut(Location::RegisterLocation(EDX));
3550      // We need to save the numerator while we tweak eax and edx. As we are using imul in a way
3551      // which enforces results to be in EAX and EDX, things are simpler if we use EDX also as
3552      // output and request another temp.
3553      if (rem->InputAt(1)->IsIntConstant()) {
3554        locations->AddTemp(Location::RequiresRegister());
3555      }
3556      break;
3557    }
3558    case Primitive::kPrimLong: {
3559      InvokeRuntimeCallingConvention calling_convention;
3560      locations->SetInAt(0, Location::RegisterPairLocation(
3561          calling_convention.GetRegisterAt(0), calling_convention.GetRegisterAt(1)));
3562      locations->SetInAt(1, Location::RegisterPairLocation(
3563          calling_convention.GetRegisterAt(2), calling_convention.GetRegisterAt(3)));
3564      // Runtime helper puts the result in EAX, EDX.
3565      locations->SetOut(Location::RegisterPairLocation(EAX, EDX));
3566      break;
3567    }
3568    case Primitive::kPrimDouble:
3569    case Primitive::kPrimFloat: {
3570      locations->SetInAt(0, Location::Any());
3571      locations->SetInAt(1, Location::Any());
3572      locations->SetOut(Location::RequiresFpuRegister());
3573      locations->AddTemp(Location::RegisterLocation(EAX));
3574      break;
3575    }
3576
3577    default:
3578      LOG(FATAL) << "Unexpected rem type " << type;
3579  }
3580}
3581
3582void InstructionCodeGeneratorX86::VisitRem(HRem* rem) {
3583  Primitive::Type type = rem->GetResultType();
3584  switch (type) {
3585    case Primitive::kPrimInt:
3586    case Primitive::kPrimLong: {
3587      GenerateDivRemIntegral(rem);
3588      break;
3589    }
3590    case Primitive::kPrimFloat:
3591    case Primitive::kPrimDouble: {
3592      GenerateRemFP(rem);
3593      break;
3594    }
3595    default:
3596      LOG(FATAL) << "Unexpected rem type " << type;
3597  }
3598}
3599
3600void LocationsBuilderX86::VisitDivZeroCheck(HDivZeroCheck* instruction) {
3601  LocationSummary::CallKind call_kind = instruction->CanThrowIntoCatchBlock()
3602      ? LocationSummary::kCallOnSlowPath
3603      : LocationSummary::kNoCall;
3604  LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, call_kind);
3605  switch (instruction->GetType()) {
3606    case Primitive::kPrimBoolean:
3607    case Primitive::kPrimByte:
3608    case Primitive::kPrimChar:
3609    case Primitive::kPrimShort:
3610    case Primitive::kPrimInt: {
3611      locations->SetInAt(0, Location::Any());
3612      break;
3613    }
3614    case Primitive::kPrimLong: {
3615      locations->SetInAt(0, Location::RegisterOrConstant(instruction->InputAt(0)));
3616      if (!instruction->IsConstant()) {
3617        locations->AddTemp(Location::RequiresRegister());
3618      }
3619      break;
3620    }
3621    default:
3622      LOG(FATAL) << "Unexpected type for HDivZeroCheck " << instruction->GetType();
3623  }
3624  if (instruction->HasUses()) {
3625    locations->SetOut(Location::SameAsFirstInput());
3626  }
3627}
3628
3629void InstructionCodeGeneratorX86::VisitDivZeroCheck(HDivZeroCheck* instruction) {
3630  SlowPathCode* slow_path = new (GetGraph()->GetArena()) DivZeroCheckSlowPathX86(instruction);
3631  codegen_->AddSlowPath(slow_path);
3632
3633  LocationSummary* locations = instruction->GetLocations();
3634  Location value = locations->InAt(0);
3635
3636  switch (instruction->GetType()) {
3637    case Primitive::kPrimBoolean:
3638    case Primitive::kPrimByte:
3639    case Primitive::kPrimChar:
3640    case Primitive::kPrimShort:
3641    case Primitive::kPrimInt: {
3642      if (value.IsRegister()) {
3643        __ testl(value.AsRegister<Register>(), value.AsRegister<Register>());
3644        __ j(kEqual, slow_path->GetEntryLabel());
3645      } else if (value.IsStackSlot()) {
3646        __ cmpl(Address(ESP, value.GetStackIndex()), Immediate(0));
3647        __ j(kEqual, slow_path->GetEntryLabel());
3648      } else {
3649        DCHECK(value.IsConstant()) << value;
3650        if (value.GetConstant()->AsIntConstant()->GetValue() == 0) {
3651        __ jmp(slow_path->GetEntryLabel());
3652        }
3653      }
3654      break;
3655    }
3656    case Primitive::kPrimLong: {
3657      if (value.IsRegisterPair()) {
3658        Register temp = locations->GetTemp(0).AsRegister<Register>();
3659        __ movl(temp, value.AsRegisterPairLow<Register>());
3660        __ orl(temp, value.AsRegisterPairHigh<Register>());
3661        __ j(kEqual, slow_path->GetEntryLabel());
3662      } else {
3663        DCHECK(value.IsConstant()) << value;
3664        if (value.GetConstant()->AsLongConstant()->GetValue() == 0) {
3665          __ jmp(slow_path->GetEntryLabel());
3666        }
3667      }
3668      break;
3669    }
3670    default:
3671      LOG(FATAL) << "Unexpected type for HDivZeroCheck" << instruction->GetType();
3672  }
3673}
3674
3675void LocationsBuilderX86::HandleShift(HBinaryOperation* op) {
3676  DCHECK(op->IsShl() || op->IsShr() || op->IsUShr());
3677
3678  LocationSummary* locations =
3679      new (GetGraph()->GetArena()) LocationSummary(op, LocationSummary::kNoCall);
3680
3681  switch (op->GetResultType()) {
3682    case Primitive::kPrimInt:
3683    case Primitive::kPrimLong: {
3684      // Can't have Location::Any() and output SameAsFirstInput()
3685      locations->SetInAt(0, Location::RequiresRegister());
3686      // The shift count needs to be in CL or a constant.
3687      locations->SetInAt(1, Location::ByteRegisterOrConstant(ECX, op->InputAt(1)));
3688      locations->SetOut(Location::SameAsFirstInput());
3689      break;
3690    }
3691    default:
3692      LOG(FATAL) << "Unexpected op type " << op->GetResultType();
3693  }
3694}
3695
3696void InstructionCodeGeneratorX86::HandleShift(HBinaryOperation* op) {
3697  DCHECK(op->IsShl() || op->IsShr() || op->IsUShr());
3698
3699  LocationSummary* locations = op->GetLocations();
3700  Location first = locations->InAt(0);
3701  Location second = locations->InAt(1);
3702  DCHECK(first.Equals(locations->Out()));
3703
3704  switch (op->GetResultType()) {
3705    case Primitive::kPrimInt: {
3706      DCHECK(first.IsRegister());
3707      Register first_reg = first.AsRegister<Register>();
3708      if (second.IsRegister()) {
3709        Register second_reg = second.AsRegister<Register>();
3710        DCHECK_EQ(ECX, second_reg);
3711        if (op->IsShl()) {
3712          __ shll(first_reg, second_reg);
3713        } else if (op->IsShr()) {
3714          __ sarl(first_reg, second_reg);
3715        } else {
3716          __ shrl(first_reg, second_reg);
3717        }
3718      } else {
3719        int32_t shift = second.GetConstant()->AsIntConstant()->GetValue() & kMaxIntShiftDistance;
3720        if (shift == 0) {
3721          return;
3722        }
3723        Immediate imm(shift);
3724        if (op->IsShl()) {
3725          __ shll(first_reg, imm);
3726        } else if (op->IsShr()) {
3727          __ sarl(first_reg, imm);
3728        } else {
3729          __ shrl(first_reg, imm);
3730        }
3731      }
3732      break;
3733    }
3734    case Primitive::kPrimLong: {
3735      if (second.IsRegister()) {
3736        Register second_reg = second.AsRegister<Register>();
3737        DCHECK_EQ(ECX, second_reg);
3738        if (op->IsShl()) {
3739          GenerateShlLong(first, second_reg);
3740        } else if (op->IsShr()) {
3741          GenerateShrLong(first, second_reg);
3742        } else {
3743          GenerateUShrLong(first, second_reg);
3744        }
3745      } else {
3746        // Shift by a constant.
3747        int32_t shift = second.GetConstant()->AsIntConstant()->GetValue() & kMaxLongShiftDistance;
3748        // Nothing to do if the shift is 0, as the input is already the output.
3749        if (shift != 0) {
3750          if (op->IsShl()) {
3751            GenerateShlLong(first, shift);
3752          } else if (op->IsShr()) {
3753            GenerateShrLong(first, shift);
3754          } else {
3755            GenerateUShrLong(first, shift);
3756          }
3757        }
3758      }
3759      break;
3760    }
3761    default:
3762      LOG(FATAL) << "Unexpected op type " << op->GetResultType();
3763  }
3764}
3765
3766void InstructionCodeGeneratorX86::GenerateShlLong(const Location& loc, int shift) {
3767  Register low = loc.AsRegisterPairLow<Register>();
3768  Register high = loc.AsRegisterPairHigh<Register>();
3769  if (shift == 1) {
3770    // This is just an addition.
3771    __ addl(low, low);
3772    __ adcl(high, high);
3773  } else if (shift == 32) {
3774    // Shift by 32 is easy. High gets low, and low gets 0.
3775    codegen_->EmitParallelMoves(
3776        loc.ToLow(),
3777        loc.ToHigh(),
3778        Primitive::kPrimInt,
3779        Location::ConstantLocation(GetGraph()->GetIntConstant(0)),
3780        loc.ToLow(),
3781        Primitive::kPrimInt);
3782  } else if (shift > 32) {
3783    // Low part becomes 0.  High part is low part << (shift-32).
3784    __ movl(high, low);
3785    __ shll(high, Immediate(shift - 32));
3786    __ xorl(low, low);
3787  } else {
3788    // Between 1 and 31.
3789    __ shld(high, low, Immediate(shift));
3790    __ shll(low, Immediate(shift));
3791  }
3792}
3793
3794void InstructionCodeGeneratorX86::GenerateShlLong(const Location& loc, Register shifter) {
3795  NearLabel done;
3796  __ shld(loc.AsRegisterPairHigh<Register>(), loc.AsRegisterPairLow<Register>(), shifter);
3797  __ shll(loc.AsRegisterPairLow<Register>(), shifter);
3798  __ testl(shifter, Immediate(32));
3799  __ j(kEqual, &done);
3800  __ movl(loc.AsRegisterPairHigh<Register>(), loc.AsRegisterPairLow<Register>());
3801  __ movl(loc.AsRegisterPairLow<Register>(), Immediate(0));
3802  __ Bind(&done);
3803}
3804
3805void InstructionCodeGeneratorX86::GenerateShrLong(const Location& loc, int shift) {
3806  Register low = loc.AsRegisterPairLow<Register>();
3807  Register high = loc.AsRegisterPairHigh<Register>();
3808  if (shift == 32) {
3809    // Need to copy the sign.
3810    DCHECK_NE(low, high);
3811    __ movl(low, high);
3812    __ sarl(high, Immediate(31));
3813  } else if (shift > 32) {
3814    DCHECK_NE(low, high);
3815    // High part becomes sign. Low part is shifted by shift - 32.
3816    __ movl(low, high);
3817    __ sarl(high, Immediate(31));
3818    __ sarl(low, Immediate(shift - 32));
3819  } else {
3820    // Between 1 and 31.
3821    __ shrd(low, high, Immediate(shift));
3822    __ sarl(high, Immediate(shift));
3823  }
3824}
3825
3826void InstructionCodeGeneratorX86::GenerateShrLong(const Location& loc, Register shifter) {
3827  NearLabel done;
3828  __ shrd(loc.AsRegisterPairLow<Register>(), loc.AsRegisterPairHigh<Register>(), shifter);
3829  __ sarl(loc.AsRegisterPairHigh<Register>(), shifter);
3830  __ testl(shifter, Immediate(32));
3831  __ j(kEqual, &done);
3832  __ movl(loc.AsRegisterPairLow<Register>(), loc.AsRegisterPairHigh<Register>());
3833  __ sarl(loc.AsRegisterPairHigh<Register>(), Immediate(31));
3834  __ Bind(&done);
3835}
3836
3837void InstructionCodeGeneratorX86::GenerateUShrLong(const Location& loc, int shift) {
3838  Register low = loc.AsRegisterPairLow<Register>();
3839  Register high = loc.AsRegisterPairHigh<Register>();
3840  if (shift == 32) {
3841    // Shift by 32 is easy. Low gets high, and high gets 0.
3842    codegen_->EmitParallelMoves(
3843        loc.ToHigh(),
3844        loc.ToLow(),
3845        Primitive::kPrimInt,
3846        Location::ConstantLocation(GetGraph()->GetIntConstant(0)),
3847        loc.ToHigh(),
3848        Primitive::kPrimInt);
3849  } else if (shift > 32) {
3850    // Low part is high >> (shift - 32). High part becomes 0.
3851    __ movl(low, high);
3852    __ shrl(low, Immediate(shift - 32));
3853    __ xorl(high, high);
3854  } else {
3855    // Between 1 and 31.
3856    __ shrd(low, high, Immediate(shift));
3857    __ shrl(high, Immediate(shift));
3858  }
3859}
3860
3861void InstructionCodeGeneratorX86::GenerateUShrLong(const Location& loc, Register shifter) {
3862  NearLabel done;
3863  __ shrd(loc.AsRegisterPairLow<Register>(), loc.AsRegisterPairHigh<Register>(), shifter);
3864  __ shrl(loc.AsRegisterPairHigh<Register>(), shifter);
3865  __ testl(shifter, Immediate(32));
3866  __ j(kEqual, &done);
3867  __ movl(loc.AsRegisterPairLow<Register>(), loc.AsRegisterPairHigh<Register>());
3868  __ movl(loc.AsRegisterPairHigh<Register>(), Immediate(0));
3869  __ Bind(&done);
3870}
3871
3872void LocationsBuilderX86::VisitRor(HRor* ror) {
3873  LocationSummary* locations =
3874      new (GetGraph()->GetArena()) LocationSummary(ror, LocationSummary::kNoCall);
3875
3876  switch (ror->GetResultType()) {
3877    case Primitive::kPrimLong:
3878      // Add the temporary needed.
3879      locations->AddTemp(Location::RequiresRegister());
3880      FALLTHROUGH_INTENDED;
3881    case Primitive::kPrimInt:
3882      locations->SetInAt(0, Location::RequiresRegister());
3883      // The shift count needs to be in CL (unless it is a constant).
3884      locations->SetInAt(1, Location::ByteRegisterOrConstant(ECX, ror->InputAt(1)));
3885      locations->SetOut(Location::SameAsFirstInput());
3886      break;
3887    default:
3888      LOG(FATAL) << "Unexpected operation type " << ror->GetResultType();
3889      UNREACHABLE();
3890  }
3891}
3892
3893void InstructionCodeGeneratorX86::VisitRor(HRor* ror) {
3894  LocationSummary* locations = ror->GetLocations();
3895  Location first = locations->InAt(0);
3896  Location second = locations->InAt(1);
3897
3898  if (ror->GetResultType() == Primitive::kPrimInt) {
3899    Register first_reg = first.AsRegister<Register>();
3900    if (second.IsRegister()) {
3901      Register second_reg = second.AsRegister<Register>();
3902      __ rorl(first_reg, second_reg);
3903    } else {
3904      Immediate imm(second.GetConstant()->AsIntConstant()->GetValue() & kMaxIntShiftDistance);
3905      __ rorl(first_reg, imm);
3906    }
3907    return;
3908  }
3909
3910  DCHECK_EQ(ror->GetResultType(), Primitive::kPrimLong);
3911  Register first_reg_lo = first.AsRegisterPairLow<Register>();
3912  Register first_reg_hi = first.AsRegisterPairHigh<Register>();
3913  Register temp_reg = locations->GetTemp(0).AsRegister<Register>();
3914  if (second.IsRegister()) {
3915    Register second_reg = second.AsRegister<Register>();
3916    DCHECK_EQ(second_reg, ECX);
3917    __ movl(temp_reg, first_reg_hi);
3918    __ shrd(first_reg_hi, first_reg_lo, second_reg);
3919    __ shrd(first_reg_lo, temp_reg, second_reg);
3920    __ movl(temp_reg, first_reg_hi);
3921    __ testl(second_reg, Immediate(32));
3922    __ cmovl(kNotEqual, first_reg_hi, first_reg_lo);
3923    __ cmovl(kNotEqual, first_reg_lo, temp_reg);
3924  } else {
3925    int32_t shift_amt = second.GetConstant()->AsIntConstant()->GetValue() & kMaxLongShiftDistance;
3926    if (shift_amt == 0) {
3927      // Already fine.
3928      return;
3929    }
3930    if (shift_amt == 32) {
3931      // Just swap.
3932      __ movl(temp_reg, first_reg_lo);
3933      __ movl(first_reg_lo, first_reg_hi);
3934      __ movl(first_reg_hi, temp_reg);
3935      return;
3936    }
3937
3938    Immediate imm(shift_amt);
3939    // Save the constents of the low value.
3940    __ movl(temp_reg, first_reg_lo);
3941
3942    // Shift right into low, feeding bits from high.
3943    __ shrd(first_reg_lo, first_reg_hi, imm);
3944
3945    // Shift right into high, feeding bits from the original low.
3946    __ shrd(first_reg_hi, temp_reg, imm);
3947
3948    // Swap if needed.
3949    if (shift_amt > 32) {
3950      __ movl(temp_reg, first_reg_lo);
3951      __ movl(first_reg_lo, first_reg_hi);
3952      __ movl(first_reg_hi, temp_reg);
3953    }
3954  }
3955}
3956
3957void LocationsBuilderX86::VisitShl(HShl* shl) {
3958  HandleShift(shl);
3959}
3960
3961void InstructionCodeGeneratorX86::VisitShl(HShl* shl) {
3962  HandleShift(shl);
3963}
3964
3965void LocationsBuilderX86::VisitShr(HShr* shr) {
3966  HandleShift(shr);
3967}
3968
3969void InstructionCodeGeneratorX86::VisitShr(HShr* shr) {
3970  HandleShift(shr);
3971}
3972
3973void LocationsBuilderX86::VisitUShr(HUShr* ushr) {
3974  HandleShift(ushr);
3975}
3976
3977void InstructionCodeGeneratorX86::VisitUShr(HUShr* ushr) {
3978  HandleShift(ushr);
3979}
3980
3981void LocationsBuilderX86::VisitNewInstance(HNewInstance* instruction) {
3982  LocationSummary* locations =
3983      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCall);
3984  locations->SetOut(Location::RegisterLocation(EAX));
3985  if (instruction->IsStringAlloc()) {
3986    locations->AddTemp(Location::RegisterLocation(kMethodRegisterArgument));
3987  } else {
3988    InvokeRuntimeCallingConvention calling_convention;
3989    locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0)));
3990    locations->SetInAt(1, Location::RegisterLocation(calling_convention.GetRegisterAt(1)));
3991  }
3992}
3993
3994void InstructionCodeGeneratorX86::VisitNewInstance(HNewInstance* instruction) {
3995  // Note: if heap poisoning is enabled, the entry point takes cares
3996  // of poisoning the reference.
3997  if (instruction->IsStringAlloc()) {
3998    // String is allocated through StringFactory. Call NewEmptyString entry point.
3999    Register temp = instruction->GetLocations()->GetTemp(0).AsRegister<Register>();
4000    MemberOffset code_offset = ArtMethod::EntryPointFromQuickCompiledCodeOffset(kX86WordSize);
4001    __ fs()->movl(temp, Address::Absolute(QUICK_ENTRY_POINT(pNewEmptyString)));
4002    __ call(Address(temp, code_offset.Int32Value()));
4003    codegen_->RecordPcInfo(instruction, instruction->GetDexPc());
4004  } else {
4005    codegen_->InvokeRuntime(instruction->GetEntrypoint(),
4006                            instruction,
4007                            instruction->GetDexPc(),
4008                            nullptr);
4009    CheckEntrypointTypes<kQuickAllocObjectWithAccessCheck, void*, uint32_t, ArtMethod*>();
4010    DCHECK(!codegen_->IsLeafMethod());
4011  }
4012}
4013
4014void LocationsBuilderX86::VisitNewArray(HNewArray* instruction) {
4015  LocationSummary* locations =
4016      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCall);
4017  locations->SetOut(Location::RegisterLocation(EAX));
4018  InvokeRuntimeCallingConvention calling_convention;
4019  locations->AddTemp(Location::RegisterLocation(calling_convention.GetRegisterAt(0)));
4020  locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(1)));
4021  locations->SetInAt(1, Location::RegisterLocation(calling_convention.GetRegisterAt(2)));
4022}
4023
4024void InstructionCodeGeneratorX86::VisitNewArray(HNewArray* instruction) {
4025  InvokeRuntimeCallingConvention calling_convention;
4026  __ movl(calling_convention.GetRegisterAt(0), Immediate(instruction->GetTypeIndex()));
4027  // Note: if heap poisoning is enabled, the entry point takes cares
4028  // of poisoning the reference.
4029  codegen_->InvokeRuntime(instruction->GetEntrypoint(),
4030                          instruction,
4031                          instruction->GetDexPc(),
4032                          nullptr);
4033  CheckEntrypointTypes<kQuickAllocArrayWithAccessCheck, void*, uint32_t, int32_t, ArtMethod*>();
4034  DCHECK(!codegen_->IsLeafMethod());
4035}
4036
4037void LocationsBuilderX86::VisitParameterValue(HParameterValue* instruction) {
4038  LocationSummary* locations =
4039      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
4040  Location location = parameter_visitor_.GetNextLocation(instruction->GetType());
4041  if (location.IsStackSlot()) {
4042    location = Location::StackSlot(location.GetStackIndex() + codegen_->GetFrameSize());
4043  } else if (location.IsDoubleStackSlot()) {
4044    location = Location::DoubleStackSlot(location.GetStackIndex() + codegen_->GetFrameSize());
4045  }
4046  locations->SetOut(location);
4047}
4048
4049void InstructionCodeGeneratorX86::VisitParameterValue(
4050    HParameterValue* instruction ATTRIBUTE_UNUSED) {
4051}
4052
4053void LocationsBuilderX86::VisitCurrentMethod(HCurrentMethod* instruction) {
4054  LocationSummary* locations =
4055      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
4056  locations->SetOut(Location::RegisterLocation(kMethodRegisterArgument));
4057}
4058
4059void InstructionCodeGeneratorX86::VisitCurrentMethod(HCurrentMethod* instruction ATTRIBUTE_UNUSED) {
4060}
4061
4062void LocationsBuilderX86::VisitClassTableGet(HClassTableGet* instruction) {
4063  LocationSummary* locations =
4064      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
4065  locations->SetInAt(0, Location::RequiresRegister());
4066  locations->SetOut(Location::RequiresRegister());
4067}
4068
4069void InstructionCodeGeneratorX86::VisitClassTableGet(HClassTableGet* instruction) {
4070  LocationSummary* locations = instruction->GetLocations();
4071  if (instruction->GetTableKind() == HClassTableGet::TableKind::kVTable) {
4072    uint32_t method_offset = mirror::Class::EmbeddedVTableEntryOffset(
4073        instruction->GetIndex(), kX86PointerSize).SizeValue();
4074    __ movl(locations->Out().AsRegister<Register>(),
4075            Address(locations->InAt(0).AsRegister<Register>(), method_offset));
4076  } else {
4077    uint32_t method_offset = static_cast<uint32_t>(ImTable::OffsetOfElement(
4078        instruction->GetIndex() % ImTable::kSize, kX86PointerSize));
4079    __ movl(locations->Out().AsRegister<Register>(),
4080            Address(locations->InAt(0).AsRegister<Register>(),
4081                    mirror::Class::ImtPtrOffset(kX86PointerSize).Uint32Value()));
4082    // temp = temp->GetImtEntryAt(method_offset);
4083    __ movl(locations->Out().AsRegister<Register>(),
4084            Address(locations->Out().AsRegister<Register>(), method_offset));
4085  }
4086}
4087
4088void LocationsBuilderX86::VisitNot(HNot* not_) {
4089  LocationSummary* locations =
4090      new (GetGraph()->GetArena()) LocationSummary(not_, LocationSummary::kNoCall);
4091  locations->SetInAt(0, Location::RequiresRegister());
4092  locations->SetOut(Location::SameAsFirstInput());
4093}
4094
4095void InstructionCodeGeneratorX86::VisitNot(HNot* not_) {
4096  LocationSummary* locations = not_->GetLocations();
4097  Location in = locations->InAt(0);
4098  Location out = locations->Out();
4099  DCHECK(in.Equals(out));
4100  switch (not_->GetResultType()) {
4101    case Primitive::kPrimInt:
4102      __ notl(out.AsRegister<Register>());
4103      break;
4104
4105    case Primitive::kPrimLong:
4106      __ notl(out.AsRegisterPairLow<Register>());
4107      __ notl(out.AsRegisterPairHigh<Register>());
4108      break;
4109
4110    default:
4111      LOG(FATAL) << "Unimplemented type for not operation " << not_->GetResultType();
4112  }
4113}
4114
4115void LocationsBuilderX86::VisitBooleanNot(HBooleanNot* bool_not) {
4116  LocationSummary* locations =
4117      new (GetGraph()->GetArena()) LocationSummary(bool_not, LocationSummary::kNoCall);
4118  locations->SetInAt(0, Location::RequiresRegister());
4119  locations->SetOut(Location::SameAsFirstInput());
4120}
4121
4122void InstructionCodeGeneratorX86::VisitBooleanNot(HBooleanNot* bool_not) {
4123  LocationSummary* locations = bool_not->GetLocations();
4124  Location in = locations->InAt(0);
4125  Location out = locations->Out();
4126  DCHECK(in.Equals(out));
4127  __ xorl(out.AsRegister<Register>(), Immediate(1));
4128}
4129
4130void LocationsBuilderX86::VisitCompare(HCompare* compare) {
4131  LocationSummary* locations =
4132      new (GetGraph()->GetArena()) LocationSummary(compare, LocationSummary::kNoCall);
4133  switch (compare->InputAt(0)->GetType()) {
4134    case Primitive::kPrimBoolean:
4135    case Primitive::kPrimByte:
4136    case Primitive::kPrimShort:
4137    case Primitive::kPrimChar:
4138    case Primitive::kPrimInt:
4139    case Primitive::kPrimLong: {
4140      locations->SetInAt(0, Location::RequiresRegister());
4141      locations->SetInAt(1, Location::Any());
4142      locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
4143      break;
4144    }
4145    case Primitive::kPrimFloat:
4146    case Primitive::kPrimDouble: {
4147      locations->SetInAt(0, Location::RequiresFpuRegister());
4148      if (compare->InputAt(1)->IsX86LoadFromConstantTable()) {
4149        DCHECK(compare->InputAt(1)->IsEmittedAtUseSite());
4150      } else if (compare->InputAt(1)->IsConstant()) {
4151        locations->SetInAt(1, Location::RequiresFpuRegister());
4152      } else {
4153        locations->SetInAt(1, Location::Any());
4154      }
4155      locations->SetOut(Location::RequiresRegister());
4156      break;
4157    }
4158    default:
4159      LOG(FATAL) << "Unexpected type for compare operation " << compare->InputAt(0)->GetType();
4160  }
4161}
4162
4163void InstructionCodeGeneratorX86::VisitCompare(HCompare* compare) {
4164  LocationSummary* locations = compare->GetLocations();
4165  Register out = locations->Out().AsRegister<Register>();
4166  Location left = locations->InAt(0);
4167  Location right = locations->InAt(1);
4168
4169  NearLabel less, greater, done;
4170  Condition less_cond = kLess;
4171
4172  switch (compare->InputAt(0)->GetType()) {
4173    case Primitive::kPrimBoolean:
4174    case Primitive::kPrimByte:
4175    case Primitive::kPrimShort:
4176    case Primitive::kPrimChar:
4177    case Primitive::kPrimInt: {
4178      GenerateIntCompare(left, right);
4179      break;
4180    }
4181    case Primitive::kPrimLong: {
4182      Register left_low = left.AsRegisterPairLow<Register>();
4183      Register left_high = left.AsRegisterPairHigh<Register>();
4184      int32_t val_low = 0;
4185      int32_t val_high = 0;
4186      bool right_is_const = false;
4187
4188      if (right.IsConstant()) {
4189        DCHECK(right.GetConstant()->IsLongConstant());
4190        right_is_const = true;
4191        int64_t val = right.GetConstant()->AsLongConstant()->GetValue();
4192        val_low = Low32Bits(val);
4193        val_high = High32Bits(val);
4194      }
4195
4196      if (right.IsRegisterPair()) {
4197        __ cmpl(left_high, right.AsRegisterPairHigh<Register>());
4198      } else if (right.IsDoubleStackSlot()) {
4199        __ cmpl(left_high, Address(ESP, right.GetHighStackIndex(kX86WordSize)));
4200      } else {
4201        DCHECK(right_is_const) << right;
4202        codegen_->Compare32BitValue(left_high, val_high);
4203      }
4204      __ j(kLess, &less);  // Signed compare.
4205      __ j(kGreater, &greater);  // Signed compare.
4206      if (right.IsRegisterPair()) {
4207        __ cmpl(left_low, right.AsRegisterPairLow<Register>());
4208      } else if (right.IsDoubleStackSlot()) {
4209        __ cmpl(left_low, Address(ESP, right.GetStackIndex()));
4210      } else {
4211        DCHECK(right_is_const) << right;
4212        codegen_->Compare32BitValue(left_low, val_low);
4213      }
4214      less_cond = kBelow;  // for CF (unsigned).
4215      break;
4216    }
4217    case Primitive::kPrimFloat: {
4218      GenerateFPCompare(left, right, compare, false);
4219      __ j(kUnordered, compare->IsGtBias() ? &greater : &less);
4220      less_cond = kBelow;  // for CF (floats).
4221      break;
4222    }
4223    case Primitive::kPrimDouble: {
4224      GenerateFPCompare(left, right, compare, true);
4225      __ j(kUnordered, compare->IsGtBias() ? &greater : &less);
4226      less_cond = kBelow;  // for CF (floats).
4227      break;
4228    }
4229    default:
4230      LOG(FATAL) << "Unexpected type for compare operation " << compare->InputAt(0)->GetType();
4231  }
4232
4233  __ movl(out, Immediate(0));
4234  __ j(kEqual, &done);
4235  __ j(less_cond, &less);
4236
4237  __ Bind(&greater);
4238  __ movl(out, Immediate(1));
4239  __ jmp(&done);
4240
4241  __ Bind(&less);
4242  __ movl(out, Immediate(-1));
4243
4244  __ Bind(&done);
4245}
4246
4247void LocationsBuilderX86::VisitPhi(HPhi* instruction) {
4248  LocationSummary* locations =
4249      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
4250  for (size_t i = 0, e = instruction->InputCount(); i < e; ++i) {
4251    locations->SetInAt(i, Location::Any());
4252  }
4253  locations->SetOut(Location::Any());
4254}
4255
4256void InstructionCodeGeneratorX86::VisitPhi(HPhi* instruction ATTRIBUTE_UNUSED) {
4257  LOG(FATAL) << "Unreachable";
4258}
4259
4260void CodeGeneratorX86::GenerateMemoryBarrier(MemBarrierKind kind) {
4261  /*
4262   * According to the JSR-133 Cookbook, for x86 only StoreLoad/AnyAny barriers need memory fence.
4263   * All other barriers (LoadAny, AnyStore, StoreStore) are nops due to the x86 memory model.
4264   * For those cases, all we need to ensure is that there is a scheduling barrier in place.
4265   */
4266  switch (kind) {
4267    case MemBarrierKind::kAnyAny: {
4268      MemoryFence();
4269      break;
4270    }
4271    case MemBarrierKind::kAnyStore:
4272    case MemBarrierKind::kLoadAny:
4273    case MemBarrierKind::kStoreStore: {
4274      // nop
4275      break;
4276    }
4277    default:
4278      LOG(FATAL) << "Unexpected memory barrier " << kind;
4279  }
4280}
4281
4282HInvokeStaticOrDirect::DispatchInfo CodeGeneratorX86::GetSupportedInvokeStaticOrDirectDispatch(
4283      const HInvokeStaticOrDirect::DispatchInfo& desired_dispatch_info,
4284      MethodReference target_method ATTRIBUTE_UNUSED) {
4285  HInvokeStaticOrDirect::DispatchInfo dispatch_info = desired_dispatch_info;
4286
4287  // We disable pc-relative load when there is an irreducible loop, as the optimization
4288  // is incompatible with it.
4289  // TODO: Create as many X86ComputeBaseMethodAddress instructions
4290  // as needed for methods with irreducible loops.
4291  if (GetGraph()->HasIrreducibleLoops() &&
4292      (dispatch_info.method_load_kind ==
4293          HInvokeStaticOrDirect::MethodLoadKind::kDexCachePcRelative)) {
4294    dispatch_info.method_load_kind = HInvokeStaticOrDirect::MethodLoadKind::kDexCacheViaMethod;
4295  }
4296  switch (dispatch_info.code_ptr_location) {
4297    case HInvokeStaticOrDirect::CodePtrLocation::kCallDirectWithFixup:
4298    case HInvokeStaticOrDirect::CodePtrLocation::kCallDirect:
4299      // For direct code, we actually prefer to call via the code pointer from ArtMethod*.
4300      // (Though the direct CALL ptr16:32 is available for consideration).
4301      return HInvokeStaticOrDirect::DispatchInfo {
4302        dispatch_info.method_load_kind,
4303        HInvokeStaticOrDirect::CodePtrLocation::kCallArtMethod,
4304        dispatch_info.method_load_data,
4305        0u
4306      };
4307    default:
4308      return dispatch_info;
4309  }
4310}
4311
4312Register CodeGeneratorX86::GetInvokeStaticOrDirectExtraParameter(HInvokeStaticOrDirect* invoke,
4313                                                                 Register temp) {
4314  DCHECK_EQ(invoke->InputCount(), invoke->GetNumberOfArguments() + 1u);
4315  Location location = invoke->GetLocations()->InAt(invoke->GetSpecialInputIndex());
4316  if (!invoke->GetLocations()->Intrinsified()) {
4317    return location.AsRegister<Register>();
4318  }
4319  // For intrinsics we allow any location, so it may be on the stack.
4320  if (!location.IsRegister()) {
4321    __ movl(temp, Address(ESP, location.GetStackIndex()));
4322    return temp;
4323  }
4324  // For register locations, check if the register was saved. If so, get it from the stack.
4325  // Note: There is a chance that the register was saved but not overwritten, so we could
4326  // save one load. However, since this is just an intrinsic slow path we prefer this
4327  // simple and more robust approach rather that trying to determine if that's the case.
4328  SlowPathCode* slow_path = GetCurrentSlowPath();
4329  DCHECK(slow_path != nullptr);  // For intrinsified invokes the call is emitted on the slow path.
4330  if (slow_path->IsCoreRegisterSaved(location.AsRegister<Register>())) {
4331    int stack_offset = slow_path->GetStackOffsetOfCoreRegister(location.AsRegister<Register>());
4332    __ movl(temp, Address(ESP, stack_offset));
4333    return temp;
4334  }
4335  return location.AsRegister<Register>();
4336}
4337
4338void CodeGeneratorX86::GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, Location temp) {
4339  Location callee_method = temp;  // For all kinds except kRecursive, callee will be in temp.
4340  switch (invoke->GetMethodLoadKind()) {
4341    case HInvokeStaticOrDirect::MethodLoadKind::kStringInit:
4342      // temp = thread->string_init_entrypoint
4343      __ fs()->movl(temp.AsRegister<Register>(), Address::Absolute(invoke->GetStringInitOffset()));
4344      break;
4345    case HInvokeStaticOrDirect::MethodLoadKind::kRecursive:
4346      callee_method = invoke->GetLocations()->InAt(invoke->GetSpecialInputIndex());
4347      break;
4348    case HInvokeStaticOrDirect::MethodLoadKind::kDirectAddress:
4349      __ movl(temp.AsRegister<Register>(), Immediate(invoke->GetMethodAddress()));
4350      break;
4351    case HInvokeStaticOrDirect::MethodLoadKind::kDirectAddressWithFixup:
4352      __ movl(temp.AsRegister<Register>(), Immediate(/* placeholder */ 0));
4353      method_patches_.emplace_back(invoke->GetTargetMethod());
4354      __ Bind(&method_patches_.back().label);  // Bind the label at the end of the "movl" insn.
4355      break;
4356    case HInvokeStaticOrDirect::MethodLoadKind::kDexCachePcRelative: {
4357      Register base_reg = GetInvokeStaticOrDirectExtraParameter(invoke,
4358                                                                temp.AsRegister<Register>());
4359      __ movl(temp.AsRegister<Register>(), Address(base_reg, kDummy32BitOffset));
4360      // Bind a new fixup label at the end of the "movl" insn.
4361      uint32_t offset = invoke->GetDexCacheArrayOffset();
4362      __ Bind(NewPcRelativeDexCacheArrayPatch(*invoke->GetTargetMethod().dex_file, offset));
4363      break;
4364    }
4365    case HInvokeStaticOrDirect::MethodLoadKind::kDexCacheViaMethod: {
4366      Location current_method = invoke->GetLocations()->InAt(invoke->GetSpecialInputIndex());
4367      Register method_reg;
4368      Register reg = temp.AsRegister<Register>();
4369      if (current_method.IsRegister()) {
4370        method_reg = current_method.AsRegister<Register>();
4371      } else {
4372        DCHECK(invoke->GetLocations()->Intrinsified());
4373        DCHECK(!current_method.IsValid());
4374        method_reg = reg;
4375        __ movl(reg, Address(ESP, kCurrentMethodStackOffset));
4376      }
4377      // /* ArtMethod*[] */ temp = temp.ptr_sized_fields_->dex_cache_resolved_methods_;
4378      __ movl(reg, Address(method_reg,
4379                           ArtMethod::DexCacheResolvedMethodsOffset(kX86PointerSize).Int32Value()));
4380      // temp = temp[index_in_cache];
4381      // Note: Don't use invoke->GetTargetMethod() as it may point to a different dex file.
4382      uint32_t index_in_cache = invoke->GetDexMethodIndex();
4383      __ movl(reg, Address(reg, CodeGenerator::GetCachePointerOffset(index_in_cache)));
4384      break;
4385    }
4386  }
4387
4388  switch (invoke->GetCodePtrLocation()) {
4389    case HInvokeStaticOrDirect::CodePtrLocation::kCallSelf:
4390      __ call(GetFrameEntryLabel());
4391      break;
4392    case HInvokeStaticOrDirect::CodePtrLocation::kCallPCRelative: {
4393      relative_call_patches_.emplace_back(invoke->GetTargetMethod());
4394      Label* label = &relative_call_patches_.back().label;
4395      __ call(label);  // Bind to the patch label, override at link time.
4396      __ Bind(label);  // Bind the label at the end of the "call" insn.
4397      break;
4398    }
4399    case HInvokeStaticOrDirect::CodePtrLocation::kCallDirectWithFixup:
4400    case HInvokeStaticOrDirect::CodePtrLocation::kCallDirect:
4401      // Filtered out by GetSupportedInvokeStaticOrDirectDispatch().
4402      LOG(FATAL) << "Unsupported";
4403      UNREACHABLE();
4404    case HInvokeStaticOrDirect::CodePtrLocation::kCallArtMethod:
4405      // (callee_method + offset_of_quick_compiled_code)()
4406      __ call(Address(callee_method.AsRegister<Register>(),
4407                      ArtMethod::EntryPointFromQuickCompiledCodeOffset(
4408                          kX86WordSize).Int32Value()));
4409      break;
4410  }
4411
4412  DCHECK(!IsLeafMethod());
4413}
4414
4415void CodeGeneratorX86::GenerateVirtualCall(HInvokeVirtual* invoke, Location temp_in) {
4416  Register temp = temp_in.AsRegister<Register>();
4417  uint32_t method_offset = mirror::Class::EmbeddedVTableEntryOffset(
4418      invoke->GetVTableIndex(), kX86PointerSize).Uint32Value();
4419
4420  // Use the calling convention instead of the location of the receiver, as
4421  // intrinsics may have put the receiver in a different register. In the intrinsics
4422  // slow path, the arguments have been moved to the right place, so here we are
4423  // guaranteed that the receiver is the first register of the calling convention.
4424  InvokeDexCallingConvention calling_convention;
4425  Register receiver = calling_convention.GetRegisterAt(0);
4426  uint32_t class_offset = mirror::Object::ClassOffset().Int32Value();
4427  // /* HeapReference<Class> */ temp = receiver->klass_
4428  __ movl(temp, Address(receiver, class_offset));
4429  MaybeRecordImplicitNullCheck(invoke);
4430  // Instead of simply (possibly) unpoisoning `temp` here, we should
4431  // emit a read barrier for the previous class reference load.
4432  // However this is not required in practice, as this is an
4433  // intermediate/temporary reference and because the current
4434  // concurrent copying collector keeps the from-space memory
4435  // intact/accessible until the end of the marking phase (the
4436  // concurrent copying collector may not in the future).
4437  __ MaybeUnpoisonHeapReference(temp);
4438  // temp = temp->GetMethodAt(method_offset);
4439  __ movl(temp, Address(temp, method_offset));
4440  // call temp->GetEntryPoint();
4441  __ call(Address(
4442      temp, ArtMethod::EntryPointFromQuickCompiledCodeOffset(kX86WordSize).Int32Value()));
4443}
4444
4445void CodeGeneratorX86::RecordSimplePatch() {
4446  if (GetCompilerOptions().GetIncludePatchInformation()) {
4447    simple_patches_.emplace_back();
4448    __ Bind(&simple_patches_.back());
4449  }
4450}
4451
4452void CodeGeneratorX86::RecordStringPatch(HLoadString* load_string) {
4453  string_patches_.emplace_back(load_string->GetDexFile(), load_string->GetStringIndex());
4454  __ Bind(&string_patches_.back().label);
4455}
4456
4457Label* CodeGeneratorX86::NewPcRelativeDexCacheArrayPatch(const DexFile& dex_file,
4458                                                         uint32_t element_offset) {
4459  // Add the patch entry and bind its label at the end of the instruction.
4460  pc_relative_dex_cache_patches_.emplace_back(dex_file, element_offset);
4461  return &pc_relative_dex_cache_patches_.back().label;
4462}
4463
4464void CodeGeneratorX86::EmitLinkerPatches(ArenaVector<LinkerPatch>* linker_patches) {
4465  DCHECK(linker_patches->empty());
4466  size_t size =
4467      method_patches_.size() +
4468      relative_call_patches_.size() +
4469      pc_relative_dex_cache_patches_.size() +
4470      simple_patches_.size() +
4471      string_patches_.size();
4472  linker_patches->reserve(size);
4473  // The label points to the end of the "movl" insn but the literal offset for method
4474  // patch needs to point to the embedded constant which occupies the last 4 bytes.
4475  constexpr uint32_t kLabelPositionToLiteralOffsetAdjustment = 4u;
4476  for (const MethodPatchInfo<Label>& info : method_patches_) {
4477    uint32_t literal_offset = info.label.Position() - kLabelPositionToLiteralOffsetAdjustment;
4478    linker_patches->push_back(LinkerPatch::MethodPatch(literal_offset,
4479                                                       info.target_method.dex_file,
4480                                                       info.target_method.dex_method_index));
4481  }
4482  for (const MethodPatchInfo<Label>& info : relative_call_patches_) {
4483    uint32_t literal_offset = info.label.Position() - kLabelPositionToLiteralOffsetAdjustment;
4484    linker_patches->push_back(LinkerPatch::RelativeCodePatch(literal_offset,
4485                                                             info.target_method.dex_file,
4486                                                             info.target_method.dex_method_index));
4487  }
4488  for (const PcRelativeDexCacheAccessInfo& info : pc_relative_dex_cache_patches_) {
4489    uint32_t literal_offset = info.label.Position() - kLabelPositionToLiteralOffsetAdjustment;
4490    linker_patches->push_back(LinkerPatch::DexCacheArrayPatch(literal_offset,
4491                                                              &info.target_dex_file,
4492                                                              GetMethodAddressOffset(),
4493                                                              info.element_offset));
4494  }
4495  for (const Label& label : simple_patches_) {
4496    uint32_t literal_offset = label.Position() - kLabelPositionToLiteralOffsetAdjustment;
4497    linker_patches->push_back(LinkerPatch::RecordPosition(literal_offset));
4498  }
4499  if (GetCompilerOptions().GetCompilePic()) {
4500    for (const StringPatchInfo<Label>& info : string_patches_) {
4501      uint32_t literal_offset = info.label.Position() - kLabelPositionToLiteralOffsetAdjustment;
4502      linker_patches->push_back(LinkerPatch::RelativeStringPatch(literal_offset,
4503                                                                 &info.dex_file,
4504                                                                 GetMethodAddressOffset(),
4505                                                                 info.string_index));
4506    }
4507  } else {
4508    for (const StringPatchInfo<Label>& info : string_patches_) {
4509      uint32_t literal_offset = info.label.Position() - kLabelPositionToLiteralOffsetAdjustment;
4510      linker_patches->push_back(LinkerPatch::StringPatch(literal_offset,
4511                                                         &info.dex_file,
4512                                                         info.string_index));
4513    }
4514  }
4515}
4516
4517void CodeGeneratorX86::MarkGCCard(Register temp,
4518                                  Register card,
4519                                  Register object,
4520                                  Register value,
4521                                  bool value_can_be_null) {
4522  NearLabel is_null;
4523  if (value_can_be_null) {
4524    __ testl(value, value);
4525    __ j(kEqual, &is_null);
4526  }
4527  __ fs()->movl(card, Address::Absolute(Thread::CardTableOffset<kX86WordSize>().Int32Value()));
4528  __ movl(temp, object);
4529  __ shrl(temp, Immediate(gc::accounting::CardTable::kCardShift));
4530  __ movb(Address(temp, card, TIMES_1, 0),
4531          X86ManagedRegister::FromCpuRegister(card).AsByteRegister());
4532  if (value_can_be_null) {
4533    __ Bind(&is_null);
4534  }
4535}
4536
4537void LocationsBuilderX86::HandleFieldGet(HInstruction* instruction, const FieldInfo& field_info) {
4538  DCHECK(instruction->IsInstanceFieldGet() || instruction->IsStaticFieldGet());
4539
4540  bool object_field_get_with_read_barrier =
4541      kEmitCompilerReadBarrier && (instruction->GetType() == Primitive::kPrimNot);
4542  LocationSummary* locations =
4543      new (GetGraph()->GetArena()) LocationSummary(instruction,
4544                                                   kEmitCompilerReadBarrier ?
4545                                                       LocationSummary::kCallOnSlowPath :
4546                                                       LocationSummary::kNoCall);
4547  locations->SetInAt(0, Location::RequiresRegister());
4548
4549  if (Primitive::IsFloatingPointType(instruction->GetType())) {
4550    locations->SetOut(Location::RequiresFpuRegister());
4551  } else {
4552    // The output overlaps in case of long: we don't want the low move
4553    // to overwrite the object's location.  Likewise, in the case of
4554    // an object field get with read barriers enabled, we do not want
4555    // the move to overwrite the object's location, as we need it to emit
4556    // the read barrier.
4557    locations->SetOut(
4558        Location::RequiresRegister(),
4559        (object_field_get_with_read_barrier || instruction->GetType() == Primitive::kPrimLong) ?
4560            Location::kOutputOverlap :
4561            Location::kNoOutputOverlap);
4562  }
4563
4564  if (field_info.IsVolatile() && (field_info.GetFieldType() == Primitive::kPrimLong)) {
4565    // Long values can be loaded atomically into an XMM using movsd.
4566    // So we use an XMM register as a temp to achieve atomicity (first
4567    // load the temp into the XMM and then copy the XMM into the
4568    // output, 32 bits at a time).
4569    locations->AddTemp(Location::RequiresFpuRegister());
4570  } else if (object_field_get_with_read_barrier && kUseBakerReadBarrier) {
4571    // We need a temporary register for the read barrier marking slow
4572    // path in CodeGeneratorX86::GenerateFieldLoadWithBakerReadBarrier.
4573    locations->AddTemp(Location::RequiresRegister());
4574  }
4575}
4576
4577void InstructionCodeGeneratorX86::HandleFieldGet(HInstruction* instruction,
4578                                                 const FieldInfo& field_info) {
4579  DCHECK(instruction->IsInstanceFieldGet() || instruction->IsStaticFieldGet());
4580
4581  LocationSummary* locations = instruction->GetLocations();
4582  Location base_loc = locations->InAt(0);
4583  Register base = base_loc.AsRegister<Register>();
4584  Location out = locations->Out();
4585  bool is_volatile = field_info.IsVolatile();
4586  Primitive::Type field_type = field_info.GetFieldType();
4587  uint32_t offset = field_info.GetFieldOffset().Uint32Value();
4588
4589  switch (field_type) {
4590    case Primitive::kPrimBoolean: {
4591      __ movzxb(out.AsRegister<Register>(), Address(base, offset));
4592      break;
4593    }
4594
4595    case Primitive::kPrimByte: {
4596      __ movsxb(out.AsRegister<Register>(), Address(base, offset));
4597      break;
4598    }
4599
4600    case Primitive::kPrimShort: {
4601      __ movsxw(out.AsRegister<Register>(), Address(base, offset));
4602      break;
4603    }
4604
4605    case Primitive::kPrimChar: {
4606      __ movzxw(out.AsRegister<Register>(), Address(base, offset));
4607      break;
4608    }
4609
4610    case Primitive::kPrimInt:
4611      __ movl(out.AsRegister<Register>(), Address(base, offset));
4612      break;
4613
4614    case Primitive::kPrimNot: {
4615      // /* HeapReference<Object> */ out = *(base + offset)
4616      if (kEmitCompilerReadBarrier && kUseBakerReadBarrier) {
4617        Location temp_loc = locations->GetTemp(0);
4618        // Note that a potential implicit null check is handled in this
4619        // CodeGeneratorX86::GenerateFieldLoadWithBakerReadBarrier call.
4620        codegen_->GenerateFieldLoadWithBakerReadBarrier(
4621            instruction, out, base, offset, temp_loc, /* needs_null_check */ true);
4622        if (is_volatile) {
4623          codegen_->GenerateMemoryBarrier(MemBarrierKind::kLoadAny);
4624        }
4625      } else {
4626        __ movl(out.AsRegister<Register>(), Address(base, offset));
4627        codegen_->MaybeRecordImplicitNullCheck(instruction);
4628        if (is_volatile) {
4629          codegen_->GenerateMemoryBarrier(MemBarrierKind::kLoadAny);
4630        }
4631        // If read barriers are enabled, emit read barriers other than
4632        // Baker's using a slow path (and also unpoison the loaded
4633        // reference, if heap poisoning is enabled).
4634        codegen_->MaybeGenerateReadBarrierSlow(instruction, out, out, base_loc, offset);
4635      }
4636      break;
4637    }
4638
4639    case Primitive::kPrimLong: {
4640      if (is_volatile) {
4641        XmmRegister temp = locations->GetTemp(0).AsFpuRegister<XmmRegister>();
4642        __ movsd(temp, Address(base, offset));
4643        codegen_->MaybeRecordImplicitNullCheck(instruction);
4644        __ movd(out.AsRegisterPairLow<Register>(), temp);
4645        __ psrlq(temp, Immediate(32));
4646        __ movd(out.AsRegisterPairHigh<Register>(), temp);
4647      } else {
4648        DCHECK_NE(base, out.AsRegisterPairLow<Register>());
4649        __ movl(out.AsRegisterPairLow<Register>(), Address(base, offset));
4650        codegen_->MaybeRecordImplicitNullCheck(instruction);
4651        __ movl(out.AsRegisterPairHigh<Register>(), Address(base, kX86WordSize + offset));
4652      }
4653      break;
4654    }
4655
4656    case Primitive::kPrimFloat: {
4657      __ movss(out.AsFpuRegister<XmmRegister>(), Address(base, offset));
4658      break;
4659    }
4660
4661    case Primitive::kPrimDouble: {
4662      __ movsd(out.AsFpuRegister<XmmRegister>(), Address(base, offset));
4663      break;
4664    }
4665
4666    case Primitive::kPrimVoid:
4667      LOG(FATAL) << "Unreachable type " << field_type;
4668      UNREACHABLE();
4669  }
4670
4671  if (field_type == Primitive::kPrimNot || field_type == Primitive::kPrimLong) {
4672    // Potential implicit null checks, in the case of reference or
4673    // long fields, are handled in the previous switch statement.
4674  } else {
4675    codegen_->MaybeRecordImplicitNullCheck(instruction);
4676  }
4677
4678  if (is_volatile) {
4679    if (field_type == Primitive::kPrimNot) {
4680      // Memory barriers, in the case of references, are also handled
4681      // in the previous switch statement.
4682    } else {
4683      codegen_->GenerateMemoryBarrier(MemBarrierKind::kLoadAny);
4684    }
4685  }
4686}
4687
4688void LocationsBuilderX86::HandleFieldSet(HInstruction* instruction, const FieldInfo& field_info) {
4689  DCHECK(instruction->IsInstanceFieldSet() || instruction->IsStaticFieldSet());
4690
4691  LocationSummary* locations =
4692      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
4693  locations->SetInAt(0, Location::RequiresRegister());
4694  bool is_volatile = field_info.IsVolatile();
4695  Primitive::Type field_type = field_info.GetFieldType();
4696  bool is_byte_type = (field_type == Primitive::kPrimBoolean)
4697    || (field_type == Primitive::kPrimByte);
4698
4699  // The register allocator does not support multiple
4700  // inputs that die at entry with one in a specific register.
4701  if (is_byte_type) {
4702    // Ensure the value is in a byte register.
4703    locations->SetInAt(1, Location::RegisterLocation(EAX));
4704  } else if (Primitive::IsFloatingPointType(field_type)) {
4705    if (is_volatile && field_type == Primitive::kPrimDouble) {
4706      // In order to satisfy the semantics of volatile, this must be a single instruction store.
4707      locations->SetInAt(1, Location::RequiresFpuRegister());
4708    } else {
4709      locations->SetInAt(1, Location::FpuRegisterOrConstant(instruction->InputAt(1)));
4710    }
4711  } else if (is_volatile && field_type == Primitive::kPrimLong) {
4712    // In order to satisfy the semantics of volatile, this must be a single instruction store.
4713    locations->SetInAt(1, Location::RequiresRegister());
4714
4715    // 64bits value can be atomically written to an address with movsd and an XMM register.
4716    // We need two XMM registers because there's no easier way to (bit) copy a register pair
4717    // into a single XMM register (we copy each pair part into the XMMs and then interleave them).
4718    // NB: We could make the register allocator understand fp_reg <-> core_reg moves but given the
4719    // isolated cases when we need this it isn't worth adding the extra complexity.
4720    locations->AddTemp(Location::RequiresFpuRegister());
4721    locations->AddTemp(Location::RequiresFpuRegister());
4722  } else {
4723    locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1)));
4724
4725    if (CodeGenerator::StoreNeedsWriteBarrier(field_type, instruction->InputAt(1))) {
4726      // Temporary registers for the write barrier.
4727      locations->AddTemp(Location::RequiresRegister());  // May be used for reference poisoning too.
4728      // Ensure the card is in a byte register.
4729      locations->AddTemp(Location::RegisterLocation(ECX));
4730    }
4731  }
4732}
4733
4734void InstructionCodeGeneratorX86::HandleFieldSet(HInstruction* instruction,
4735                                                 const FieldInfo& field_info,
4736                                                 bool value_can_be_null) {
4737  DCHECK(instruction->IsInstanceFieldSet() || instruction->IsStaticFieldSet());
4738
4739  LocationSummary* locations = instruction->GetLocations();
4740  Register base = locations->InAt(0).AsRegister<Register>();
4741  Location value = locations->InAt(1);
4742  bool is_volatile = field_info.IsVolatile();
4743  Primitive::Type field_type = field_info.GetFieldType();
4744  uint32_t offset = field_info.GetFieldOffset().Uint32Value();
4745  bool needs_write_barrier =
4746      CodeGenerator::StoreNeedsWriteBarrier(field_type, instruction->InputAt(1));
4747
4748  if (is_volatile) {
4749    codegen_->GenerateMemoryBarrier(MemBarrierKind::kAnyStore);
4750  }
4751
4752  bool maybe_record_implicit_null_check_done = false;
4753
4754  switch (field_type) {
4755    case Primitive::kPrimBoolean:
4756    case Primitive::kPrimByte: {
4757      __ movb(Address(base, offset), value.AsRegister<ByteRegister>());
4758      break;
4759    }
4760
4761    case Primitive::kPrimShort:
4762    case Primitive::kPrimChar: {
4763      if (value.IsConstant()) {
4764        int16_t v = CodeGenerator::GetInt32ValueOf(value.GetConstant());
4765        __ movw(Address(base, offset), Immediate(v));
4766      } else {
4767        __ movw(Address(base, offset), value.AsRegister<Register>());
4768      }
4769      break;
4770    }
4771
4772    case Primitive::kPrimInt:
4773    case Primitive::kPrimNot: {
4774      if (kPoisonHeapReferences && needs_write_barrier) {
4775        // Note that in the case where `value` is a null reference,
4776        // we do not enter this block, as the reference does not
4777        // need poisoning.
4778        DCHECK_EQ(field_type, Primitive::kPrimNot);
4779        Register temp = locations->GetTemp(0).AsRegister<Register>();
4780        __ movl(temp, value.AsRegister<Register>());
4781        __ PoisonHeapReference(temp);
4782        __ movl(Address(base, offset), temp);
4783      } else if (value.IsConstant()) {
4784        int32_t v = CodeGenerator::GetInt32ValueOf(value.GetConstant());
4785        __ movl(Address(base, offset), Immediate(v));
4786      } else {
4787        DCHECK(value.IsRegister()) << value;
4788        __ movl(Address(base, offset), value.AsRegister<Register>());
4789      }
4790      break;
4791    }
4792
4793    case Primitive::kPrimLong: {
4794      if (is_volatile) {
4795        XmmRegister temp1 = locations->GetTemp(0).AsFpuRegister<XmmRegister>();
4796        XmmRegister temp2 = locations->GetTemp(1).AsFpuRegister<XmmRegister>();
4797        __ movd(temp1, value.AsRegisterPairLow<Register>());
4798        __ movd(temp2, value.AsRegisterPairHigh<Register>());
4799        __ punpckldq(temp1, temp2);
4800        __ movsd(Address(base, offset), temp1);
4801        codegen_->MaybeRecordImplicitNullCheck(instruction);
4802      } else if (value.IsConstant()) {
4803        int64_t v = CodeGenerator::GetInt64ValueOf(value.GetConstant());
4804        __ movl(Address(base, offset), Immediate(Low32Bits(v)));
4805        codegen_->MaybeRecordImplicitNullCheck(instruction);
4806        __ movl(Address(base, kX86WordSize + offset), Immediate(High32Bits(v)));
4807      } else {
4808        __ movl(Address(base, offset), value.AsRegisterPairLow<Register>());
4809        codegen_->MaybeRecordImplicitNullCheck(instruction);
4810        __ movl(Address(base, kX86WordSize + offset), value.AsRegisterPairHigh<Register>());
4811      }
4812      maybe_record_implicit_null_check_done = true;
4813      break;
4814    }
4815
4816    case Primitive::kPrimFloat: {
4817      if (value.IsConstant()) {
4818        int32_t v = CodeGenerator::GetInt32ValueOf(value.GetConstant());
4819        __ movl(Address(base, offset), Immediate(v));
4820      } else {
4821        __ movss(Address(base, offset), value.AsFpuRegister<XmmRegister>());
4822      }
4823      break;
4824    }
4825
4826    case Primitive::kPrimDouble: {
4827      if (value.IsConstant()) {
4828        int64_t v = CodeGenerator::GetInt64ValueOf(value.GetConstant());
4829        __ movl(Address(base, offset), Immediate(Low32Bits(v)));
4830        codegen_->MaybeRecordImplicitNullCheck(instruction);
4831        __ movl(Address(base, kX86WordSize + offset), Immediate(High32Bits(v)));
4832        maybe_record_implicit_null_check_done = true;
4833      } else {
4834        __ movsd(Address(base, offset), value.AsFpuRegister<XmmRegister>());
4835      }
4836      break;
4837    }
4838
4839    case Primitive::kPrimVoid:
4840      LOG(FATAL) << "Unreachable type " << field_type;
4841      UNREACHABLE();
4842  }
4843
4844  if (!maybe_record_implicit_null_check_done) {
4845    codegen_->MaybeRecordImplicitNullCheck(instruction);
4846  }
4847
4848  if (needs_write_barrier) {
4849    Register temp = locations->GetTemp(0).AsRegister<Register>();
4850    Register card = locations->GetTemp(1).AsRegister<Register>();
4851    codegen_->MarkGCCard(temp, card, base, value.AsRegister<Register>(), value_can_be_null);
4852  }
4853
4854  if (is_volatile) {
4855    codegen_->GenerateMemoryBarrier(MemBarrierKind::kAnyAny);
4856  }
4857}
4858
4859void LocationsBuilderX86::VisitStaticFieldGet(HStaticFieldGet* instruction) {
4860  HandleFieldGet(instruction, instruction->GetFieldInfo());
4861}
4862
4863void InstructionCodeGeneratorX86::VisitStaticFieldGet(HStaticFieldGet* instruction) {
4864  HandleFieldGet(instruction, instruction->GetFieldInfo());
4865}
4866
4867void LocationsBuilderX86::VisitStaticFieldSet(HStaticFieldSet* instruction) {
4868  HandleFieldSet(instruction, instruction->GetFieldInfo());
4869}
4870
4871void InstructionCodeGeneratorX86::VisitStaticFieldSet(HStaticFieldSet* instruction) {
4872  HandleFieldSet(instruction, instruction->GetFieldInfo(), instruction->GetValueCanBeNull());
4873}
4874
4875void LocationsBuilderX86::VisitInstanceFieldSet(HInstanceFieldSet* instruction) {
4876  HandleFieldSet(instruction, instruction->GetFieldInfo());
4877}
4878
4879void InstructionCodeGeneratorX86::VisitInstanceFieldSet(HInstanceFieldSet* instruction) {
4880  HandleFieldSet(instruction, instruction->GetFieldInfo(), instruction->GetValueCanBeNull());
4881}
4882
4883void LocationsBuilderX86::VisitInstanceFieldGet(HInstanceFieldGet* instruction) {
4884  HandleFieldGet(instruction, instruction->GetFieldInfo());
4885}
4886
4887void InstructionCodeGeneratorX86::VisitInstanceFieldGet(HInstanceFieldGet* instruction) {
4888  HandleFieldGet(instruction, instruction->GetFieldInfo());
4889}
4890
4891void LocationsBuilderX86::VisitUnresolvedInstanceFieldGet(
4892    HUnresolvedInstanceFieldGet* instruction) {
4893  FieldAccessCallingConventionX86 calling_convention;
4894  codegen_->CreateUnresolvedFieldLocationSummary(
4895      instruction, instruction->GetFieldType(), calling_convention);
4896}
4897
4898void InstructionCodeGeneratorX86::VisitUnresolvedInstanceFieldGet(
4899    HUnresolvedInstanceFieldGet* instruction) {
4900  FieldAccessCallingConventionX86 calling_convention;
4901  codegen_->GenerateUnresolvedFieldAccess(instruction,
4902                                          instruction->GetFieldType(),
4903                                          instruction->GetFieldIndex(),
4904                                          instruction->GetDexPc(),
4905                                          calling_convention);
4906}
4907
4908void LocationsBuilderX86::VisitUnresolvedInstanceFieldSet(
4909    HUnresolvedInstanceFieldSet* instruction) {
4910  FieldAccessCallingConventionX86 calling_convention;
4911  codegen_->CreateUnresolvedFieldLocationSummary(
4912      instruction, instruction->GetFieldType(), calling_convention);
4913}
4914
4915void InstructionCodeGeneratorX86::VisitUnresolvedInstanceFieldSet(
4916    HUnresolvedInstanceFieldSet* instruction) {
4917  FieldAccessCallingConventionX86 calling_convention;
4918  codegen_->GenerateUnresolvedFieldAccess(instruction,
4919                                          instruction->GetFieldType(),
4920                                          instruction->GetFieldIndex(),
4921                                          instruction->GetDexPc(),
4922                                          calling_convention);
4923}
4924
4925void LocationsBuilderX86::VisitUnresolvedStaticFieldGet(
4926    HUnresolvedStaticFieldGet* instruction) {
4927  FieldAccessCallingConventionX86 calling_convention;
4928  codegen_->CreateUnresolvedFieldLocationSummary(
4929      instruction, instruction->GetFieldType(), calling_convention);
4930}
4931
4932void InstructionCodeGeneratorX86::VisitUnresolvedStaticFieldGet(
4933    HUnresolvedStaticFieldGet* instruction) {
4934  FieldAccessCallingConventionX86 calling_convention;
4935  codegen_->GenerateUnresolvedFieldAccess(instruction,
4936                                          instruction->GetFieldType(),
4937                                          instruction->GetFieldIndex(),
4938                                          instruction->GetDexPc(),
4939                                          calling_convention);
4940}
4941
4942void LocationsBuilderX86::VisitUnresolvedStaticFieldSet(
4943    HUnresolvedStaticFieldSet* instruction) {
4944  FieldAccessCallingConventionX86 calling_convention;
4945  codegen_->CreateUnresolvedFieldLocationSummary(
4946      instruction, instruction->GetFieldType(), calling_convention);
4947}
4948
4949void InstructionCodeGeneratorX86::VisitUnresolvedStaticFieldSet(
4950    HUnresolvedStaticFieldSet* instruction) {
4951  FieldAccessCallingConventionX86 calling_convention;
4952  codegen_->GenerateUnresolvedFieldAccess(instruction,
4953                                          instruction->GetFieldType(),
4954                                          instruction->GetFieldIndex(),
4955                                          instruction->GetDexPc(),
4956                                          calling_convention);
4957}
4958
4959void LocationsBuilderX86::VisitNullCheck(HNullCheck* instruction) {
4960  LocationSummary::CallKind call_kind = instruction->CanThrowIntoCatchBlock()
4961      ? LocationSummary::kCallOnSlowPath
4962      : LocationSummary::kNoCall;
4963  LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, call_kind);
4964  Location loc = codegen_->IsImplicitNullCheckAllowed(instruction)
4965      ? Location::RequiresRegister()
4966      : Location::Any();
4967  locations->SetInAt(0, loc);
4968  if (instruction->HasUses()) {
4969    locations->SetOut(Location::SameAsFirstInput());
4970  }
4971}
4972
4973void CodeGeneratorX86::GenerateImplicitNullCheck(HNullCheck* instruction) {
4974  if (CanMoveNullCheckToUser(instruction)) {
4975    return;
4976  }
4977  LocationSummary* locations = instruction->GetLocations();
4978  Location obj = locations->InAt(0);
4979
4980  __ testl(EAX, Address(obj.AsRegister<Register>(), 0));
4981  RecordPcInfo(instruction, instruction->GetDexPc());
4982}
4983
4984void CodeGeneratorX86::GenerateExplicitNullCheck(HNullCheck* instruction) {
4985  SlowPathCode* slow_path = new (GetGraph()->GetArena()) NullCheckSlowPathX86(instruction);
4986  AddSlowPath(slow_path);
4987
4988  LocationSummary* locations = instruction->GetLocations();
4989  Location obj = locations->InAt(0);
4990
4991  if (obj.IsRegister()) {
4992    __ testl(obj.AsRegister<Register>(), obj.AsRegister<Register>());
4993  } else if (obj.IsStackSlot()) {
4994    __ cmpl(Address(ESP, obj.GetStackIndex()), Immediate(0));
4995  } else {
4996    DCHECK(obj.IsConstant()) << obj;
4997    DCHECK(obj.GetConstant()->IsNullConstant());
4998    __ jmp(slow_path->GetEntryLabel());
4999    return;
5000  }
5001  __ j(kEqual, slow_path->GetEntryLabel());
5002}
5003
5004void InstructionCodeGeneratorX86::VisitNullCheck(HNullCheck* instruction) {
5005  codegen_->GenerateNullCheck(instruction);
5006}
5007
5008void LocationsBuilderX86::VisitArrayGet(HArrayGet* instruction) {
5009  bool object_array_get_with_read_barrier =
5010      kEmitCompilerReadBarrier && (instruction->GetType() == Primitive::kPrimNot);
5011  LocationSummary* locations =
5012      new (GetGraph()->GetArena()) LocationSummary(instruction,
5013                                                   object_array_get_with_read_barrier ?
5014                                                       LocationSummary::kCallOnSlowPath :
5015                                                       LocationSummary::kNoCall);
5016  locations->SetInAt(0, Location::RequiresRegister());
5017  locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1)));
5018  if (Primitive::IsFloatingPointType(instruction->GetType())) {
5019    locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
5020  } else {
5021    // The output overlaps in case of long: we don't want the low move
5022    // to overwrite the array's location.  Likewise, in the case of an
5023    // object array get with read barriers enabled, we do not want the
5024    // move to overwrite the array's location, as we need it to emit
5025    // the read barrier.
5026    locations->SetOut(
5027        Location::RequiresRegister(),
5028        (instruction->GetType() == Primitive::kPrimLong || object_array_get_with_read_barrier) ?
5029            Location::kOutputOverlap :
5030            Location::kNoOutputOverlap);
5031  }
5032  // We need a temporary register for the read barrier marking slow
5033  // path in CodeGeneratorX86::GenerateArrayLoadWithBakerReadBarrier.
5034  if (object_array_get_with_read_barrier && kUseBakerReadBarrier) {
5035    locations->AddTemp(Location::RequiresRegister());
5036  }
5037}
5038
5039void InstructionCodeGeneratorX86::VisitArrayGet(HArrayGet* instruction) {
5040  LocationSummary* locations = instruction->GetLocations();
5041  Location obj_loc = locations->InAt(0);
5042  Register obj = obj_loc.AsRegister<Register>();
5043  Location index = locations->InAt(1);
5044  Location out_loc = locations->Out();
5045
5046  Primitive::Type type = instruction->GetType();
5047  switch (type) {
5048    case Primitive::kPrimBoolean: {
5049      uint32_t data_offset = mirror::Array::DataOffset(sizeof(uint8_t)).Uint32Value();
5050      Register out = out_loc.AsRegister<Register>();
5051      if (index.IsConstant()) {
5052        __ movzxb(out, Address(obj,
5053            (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_1) + data_offset));
5054      } else {
5055        __ movzxb(out, Address(obj, index.AsRegister<Register>(), TIMES_1, data_offset));
5056      }
5057      break;
5058    }
5059
5060    case Primitive::kPrimByte: {
5061      uint32_t data_offset = mirror::Array::DataOffset(sizeof(int8_t)).Uint32Value();
5062      Register out = out_loc.AsRegister<Register>();
5063      if (index.IsConstant()) {
5064        __ movsxb(out, Address(obj,
5065            (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_1) + data_offset));
5066      } else {
5067        __ movsxb(out, Address(obj, index.AsRegister<Register>(), TIMES_1, data_offset));
5068      }
5069      break;
5070    }
5071
5072    case Primitive::kPrimShort: {
5073      uint32_t data_offset = mirror::Array::DataOffset(sizeof(int16_t)).Uint32Value();
5074      Register out = out_loc.AsRegister<Register>();
5075      if (index.IsConstant()) {
5076        __ movsxw(out, Address(obj,
5077            (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_2) + data_offset));
5078      } else {
5079        __ movsxw(out, Address(obj, index.AsRegister<Register>(), TIMES_2, data_offset));
5080      }
5081      break;
5082    }
5083
5084    case Primitive::kPrimChar: {
5085      uint32_t data_offset = mirror::Array::DataOffset(sizeof(uint16_t)).Uint32Value();
5086      Register out = out_loc.AsRegister<Register>();
5087      if (index.IsConstant()) {
5088        __ movzxw(out, Address(obj,
5089            (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_2) + data_offset));
5090      } else {
5091        __ movzxw(out, Address(obj, index.AsRegister<Register>(), TIMES_2, data_offset));
5092      }
5093      break;
5094    }
5095
5096    case Primitive::kPrimInt: {
5097      uint32_t data_offset = mirror::Array::DataOffset(sizeof(int32_t)).Uint32Value();
5098      Register out = out_loc.AsRegister<Register>();
5099      if (index.IsConstant()) {
5100        __ movl(out, Address(obj,
5101            (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_4) + data_offset));
5102      } else {
5103        __ movl(out, Address(obj, index.AsRegister<Register>(), TIMES_4, data_offset));
5104      }
5105      break;
5106    }
5107
5108    case Primitive::kPrimNot: {
5109      static_assert(
5110          sizeof(mirror::HeapReference<mirror::Object>) == sizeof(int32_t),
5111          "art::mirror::HeapReference<art::mirror::Object> and int32_t have different sizes.");
5112      uint32_t data_offset = mirror::Array::DataOffset(sizeof(int32_t)).Uint32Value();
5113      // /* HeapReference<Object> */ out =
5114      //     *(obj + data_offset + index * sizeof(HeapReference<Object>))
5115      if (kEmitCompilerReadBarrier && kUseBakerReadBarrier) {
5116        Location temp = locations->GetTemp(0);
5117        // Note that a potential implicit null check is handled in this
5118        // CodeGeneratorX86::GenerateArrayLoadWithBakerReadBarrier call.
5119        codegen_->GenerateArrayLoadWithBakerReadBarrier(
5120            instruction, out_loc, obj, data_offset, index, temp, /* needs_null_check */ true);
5121      } else {
5122        Register out = out_loc.AsRegister<Register>();
5123        if (index.IsConstant()) {
5124          uint32_t offset =
5125              (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_4) + data_offset;
5126          __ movl(out, Address(obj, offset));
5127          codegen_->MaybeRecordImplicitNullCheck(instruction);
5128          // If read barriers are enabled, emit read barriers other than
5129          // Baker's using a slow path (and also unpoison the loaded
5130          // reference, if heap poisoning is enabled).
5131          codegen_->MaybeGenerateReadBarrierSlow(instruction, out_loc, out_loc, obj_loc, offset);
5132        } else {
5133          __ movl(out, Address(obj, index.AsRegister<Register>(), TIMES_4, data_offset));
5134          codegen_->MaybeRecordImplicitNullCheck(instruction);
5135          // If read barriers are enabled, emit read barriers other than
5136          // Baker's using a slow path (and also unpoison the loaded
5137          // reference, if heap poisoning is enabled).
5138          codegen_->MaybeGenerateReadBarrierSlow(
5139              instruction, out_loc, out_loc, obj_loc, data_offset, index);
5140        }
5141      }
5142      break;
5143    }
5144
5145    case Primitive::kPrimLong: {
5146      uint32_t data_offset = mirror::Array::DataOffset(sizeof(int64_t)).Uint32Value();
5147      DCHECK_NE(obj, out_loc.AsRegisterPairLow<Register>());
5148      if (index.IsConstant()) {
5149        size_t offset = (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_8) + data_offset;
5150        __ movl(out_loc.AsRegisterPairLow<Register>(), Address(obj, offset));
5151        codegen_->MaybeRecordImplicitNullCheck(instruction);
5152        __ movl(out_loc.AsRegisterPairHigh<Register>(), Address(obj, offset + kX86WordSize));
5153      } else {
5154        __ movl(out_loc.AsRegisterPairLow<Register>(),
5155                Address(obj, index.AsRegister<Register>(), TIMES_8, data_offset));
5156        codegen_->MaybeRecordImplicitNullCheck(instruction);
5157        __ movl(out_loc.AsRegisterPairHigh<Register>(),
5158                Address(obj, index.AsRegister<Register>(), TIMES_8, data_offset + kX86WordSize));
5159      }
5160      break;
5161    }
5162
5163    case Primitive::kPrimFloat: {
5164      uint32_t data_offset = mirror::Array::DataOffset(sizeof(float)).Uint32Value();
5165      XmmRegister out = out_loc.AsFpuRegister<XmmRegister>();
5166      if (index.IsConstant()) {
5167        __ movss(out, Address(obj,
5168            (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_4) + data_offset));
5169      } else {
5170        __ movss(out, Address(obj, index.AsRegister<Register>(), TIMES_4, data_offset));
5171      }
5172      break;
5173    }
5174
5175    case Primitive::kPrimDouble: {
5176      uint32_t data_offset = mirror::Array::DataOffset(sizeof(double)).Uint32Value();
5177      XmmRegister out = out_loc.AsFpuRegister<XmmRegister>();
5178      if (index.IsConstant()) {
5179        __ movsd(out, Address(obj,
5180            (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_8) + data_offset));
5181      } else {
5182        __ movsd(out, Address(obj, index.AsRegister<Register>(), TIMES_8, data_offset));
5183      }
5184      break;
5185    }
5186
5187    case Primitive::kPrimVoid:
5188      LOG(FATAL) << "Unreachable type " << type;
5189      UNREACHABLE();
5190  }
5191
5192  if (type == Primitive::kPrimNot || type == Primitive::kPrimLong) {
5193    // Potential implicit null checks, in the case of reference or
5194    // long arrays, are handled in the previous switch statement.
5195  } else {
5196    codegen_->MaybeRecordImplicitNullCheck(instruction);
5197  }
5198}
5199
5200void LocationsBuilderX86::VisitArraySet(HArraySet* instruction) {
5201  Primitive::Type value_type = instruction->GetComponentType();
5202
5203  bool needs_write_barrier =
5204      CodeGenerator::StoreNeedsWriteBarrier(value_type, instruction->GetValue());
5205  bool may_need_runtime_call_for_type_check = instruction->NeedsTypeCheck();
5206  bool object_array_set_with_read_barrier =
5207      kEmitCompilerReadBarrier && (value_type == Primitive::kPrimNot);
5208
5209  LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(
5210      instruction,
5211      (may_need_runtime_call_for_type_check || object_array_set_with_read_barrier) ?
5212          LocationSummary::kCallOnSlowPath :
5213          LocationSummary::kNoCall);
5214
5215  bool is_byte_type = (value_type == Primitive::kPrimBoolean)
5216      || (value_type == Primitive::kPrimByte);
5217  // We need the inputs to be different than the output in case of long operation.
5218  // In case of a byte operation, the register allocator does not support multiple
5219  // inputs that die at entry with one in a specific register.
5220  locations->SetInAt(0, Location::RequiresRegister());
5221  locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1)));
5222  if (is_byte_type) {
5223    // Ensure the value is in a byte register.
5224    locations->SetInAt(2, Location::ByteRegisterOrConstant(EAX, instruction->InputAt(2)));
5225  } else if (Primitive::IsFloatingPointType(value_type)) {
5226    locations->SetInAt(2, Location::FpuRegisterOrConstant(instruction->InputAt(2)));
5227  } else {
5228    locations->SetInAt(2, Location::RegisterOrConstant(instruction->InputAt(2)));
5229  }
5230  if (needs_write_barrier) {
5231    // Temporary registers for the write barrier.
5232    locations->AddTemp(Location::RequiresRegister());  // Possibly used for ref. poisoning too.
5233    // Ensure the card is in a byte register.
5234    locations->AddTemp(Location::RegisterLocation(ECX));
5235  }
5236}
5237
5238void InstructionCodeGeneratorX86::VisitArraySet(HArraySet* instruction) {
5239  LocationSummary* locations = instruction->GetLocations();
5240  Location array_loc = locations->InAt(0);
5241  Register array = array_loc.AsRegister<Register>();
5242  Location index = locations->InAt(1);
5243  Location value = locations->InAt(2);
5244  Primitive::Type value_type = instruction->GetComponentType();
5245  uint32_t class_offset = mirror::Object::ClassOffset().Int32Value();
5246  uint32_t super_offset = mirror::Class::SuperClassOffset().Int32Value();
5247  uint32_t component_offset = mirror::Class::ComponentTypeOffset().Int32Value();
5248  bool may_need_runtime_call_for_type_check = instruction->NeedsTypeCheck();
5249  bool needs_write_barrier =
5250      CodeGenerator::StoreNeedsWriteBarrier(value_type, instruction->GetValue());
5251
5252  switch (value_type) {
5253    case Primitive::kPrimBoolean:
5254    case Primitive::kPrimByte: {
5255      uint32_t offset = mirror::Array::DataOffset(sizeof(uint8_t)).Uint32Value();
5256      Address address = index.IsConstant()
5257          ? Address(array, (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_1) + offset)
5258          : Address(array, index.AsRegister<Register>(), TIMES_1, offset);
5259      if (value.IsRegister()) {
5260        __ movb(address, value.AsRegister<ByteRegister>());
5261      } else {
5262        __ movb(address, Immediate(value.GetConstant()->AsIntConstant()->GetValue()));
5263      }
5264      codegen_->MaybeRecordImplicitNullCheck(instruction);
5265      break;
5266    }
5267
5268    case Primitive::kPrimShort:
5269    case Primitive::kPrimChar: {
5270      uint32_t offset = mirror::Array::DataOffset(sizeof(uint16_t)).Uint32Value();
5271      Address address = index.IsConstant()
5272          ? Address(array, (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_2) + offset)
5273          : Address(array, index.AsRegister<Register>(), TIMES_2, offset);
5274      if (value.IsRegister()) {
5275        __ movw(address, value.AsRegister<Register>());
5276      } else {
5277        __ movw(address, Immediate(value.GetConstant()->AsIntConstant()->GetValue()));
5278      }
5279      codegen_->MaybeRecordImplicitNullCheck(instruction);
5280      break;
5281    }
5282
5283    case Primitive::kPrimNot: {
5284      uint32_t offset = mirror::Array::DataOffset(sizeof(int32_t)).Uint32Value();
5285      Address address = index.IsConstant()
5286          ? Address(array, (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_4) + offset)
5287          : Address(array, index.AsRegister<Register>(), TIMES_4, offset);
5288
5289      if (!value.IsRegister()) {
5290        // Just setting null.
5291        DCHECK(instruction->InputAt(2)->IsNullConstant());
5292        DCHECK(value.IsConstant()) << value;
5293        __ movl(address, Immediate(0));
5294        codegen_->MaybeRecordImplicitNullCheck(instruction);
5295        DCHECK(!needs_write_barrier);
5296        DCHECK(!may_need_runtime_call_for_type_check);
5297        break;
5298      }
5299
5300      DCHECK(needs_write_barrier);
5301      Register register_value = value.AsRegister<Register>();
5302      NearLabel done, not_null, do_put;
5303      SlowPathCode* slow_path = nullptr;
5304      Register temp = locations->GetTemp(0).AsRegister<Register>();
5305      if (may_need_runtime_call_for_type_check) {
5306        slow_path = new (GetGraph()->GetArena()) ArraySetSlowPathX86(instruction);
5307        codegen_->AddSlowPath(slow_path);
5308        if (instruction->GetValueCanBeNull()) {
5309          __ testl(register_value, register_value);
5310          __ j(kNotEqual, &not_null);
5311          __ movl(address, Immediate(0));
5312          codegen_->MaybeRecordImplicitNullCheck(instruction);
5313          __ jmp(&done);
5314          __ Bind(&not_null);
5315        }
5316
5317        if (kEmitCompilerReadBarrier) {
5318          // When read barriers are enabled, the type checking
5319          // instrumentation requires two read barriers:
5320          //
5321          //   __ movl(temp2, temp);
5322          //   // /* HeapReference<Class> */ temp = temp->component_type_
5323          //   __ movl(temp, Address(temp, component_offset));
5324          //   codegen_->GenerateReadBarrierSlow(
5325          //       instruction, temp_loc, temp_loc, temp2_loc, component_offset);
5326          //
5327          //   // /* HeapReference<Class> */ temp2 = register_value->klass_
5328          //   __ movl(temp2, Address(register_value, class_offset));
5329          //   codegen_->GenerateReadBarrierSlow(
5330          //       instruction, temp2_loc, temp2_loc, value, class_offset, temp_loc);
5331          //
5332          //   __ cmpl(temp, temp2);
5333          //
5334          // However, the second read barrier may trash `temp`, as it
5335          // is a temporary register, and as such would not be saved
5336          // along with live registers before calling the runtime (nor
5337          // restored afterwards).  So in this case, we bail out and
5338          // delegate the work to the array set slow path.
5339          //
5340          // TODO: Extend the register allocator to support a new
5341          // "(locally) live temp" location so as to avoid always
5342          // going into the slow path when read barriers are enabled.
5343          __ jmp(slow_path->GetEntryLabel());
5344        } else {
5345          // /* HeapReference<Class> */ temp = array->klass_
5346          __ movl(temp, Address(array, class_offset));
5347          codegen_->MaybeRecordImplicitNullCheck(instruction);
5348          __ MaybeUnpoisonHeapReference(temp);
5349
5350          // /* HeapReference<Class> */ temp = temp->component_type_
5351          __ movl(temp, Address(temp, component_offset));
5352          // If heap poisoning is enabled, no need to unpoison `temp`
5353          // nor the object reference in `register_value->klass`, as
5354          // we are comparing two poisoned references.
5355          __ cmpl(temp, Address(register_value, class_offset));
5356
5357          if (instruction->StaticTypeOfArrayIsObjectArray()) {
5358            __ j(kEqual, &do_put);
5359            // If heap poisoning is enabled, the `temp` reference has
5360            // not been unpoisoned yet; unpoison it now.
5361            __ MaybeUnpoisonHeapReference(temp);
5362
5363            // /* HeapReference<Class> */ temp = temp->super_class_
5364            __ movl(temp, Address(temp, super_offset));
5365            // If heap poisoning is enabled, no need to unpoison
5366            // `temp`, as we are comparing against null below.
5367            __ testl(temp, temp);
5368            __ j(kNotEqual, slow_path->GetEntryLabel());
5369            __ Bind(&do_put);
5370          } else {
5371            __ j(kNotEqual, slow_path->GetEntryLabel());
5372          }
5373        }
5374      }
5375
5376      if (kPoisonHeapReferences) {
5377        __ movl(temp, register_value);
5378        __ PoisonHeapReference(temp);
5379        __ movl(address, temp);
5380      } else {
5381        __ movl(address, register_value);
5382      }
5383      if (!may_need_runtime_call_for_type_check) {
5384        codegen_->MaybeRecordImplicitNullCheck(instruction);
5385      }
5386
5387      Register card = locations->GetTemp(1).AsRegister<Register>();
5388      codegen_->MarkGCCard(
5389          temp, card, array, value.AsRegister<Register>(), instruction->GetValueCanBeNull());
5390      __ Bind(&done);
5391
5392      if (slow_path != nullptr) {
5393        __ Bind(slow_path->GetExitLabel());
5394      }
5395
5396      break;
5397    }
5398
5399    case Primitive::kPrimInt: {
5400      uint32_t offset = mirror::Array::DataOffset(sizeof(int32_t)).Uint32Value();
5401      Address address = index.IsConstant()
5402          ? Address(array, (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_4) + offset)
5403          : Address(array, index.AsRegister<Register>(), TIMES_4, offset);
5404      if (value.IsRegister()) {
5405        __ movl(address, value.AsRegister<Register>());
5406      } else {
5407        DCHECK(value.IsConstant()) << value;
5408        int32_t v = CodeGenerator::GetInt32ValueOf(value.GetConstant());
5409        __ movl(address, Immediate(v));
5410      }
5411      codegen_->MaybeRecordImplicitNullCheck(instruction);
5412      break;
5413    }
5414
5415    case Primitive::kPrimLong: {
5416      uint32_t data_offset = mirror::Array::DataOffset(sizeof(int64_t)).Uint32Value();
5417      if (index.IsConstant()) {
5418        size_t offset = (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_8) + data_offset;
5419        if (value.IsRegisterPair()) {
5420          __ movl(Address(array, offset), value.AsRegisterPairLow<Register>());
5421          codegen_->MaybeRecordImplicitNullCheck(instruction);
5422          __ movl(Address(array, offset + kX86WordSize), value.AsRegisterPairHigh<Register>());
5423        } else {
5424          DCHECK(value.IsConstant());
5425          int64_t val = value.GetConstant()->AsLongConstant()->GetValue();
5426          __ movl(Address(array, offset), Immediate(Low32Bits(val)));
5427          codegen_->MaybeRecordImplicitNullCheck(instruction);
5428          __ movl(Address(array, offset + kX86WordSize), Immediate(High32Bits(val)));
5429        }
5430      } else {
5431        if (value.IsRegisterPair()) {
5432          __ movl(Address(array, index.AsRegister<Register>(), TIMES_8, data_offset),
5433                  value.AsRegisterPairLow<Register>());
5434          codegen_->MaybeRecordImplicitNullCheck(instruction);
5435          __ movl(Address(array, index.AsRegister<Register>(), TIMES_8, data_offset + kX86WordSize),
5436                  value.AsRegisterPairHigh<Register>());
5437        } else {
5438          DCHECK(value.IsConstant());
5439          int64_t val = value.GetConstant()->AsLongConstant()->GetValue();
5440          __ movl(Address(array, index.AsRegister<Register>(), TIMES_8, data_offset),
5441                  Immediate(Low32Bits(val)));
5442          codegen_->MaybeRecordImplicitNullCheck(instruction);
5443          __ movl(Address(array, index.AsRegister<Register>(), TIMES_8, data_offset + kX86WordSize),
5444                  Immediate(High32Bits(val)));
5445        }
5446      }
5447      break;
5448    }
5449
5450    case Primitive::kPrimFloat: {
5451      uint32_t offset = mirror::Array::DataOffset(sizeof(float)).Uint32Value();
5452      Address address = index.IsConstant()
5453          ? Address(array, (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_4) + offset)
5454          : Address(array, index.AsRegister<Register>(), TIMES_4, offset);
5455      if (value.IsFpuRegister()) {
5456        __ movss(address, value.AsFpuRegister<XmmRegister>());
5457      } else {
5458        DCHECK(value.IsConstant());
5459        int32_t v = bit_cast<int32_t, float>(value.GetConstant()->AsFloatConstant()->GetValue());
5460        __ movl(address, Immediate(v));
5461      }
5462      codegen_->MaybeRecordImplicitNullCheck(instruction);
5463      break;
5464    }
5465
5466    case Primitive::kPrimDouble: {
5467      uint32_t offset = mirror::Array::DataOffset(sizeof(double)).Uint32Value();
5468      Address address = index.IsConstant()
5469          ? Address(array, (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_8) + offset)
5470          : Address(array, index.AsRegister<Register>(), TIMES_8, offset);
5471      if (value.IsFpuRegister()) {
5472        __ movsd(address, value.AsFpuRegister<XmmRegister>());
5473      } else {
5474        DCHECK(value.IsConstant());
5475        Address address_hi = index.IsConstant() ?
5476            Address(array, (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_8) +
5477                           offset + kX86WordSize) :
5478            Address(array, index.AsRegister<Register>(), TIMES_8, offset + kX86WordSize);
5479        int64_t v = bit_cast<int64_t, double>(value.GetConstant()->AsDoubleConstant()->GetValue());
5480        __ movl(address, Immediate(Low32Bits(v)));
5481        codegen_->MaybeRecordImplicitNullCheck(instruction);
5482        __ movl(address_hi, Immediate(High32Bits(v)));
5483      }
5484      break;
5485    }
5486
5487    case Primitive::kPrimVoid:
5488      LOG(FATAL) << "Unreachable type " << instruction->GetType();
5489      UNREACHABLE();
5490  }
5491}
5492
5493void LocationsBuilderX86::VisitArrayLength(HArrayLength* instruction) {
5494  LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
5495  locations->SetInAt(0, Location::RequiresRegister());
5496  locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
5497}
5498
5499void InstructionCodeGeneratorX86::VisitArrayLength(HArrayLength* instruction) {
5500  LocationSummary* locations = instruction->GetLocations();
5501  uint32_t offset = mirror::Array::LengthOffset().Uint32Value();
5502  Register obj = locations->InAt(0).AsRegister<Register>();
5503  Register out = locations->Out().AsRegister<Register>();
5504  __ movl(out, Address(obj, offset));
5505  codegen_->MaybeRecordImplicitNullCheck(instruction);
5506}
5507
5508void LocationsBuilderX86::VisitBoundsCheck(HBoundsCheck* instruction) {
5509  LocationSummary::CallKind call_kind = instruction->CanThrowIntoCatchBlock()
5510      ? LocationSummary::kCallOnSlowPath
5511      : LocationSummary::kNoCall;
5512  LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, call_kind);
5513  locations->SetInAt(0, Location::RegisterOrConstant(instruction->InputAt(0)));
5514  locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1)));
5515  if (instruction->HasUses()) {
5516    locations->SetOut(Location::SameAsFirstInput());
5517  }
5518}
5519
5520void InstructionCodeGeneratorX86::VisitBoundsCheck(HBoundsCheck* instruction) {
5521  LocationSummary* locations = instruction->GetLocations();
5522  Location index_loc = locations->InAt(0);
5523  Location length_loc = locations->InAt(1);
5524  SlowPathCode* slow_path =
5525    new (GetGraph()->GetArena()) BoundsCheckSlowPathX86(instruction);
5526
5527  if (length_loc.IsConstant()) {
5528    int32_t length = CodeGenerator::GetInt32ValueOf(length_loc.GetConstant());
5529    if (index_loc.IsConstant()) {
5530      // BCE will remove the bounds check if we are guarenteed to pass.
5531      int32_t index = CodeGenerator::GetInt32ValueOf(index_loc.GetConstant());
5532      if (index < 0 || index >= length) {
5533        codegen_->AddSlowPath(slow_path);
5534        __ jmp(slow_path->GetEntryLabel());
5535      } else {
5536        // Some optimization after BCE may have generated this, and we should not
5537        // generate a bounds check if it is a valid range.
5538      }
5539      return;
5540    }
5541
5542    // We have to reverse the jump condition because the length is the constant.
5543    Register index_reg = index_loc.AsRegister<Register>();
5544    __ cmpl(index_reg, Immediate(length));
5545    codegen_->AddSlowPath(slow_path);
5546    __ j(kAboveEqual, slow_path->GetEntryLabel());
5547  } else {
5548    Register length = length_loc.AsRegister<Register>();
5549    if (index_loc.IsConstant()) {
5550      int32_t value = CodeGenerator::GetInt32ValueOf(index_loc.GetConstant());
5551      __ cmpl(length, Immediate(value));
5552    } else {
5553      __ cmpl(length, index_loc.AsRegister<Register>());
5554    }
5555    codegen_->AddSlowPath(slow_path);
5556    __ j(kBelowEqual, slow_path->GetEntryLabel());
5557  }
5558}
5559
5560void LocationsBuilderX86::VisitParallelMove(HParallelMove* instruction ATTRIBUTE_UNUSED) {
5561  LOG(FATAL) << "Unreachable";
5562}
5563
5564void InstructionCodeGeneratorX86::VisitParallelMove(HParallelMove* instruction) {
5565  codegen_->GetMoveResolver()->EmitNativeCode(instruction);
5566}
5567
5568void LocationsBuilderX86::VisitSuspendCheck(HSuspendCheck* instruction) {
5569  new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCallOnSlowPath);
5570}
5571
5572void InstructionCodeGeneratorX86::VisitSuspendCheck(HSuspendCheck* instruction) {
5573  HBasicBlock* block = instruction->GetBlock();
5574  if (block->GetLoopInformation() != nullptr) {
5575    DCHECK(block->GetLoopInformation()->GetSuspendCheck() == instruction);
5576    // The back edge will generate the suspend check.
5577    return;
5578  }
5579  if (block->IsEntryBlock() && instruction->GetNext()->IsGoto()) {
5580    // The goto will generate the suspend check.
5581    return;
5582  }
5583  GenerateSuspendCheck(instruction, nullptr);
5584}
5585
5586void InstructionCodeGeneratorX86::GenerateSuspendCheck(HSuspendCheck* instruction,
5587                                                       HBasicBlock* successor) {
5588  SuspendCheckSlowPathX86* slow_path =
5589      down_cast<SuspendCheckSlowPathX86*>(instruction->GetSlowPath());
5590  if (slow_path == nullptr) {
5591    slow_path = new (GetGraph()->GetArena()) SuspendCheckSlowPathX86(instruction, successor);
5592    instruction->SetSlowPath(slow_path);
5593    codegen_->AddSlowPath(slow_path);
5594    if (successor != nullptr) {
5595      DCHECK(successor->IsLoopHeader());
5596      codegen_->ClearSpillSlotsFromLoopPhisInStackMap(instruction);
5597    }
5598  } else {
5599    DCHECK_EQ(slow_path->GetSuccessor(), successor);
5600  }
5601
5602  __ fs()->cmpw(Address::Absolute(Thread::ThreadFlagsOffset<kX86WordSize>().Int32Value()),
5603                Immediate(0));
5604  if (successor == nullptr) {
5605    __ j(kNotEqual, slow_path->GetEntryLabel());
5606    __ Bind(slow_path->GetReturnLabel());
5607  } else {
5608    __ j(kEqual, codegen_->GetLabelOf(successor));
5609    __ jmp(slow_path->GetEntryLabel());
5610  }
5611}
5612
5613X86Assembler* ParallelMoveResolverX86::GetAssembler() const {
5614  return codegen_->GetAssembler();
5615}
5616
5617void ParallelMoveResolverX86::MoveMemoryToMemory32(int dst, int src) {
5618  ScratchRegisterScope ensure_scratch(
5619      this, kNoRegister, EAX, codegen_->GetNumberOfCoreRegisters());
5620  Register temp_reg = static_cast<Register>(ensure_scratch.GetRegister());
5621  int stack_offset = ensure_scratch.IsSpilled() ? kX86WordSize : 0;
5622  __ movl(temp_reg, Address(ESP, src + stack_offset));
5623  __ movl(Address(ESP, dst + stack_offset), temp_reg);
5624}
5625
5626void ParallelMoveResolverX86::MoveMemoryToMemory64(int dst, int src) {
5627  ScratchRegisterScope ensure_scratch(
5628      this, kNoRegister, EAX, codegen_->GetNumberOfCoreRegisters());
5629  Register temp_reg = static_cast<Register>(ensure_scratch.GetRegister());
5630  int stack_offset = ensure_scratch.IsSpilled() ? kX86WordSize : 0;
5631  __ movl(temp_reg, Address(ESP, src + stack_offset));
5632  __ movl(Address(ESP, dst + stack_offset), temp_reg);
5633  __ movl(temp_reg, Address(ESP, src + stack_offset + kX86WordSize));
5634  __ movl(Address(ESP, dst + stack_offset + kX86WordSize), temp_reg);
5635}
5636
5637void ParallelMoveResolverX86::EmitMove(size_t index) {
5638  MoveOperands* move = moves_[index];
5639  Location source = move->GetSource();
5640  Location destination = move->GetDestination();
5641
5642  if (source.IsRegister()) {
5643    if (destination.IsRegister()) {
5644      __ movl(destination.AsRegister<Register>(), source.AsRegister<Register>());
5645    } else if (destination.IsFpuRegister()) {
5646      __ movd(destination.AsFpuRegister<XmmRegister>(), source.AsRegister<Register>());
5647    } else {
5648      DCHECK(destination.IsStackSlot());
5649      __ movl(Address(ESP, destination.GetStackIndex()), source.AsRegister<Register>());
5650    }
5651  } else if (source.IsRegisterPair()) {
5652      size_t elem_size = Primitive::ComponentSize(Primitive::kPrimInt);
5653      // Create stack space for 2 elements.
5654      __ subl(ESP, Immediate(2 * elem_size));
5655      __ movl(Address(ESP, 0), source.AsRegisterPairLow<Register>());
5656      __ movl(Address(ESP, elem_size), source.AsRegisterPairHigh<Register>());
5657      __ movsd(destination.AsFpuRegister<XmmRegister>(), Address(ESP, 0));
5658      // And remove the temporary stack space we allocated.
5659      __ addl(ESP, Immediate(2 * elem_size));
5660  } else if (source.IsFpuRegister()) {
5661    if (destination.IsRegister()) {
5662      __ movd(destination.AsRegister<Register>(), source.AsFpuRegister<XmmRegister>());
5663    } else if (destination.IsFpuRegister()) {
5664      __ movaps(destination.AsFpuRegister<XmmRegister>(), source.AsFpuRegister<XmmRegister>());
5665    } else if (destination.IsRegisterPair()) {
5666      XmmRegister src_reg = source.AsFpuRegister<XmmRegister>();
5667      __ movd(destination.AsRegisterPairLow<Register>(), src_reg);
5668      __ psrlq(src_reg, Immediate(32));
5669      __ movd(destination.AsRegisterPairHigh<Register>(), src_reg);
5670    } else if (destination.IsStackSlot()) {
5671      __ movss(Address(ESP, destination.GetStackIndex()), source.AsFpuRegister<XmmRegister>());
5672    } else {
5673      DCHECK(destination.IsDoubleStackSlot());
5674      __ movsd(Address(ESP, destination.GetStackIndex()), source.AsFpuRegister<XmmRegister>());
5675    }
5676  } else if (source.IsStackSlot()) {
5677    if (destination.IsRegister()) {
5678      __ movl(destination.AsRegister<Register>(), Address(ESP, source.GetStackIndex()));
5679    } else if (destination.IsFpuRegister()) {
5680      __ movss(destination.AsFpuRegister<XmmRegister>(), Address(ESP, source.GetStackIndex()));
5681    } else {
5682      DCHECK(destination.IsStackSlot());
5683      MoveMemoryToMemory32(destination.GetStackIndex(), source.GetStackIndex());
5684    }
5685  } else if (source.IsDoubleStackSlot()) {
5686    if (destination.IsRegisterPair()) {
5687      __ movl(destination.AsRegisterPairLow<Register>(), Address(ESP, source.GetStackIndex()));
5688      __ movl(destination.AsRegisterPairHigh<Register>(),
5689              Address(ESP, source.GetHighStackIndex(kX86WordSize)));
5690    } else if (destination.IsFpuRegister()) {
5691      __ movsd(destination.AsFpuRegister<XmmRegister>(), Address(ESP, source.GetStackIndex()));
5692    } else {
5693      DCHECK(destination.IsDoubleStackSlot()) << destination;
5694      MoveMemoryToMemory64(destination.GetStackIndex(), source.GetStackIndex());
5695    }
5696  } else if (source.IsConstant()) {
5697    HConstant* constant = source.GetConstant();
5698    if (constant->IsIntConstant() || constant->IsNullConstant()) {
5699      int32_t value = CodeGenerator::GetInt32ValueOf(constant);
5700      if (destination.IsRegister()) {
5701        if (value == 0) {
5702          __ xorl(destination.AsRegister<Register>(), destination.AsRegister<Register>());
5703        } else {
5704          __ movl(destination.AsRegister<Register>(), Immediate(value));
5705        }
5706      } else {
5707        DCHECK(destination.IsStackSlot()) << destination;
5708        __ movl(Address(ESP, destination.GetStackIndex()), Immediate(value));
5709      }
5710    } else if (constant->IsFloatConstant()) {
5711      float fp_value = constant->AsFloatConstant()->GetValue();
5712      int32_t value = bit_cast<int32_t, float>(fp_value);
5713      Immediate imm(value);
5714      if (destination.IsFpuRegister()) {
5715        XmmRegister dest = destination.AsFpuRegister<XmmRegister>();
5716        if (value == 0) {
5717          // Easy handling of 0.0.
5718          __ xorps(dest, dest);
5719        } else {
5720          ScratchRegisterScope ensure_scratch(
5721              this, kNoRegister, EAX, codegen_->GetNumberOfCoreRegisters());
5722          Register temp = static_cast<Register>(ensure_scratch.GetRegister());
5723          __ movl(temp, Immediate(value));
5724          __ movd(dest, temp);
5725        }
5726      } else {
5727        DCHECK(destination.IsStackSlot()) << destination;
5728        __ movl(Address(ESP, destination.GetStackIndex()), imm);
5729      }
5730    } else if (constant->IsLongConstant()) {
5731      int64_t value = constant->AsLongConstant()->GetValue();
5732      int32_t low_value = Low32Bits(value);
5733      int32_t high_value = High32Bits(value);
5734      Immediate low(low_value);
5735      Immediate high(high_value);
5736      if (destination.IsDoubleStackSlot()) {
5737        __ movl(Address(ESP, destination.GetStackIndex()), low);
5738        __ movl(Address(ESP, destination.GetHighStackIndex(kX86WordSize)), high);
5739      } else {
5740        __ movl(destination.AsRegisterPairLow<Register>(), low);
5741        __ movl(destination.AsRegisterPairHigh<Register>(), high);
5742      }
5743    } else {
5744      DCHECK(constant->IsDoubleConstant());
5745      double dbl_value = constant->AsDoubleConstant()->GetValue();
5746      int64_t value = bit_cast<int64_t, double>(dbl_value);
5747      int32_t low_value = Low32Bits(value);
5748      int32_t high_value = High32Bits(value);
5749      Immediate low(low_value);
5750      Immediate high(high_value);
5751      if (destination.IsFpuRegister()) {
5752        XmmRegister dest = destination.AsFpuRegister<XmmRegister>();
5753        if (value == 0) {
5754          // Easy handling of 0.0.
5755          __ xorpd(dest, dest);
5756        } else {
5757          __ pushl(high);
5758          __ pushl(low);
5759          __ movsd(dest, Address(ESP, 0));
5760          __ addl(ESP, Immediate(8));
5761        }
5762      } else {
5763        DCHECK(destination.IsDoubleStackSlot()) << destination;
5764        __ movl(Address(ESP, destination.GetStackIndex()), low);
5765        __ movl(Address(ESP, destination.GetHighStackIndex(kX86WordSize)), high);
5766      }
5767    }
5768  } else {
5769    LOG(FATAL) << "Unimplemented move: " << destination << " <- " << source;
5770  }
5771}
5772
5773void ParallelMoveResolverX86::Exchange(Register reg, int mem) {
5774  Register suggested_scratch = reg == EAX ? EBX : EAX;
5775  ScratchRegisterScope ensure_scratch(
5776      this, reg, suggested_scratch, codegen_->GetNumberOfCoreRegisters());
5777
5778  int stack_offset = ensure_scratch.IsSpilled() ? kX86WordSize : 0;
5779  __ movl(static_cast<Register>(ensure_scratch.GetRegister()), Address(ESP, mem + stack_offset));
5780  __ movl(Address(ESP, mem + stack_offset), reg);
5781  __ movl(reg, static_cast<Register>(ensure_scratch.GetRegister()));
5782}
5783
5784void ParallelMoveResolverX86::Exchange32(XmmRegister reg, int mem) {
5785  ScratchRegisterScope ensure_scratch(
5786      this, kNoRegister, EAX, codegen_->GetNumberOfCoreRegisters());
5787
5788  Register temp_reg = static_cast<Register>(ensure_scratch.GetRegister());
5789  int stack_offset = ensure_scratch.IsSpilled() ? kX86WordSize : 0;
5790  __ movl(temp_reg, Address(ESP, mem + stack_offset));
5791  __ movss(Address(ESP, mem + stack_offset), reg);
5792  __ movd(reg, temp_reg);
5793}
5794
5795void ParallelMoveResolverX86::Exchange(int mem1, int mem2) {
5796  ScratchRegisterScope ensure_scratch1(
5797      this, kNoRegister, EAX, codegen_->GetNumberOfCoreRegisters());
5798
5799  Register suggested_scratch = ensure_scratch1.GetRegister() == EAX ? EBX : EAX;
5800  ScratchRegisterScope ensure_scratch2(
5801      this, ensure_scratch1.GetRegister(), suggested_scratch, codegen_->GetNumberOfCoreRegisters());
5802
5803  int stack_offset = ensure_scratch1.IsSpilled() ? kX86WordSize : 0;
5804  stack_offset += ensure_scratch2.IsSpilled() ? kX86WordSize : 0;
5805  __ movl(static_cast<Register>(ensure_scratch1.GetRegister()), Address(ESP, mem1 + stack_offset));
5806  __ movl(static_cast<Register>(ensure_scratch2.GetRegister()), Address(ESP, mem2 + stack_offset));
5807  __ movl(Address(ESP, mem2 + stack_offset), static_cast<Register>(ensure_scratch1.GetRegister()));
5808  __ movl(Address(ESP, mem1 + stack_offset), static_cast<Register>(ensure_scratch2.GetRegister()));
5809}
5810
5811void ParallelMoveResolverX86::EmitSwap(size_t index) {
5812  MoveOperands* move = moves_[index];
5813  Location source = move->GetSource();
5814  Location destination = move->GetDestination();
5815
5816  if (source.IsRegister() && destination.IsRegister()) {
5817    // Use XOR swap algorithm to avoid serializing XCHG instruction or using a temporary.
5818    DCHECK_NE(destination.AsRegister<Register>(), source.AsRegister<Register>());
5819    __ xorl(destination.AsRegister<Register>(), source.AsRegister<Register>());
5820    __ xorl(source.AsRegister<Register>(), destination.AsRegister<Register>());
5821    __ xorl(destination.AsRegister<Register>(), source.AsRegister<Register>());
5822  } else if (source.IsRegister() && destination.IsStackSlot()) {
5823    Exchange(source.AsRegister<Register>(), destination.GetStackIndex());
5824  } else if (source.IsStackSlot() && destination.IsRegister()) {
5825    Exchange(destination.AsRegister<Register>(), source.GetStackIndex());
5826  } else if (source.IsStackSlot() && destination.IsStackSlot()) {
5827    Exchange(destination.GetStackIndex(), source.GetStackIndex());
5828  } else if (source.IsFpuRegister() && destination.IsFpuRegister()) {
5829    // Use XOR Swap algorithm to avoid a temporary.
5830    DCHECK_NE(source.reg(), destination.reg());
5831    __ xorpd(destination.AsFpuRegister<XmmRegister>(), source.AsFpuRegister<XmmRegister>());
5832    __ xorpd(source.AsFpuRegister<XmmRegister>(), destination.AsFpuRegister<XmmRegister>());
5833    __ xorpd(destination.AsFpuRegister<XmmRegister>(), source.AsFpuRegister<XmmRegister>());
5834  } else if (source.IsFpuRegister() && destination.IsStackSlot()) {
5835    Exchange32(source.AsFpuRegister<XmmRegister>(), destination.GetStackIndex());
5836  } else if (destination.IsFpuRegister() && source.IsStackSlot()) {
5837    Exchange32(destination.AsFpuRegister<XmmRegister>(), source.GetStackIndex());
5838  } else if (source.IsFpuRegister() && destination.IsDoubleStackSlot()) {
5839    // Take advantage of the 16 bytes in the XMM register.
5840    XmmRegister reg = source.AsFpuRegister<XmmRegister>();
5841    Address stack(ESP, destination.GetStackIndex());
5842    // Load the double into the high doubleword.
5843    __ movhpd(reg, stack);
5844
5845    // Store the low double into the destination.
5846    __ movsd(stack, reg);
5847
5848    // Move the high double to the low double.
5849    __ psrldq(reg, Immediate(8));
5850  } else if (destination.IsFpuRegister() && source.IsDoubleStackSlot()) {
5851    // Take advantage of the 16 bytes in the XMM register.
5852    XmmRegister reg = destination.AsFpuRegister<XmmRegister>();
5853    Address stack(ESP, source.GetStackIndex());
5854    // Load the double into the high doubleword.
5855    __ movhpd(reg, stack);
5856
5857    // Store the low double into the destination.
5858    __ movsd(stack, reg);
5859
5860    // Move the high double to the low double.
5861    __ psrldq(reg, Immediate(8));
5862  } else if (destination.IsDoubleStackSlot() && source.IsDoubleStackSlot()) {
5863    Exchange(destination.GetStackIndex(), source.GetStackIndex());
5864    Exchange(destination.GetHighStackIndex(kX86WordSize), source.GetHighStackIndex(kX86WordSize));
5865  } else {
5866    LOG(FATAL) << "Unimplemented: source: " << source << ", destination: " << destination;
5867  }
5868}
5869
5870void ParallelMoveResolverX86::SpillScratch(int reg) {
5871  __ pushl(static_cast<Register>(reg));
5872}
5873
5874void ParallelMoveResolverX86::RestoreScratch(int reg) {
5875  __ popl(static_cast<Register>(reg));
5876}
5877
5878void LocationsBuilderX86::VisitLoadClass(HLoadClass* cls) {
5879  InvokeRuntimeCallingConvention calling_convention;
5880  CodeGenerator::CreateLoadClassLocationSummary(
5881      cls,
5882      Location::RegisterLocation(calling_convention.GetRegisterAt(0)),
5883      Location::RegisterLocation(EAX),
5884      /* code_generator_supports_read_barrier */ true);
5885}
5886
5887void InstructionCodeGeneratorX86::VisitLoadClass(HLoadClass* cls) {
5888  LocationSummary* locations = cls->GetLocations();
5889  if (cls->NeedsAccessCheck()) {
5890    codegen_->MoveConstant(locations->GetTemp(0), cls->GetTypeIndex());
5891    codegen_->InvokeRuntime(QUICK_ENTRY_POINT(pInitializeTypeAndVerifyAccess),
5892                            cls,
5893                            cls->GetDexPc(),
5894                            nullptr);
5895    CheckEntrypointTypes<kQuickInitializeTypeAndVerifyAccess, void*, uint32_t>();
5896    return;
5897  }
5898
5899  Location out_loc = locations->Out();
5900  Register out = out_loc.AsRegister<Register>();
5901  Register current_method = locations->InAt(0).AsRegister<Register>();
5902
5903  if (cls->IsReferrersClass()) {
5904    DCHECK(!cls->CanCallRuntime());
5905    DCHECK(!cls->MustGenerateClinitCheck());
5906    // /* GcRoot<mirror::Class> */ out = current_method->declaring_class_
5907    GenerateGcRootFieldLoad(
5908        cls, out_loc, Address(current_method, ArtMethod::DeclaringClassOffset().Int32Value()));
5909  } else {
5910    // /* GcRoot<mirror::Class>[] */ out =
5911    //        current_method.ptr_sized_fields_->dex_cache_resolved_types_
5912    __ movl(out, Address(current_method,
5913                         ArtMethod::DexCacheResolvedTypesOffset(kX86PointerSize).Int32Value()));
5914    // /* GcRoot<mirror::Class> */ out = out[type_index]
5915    GenerateGcRootFieldLoad(
5916        cls, out_loc, Address(out, CodeGenerator::GetCacheOffset(cls->GetTypeIndex())));
5917
5918    if (!cls->IsInDexCache() || cls->MustGenerateClinitCheck()) {
5919      DCHECK(cls->CanCallRuntime());
5920      SlowPathCode* slow_path = new (GetGraph()->GetArena()) LoadClassSlowPathX86(
5921          cls, cls, cls->GetDexPc(), cls->MustGenerateClinitCheck());
5922      codegen_->AddSlowPath(slow_path);
5923
5924      if (!cls->IsInDexCache()) {
5925        __ testl(out, out);
5926        __ j(kEqual, slow_path->GetEntryLabel());
5927      }
5928
5929      if (cls->MustGenerateClinitCheck()) {
5930        GenerateClassInitializationCheck(slow_path, out);
5931      } else {
5932        __ Bind(slow_path->GetExitLabel());
5933      }
5934    }
5935  }
5936}
5937
5938void LocationsBuilderX86::VisitClinitCheck(HClinitCheck* check) {
5939  LocationSummary* locations =
5940      new (GetGraph()->GetArena()) LocationSummary(check, LocationSummary::kCallOnSlowPath);
5941  locations->SetInAt(0, Location::RequiresRegister());
5942  if (check->HasUses()) {
5943    locations->SetOut(Location::SameAsFirstInput());
5944  }
5945}
5946
5947void InstructionCodeGeneratorX86::VisitClinitCheck(HClinitCheck* check) {
5948  // We assume the class to not be null.
5949  SlowPathCode* slow_path = new (GetGraph()->GetArena()) LoadClassSlowPathX86(
5950      check->GetLoadClass(), check, check->GetDexPc(), true);
5951  codegen_->AddSlowPath(slow_path);
5952  GenerateClassInitializationCheck(slow_path,
5953                                   check->GetLocations()->InAt(0).AsRegister<Register>());
5954}
5955
5956void InstructionCodeGeneratorX86::GenerateClassInitializationCheck(
5957    SlowPathCode* slow_path, Register class_reg) {
5958  __ cmpl(Address(class_reg,  mirror::Class::StatusOffset().Int32Value()),
5959          Immediate(mirror::Class::kStatusInitialized));
5960  __ j(kLess, slow_path->GetEntryLabel());
5961  __ Bind(slow_path->GetExitLabel());
5962  // No need for memory fence, thanks to the X86 memory model.
5963}
5964
5965HLoadString::LoadKind CodeGeneratorX86::GetSupportedLoadStringKind(
5966    HLoadString::LoadKind desired_string_load_kind) {
5967  if (kEmitCompilerReadBarrier) {
5968    switch (desired_string_load_kind) {
5969      case HLoadString::LoadKind::kBootImageLinkTimeAddress:
5970      case HLoadString::LoadKind::kBootImageLinkTimePcRelative:
5971      case HLoadString::LoadKind::kBootImageAddress:
5972        // TODO: Implement for read barrier.
5973        return HLoadString::LoadKind::kDexCacheViaMethod;
5974      default:
5975        break;
5976    }
5977  }
5978  switch (desired_string_load_kind) {
5979    case HLoadString::LoadKind::kBootImageLinkTimeAddress:
5980      DCHECK(!GetCompilerOptions().GetCompilePic());
5981      break;
5982    case HLoadString::LoadKind::kBootImageLinkTimePcRelative:
5983      DCHECK(GetCompilerOptions().GetCompilePic());
5984      FALLTHROUGH_INTENDED;
5985    case HLoadString::LoadKind::kDexCachePcRelative:
5986      DCHECK(!Runtime::Current()->UseJitCompilation());  // Note: boot image is also non-JIT.
5987      // We disable pc-relative load when there is an irreducible loop, as the optimization
5988      // is incompatible with it.
5989      // TODO: Create as many X86ComputeBaseMethodAddress instructions as needed for methods
5990      // with irreducible loops.
5991      if (GetGraph()->HasIrreducibleLoops()) {
5992        return HLoadString::LoadKind::kDexCacheViaMethod;
5993      }
5994      break;
5995    case HLoadString::LoadKind::kBootImageAddress:
5996      break;
5997    case HLoadString::LoadKind::kDexCacheAddress:
5998      DCHECK(Runtime::Current()->UseJitCompilation());
5999      break;
6000    case HLoadString::LoadKind::kDexCacheViaMethod:
6001      break;
6002  }
6003  return desired_string_load_kind;
6004}
6005
6006void LocationsBuilderX86::VisitLoadString(HLoadString* load) {
6007  LocationSummary::CallKind call_kind = (load->NeedsEnvironment() || kEmitCompilerReadBarrier)
6008      ? LocationSummary::kCallOnSlowPath
6009      : LocationSummary::kNoCall;
6010  LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(load, call_kind);
6011  HLoadString::LoadKind load_kind = load->GetLoadKind();
6012  if (load_kind == HLoadString::LoadKind::kDexCacheViaMethod ||
6013      load_kind == HLoadString::LoadKind::kBootImageLinkTimePcRelative ||
6014      load_kind == HLoadString::LoadKind::kDexCachePcRelative) {
6015    locations->SetInAt(0, Location::RequiresRegister());
6016  }
6017  locations->SetOut(Location::RequiresRegister());
6018}
6019
6020void InstructionCodeGeneratorX86::VisitLoadString(HLoadString* load) {
6021  LocationSummary* locations = load->GetLocations();
6022  Location out_loc = locations->Out();
6023  Register out = out_loc.AsRegister<Register>();
6024
6025  switch (load->GetLoadKind()) {
6026    case HLoadString::LoadKind::kBootImageLinkTimeAddress: {
6027      DCHECK(!kEmitCompilerReadBarrier);
6028      __ movl(out, Immediate(/* placeholder */ 0));
6029      codegen_->RecordStringPatch(load);
6030      return;  // No dex cache slow path.
6031    }
6032    case HLoadString::LoadKind::kBootImageLinkTimePcRelative: {
6033      DCHECK(!kEmitCompilerReadBarrier);
6034      Register method_address = locations->InAt(0).AsRegister<Register>();
6035      __ leal(out, Address(method_address, CodeGeneratorX86::kDummy32BitOffset));
6036      codegen_->RecordStringPatch(load);
6037      return;  // No dex cache slow path.
6038    }
6039    case HLoadString::LoadKind::kBootImageAddress: {
6040      DCHECK(!kEmitCompilerReadBarrier);
6041      DCHECK_NE(load->GetAddress(), 0u);
6042      uint32_t address = dchecked_integral_cast<uint32_t>(load->GetAddress());
6043      __ movl(out, Immediate(address));
6044      codegen_->RecordSimplePatch();
6045      return;  // No dex cache slow path.
6046    }
6047    case HLoadString::LoadKind::kDexCacheAddress: {
6048      DCHECK_NE(load->GetAddress(), 0u);
6049      uint32_t address = dchecked_integral_cast<uint32_t>(load->GetAddress());
6050      GenerateGcRootFieldLoad(load, out_loc, Address::Absolute(address));
6051      break;
6052    }
6053    case HLoadString::LoadKind::kDexCachePcRelative: {
6054      Register base_reg = locations->InAt(0).AsRegister<Register>();
6055      uint32_t offset = load->GetDexCacheElementOffset();
6056      Label* fixup_label = codegen_->NewPcRelativeDexCacheArrayPatch(load->GetDexFile(), offset);
6057      GenerateGcRootFieldLoad(
6058          load, out_loc, Address(base_reg, CodeGeneratorX86::kDummy32BitOffset), fixup_label);
6059      break;
6060    }
6061    case HLoadString::LoadKind::kDexCacheViaMethod: {
6062      Register current_method = locations->InAt(0).AsRegister<Register>();
6063
6064      // /* GcRoot<mirror::Class> */ out = current_method->declaring_class_
6065      GenerateGcRootFieldLoad(
6066          load, out_loc, Address(current_method, ArtMethod::DeclaringClassOffset().Int32Value()));
6067
6068      // /* GcRoot<mirror::String>[] */ out = out->dex_cache_strings_
6069      __ movl(out, Address(out, mirror::Class::DexCacheStringsOffset().Int32Value()));
6070      // /* GcRoot<mirror::String> */ out = out[string_index]
6071      GenerateGcRootFieldLoad(
6072          load, out_loc, Address(out, CodeGenerator::GetCacheOffset(load->GetStringIndex())));
6073      break;
6074    }
6075    default:
6076      LOG(FATAL) << "Unexpected load kind: " << load->GetLoadKind();
6077      UNREACHABLE();
6078  }
6079
6080  if (!load->IsInDexCache()) {
6081    SlowPathCode* slow_path = new (GetGraph()->GetArena()) LoadStringSlowPathX86(load);
6082    codegen_->AddSlowPath(slow_path);
6083    __ testl(out, out);
6084    __ j(kEqual, slow_path->GetEntryLabel());
6085    __ Bind(slow_path->GetExitLabel());
6086  }
6087}
6088
6089static Address GetExceptionTlsAddress() {
6090  return Address::Absolute(Thread::ExceptionOffset<kX86WordSize>().Int32Value());
6091}
6092
6093void LocationsBuilderX86::VisitLoadException(HLoadException* load) {
6094  LocationSummary* locations =
6095      new (GetGraph()->GetArena()) LocationSummary(load, LocationSummary::kNoCall);
6096  locations->SetOut(Location::RequiresRegister());
6097}
6098
6099void InstructionCodeGeneratorX86::VisitLoadException(HLoadException* load) {
6100  __ fs()->movl(load->GetLocations()->Out().AsRegister<Register>(), GetExceptionTlsAddress());
6101}
6102
6103void LocationsBuilderX86::VisitClearException(HClearException* clear) {
6104  new (GetGraph()->GetArena()) LocationSummary(clear, LocationSummary::kNoCall);
6105}
6106
6107void InstructionCodeGeneratorX86::VisitClearException(HClearException* clear ATTRIBUTE_UNUSED) {
6108  __ fs()->movl(GetExceptionTlsAddress(), Immediate(0));
6109}
6110
6111void LocationsBuilderX86::VisitThrow(HThrow* instruction) {
6112  LocationSummary* locations =
6113      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCall);
6114  InvokeRuntimeCallingConvention calling_convention;
6115  locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0)));
6116}
6117
6118void InstructionCodeGeneratorX86::VisitThrow(HThrow* instruction) {
6119  codegen_->InvokeRuntime(QUICK_ENTRY_POINT(pDeliverException),
6120                          instruction,
6121                          instruction->GetDexPc(),
6122                          nullptr);
6123  CheckEntrypointTypes<kQuickDeliverException, void, mirror::Object*>();
6124}
6125
6126static bool TypeCheckNeedsATemporary(TypeCheckKind type_check_kind) {
6127  return kEmitCompilerReadBarrier &&
6128      (kUseBakerReadBarrier ||
6129       type_check_kind == TypeCheckKind::kAbstractClassCheck ||
6130       type_check_kind == TypeCheckKind::kClassHierarchyCheck ||
6131       type_check_kind == TypeCheckKind::kArrayObjectCheck);
6132}
6133
6134void LocationsBuilderX86::VisitInstanceOf(HInstanceOf* instruction) {
6135  LocationSummary::CallKind call_kind = LocationSummary::kNoCall;
6136  TypeCheckKind type_check_kind = instruction->GetTypeCheckKind();
6137  switch (type_check_kind) {
6138    case TypeCheckKind::kExactCheck:
6139    case TypeCheckKind::kAbstractClassCheck:
6140    case TypeCheckKind::kClassHierarchyCheck:
6141    case TypeCheckKind::kArrayObjectCheck:
6142      call_kind =
6143          kEmitCompilerReadBarrier ? LocationSummary::kCallOnSlowPath : LocationSummary::kNoCall;
6144      break;
6145    case TypeCheckKind::kArrayCheck:
6146    case TypeCheckKind::kUnresolvedCheck:
6147    case TypeCheckKind::kInterfaceCheck:
6148      call_kind = LocationSummary::kCallOnSlowPath;
6149      break;
6150  }
6151
6152  LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, call_kind);
6153  locations->SetInAt(0, Location::RequiresRegister());
6154  locations->SetInAt(1, Location::Any());
6155  // Note that TypeCheckSlowPathX86 uses this "out" register too.
6156  locations->SetOut(Location::RequiresRegister());
6157  // When read barriers are enabled, we need a temporary register for
6158  // some cases.
6159  if (TypeCheckNeedsATemporary(type_check_kind)) {
6160    locations->AddTemp(Location::RequiresRegister());
6161  }
6162}
6163
6164void InstructionCodeGeneratorX86::VisitInstanceOf(HInstanceOf* instruction) {
6165  TypeCheckKind type_check_kind = instruction->GetTypeCheckKind();
6166  LocationSummary* locations = instruction->GetLocations();
6167  Location obj_loc = locations->InAt(0);
6168  Register obj = obj_loc.AsRegister<Register>();
6169  Location cls = locations->InAt(1);
6170  Location out_loc = locations->Out();
6171  Register out = out_loc.AsRegister<Register>();
6172  Location maybe_temp_loc = TypeCheckNeedsATemporary(type_check_kind) ?
6173      locations->GetTemp(0) :
6174      Location::NoLocation();
6175  uint32_t class_offset = mirror::Object::ClassOffset().Int32Value();
6176  uint32_t super_offset = mirror::Class::SuperClassOffset().Int32Value();
6177  uint32_t component_offset = mirror::Class::ComponentTypeOffset().Int32Value();
6178  uint32_t primitive_offset = mirror::Class::PrimitiveTypeOffset().Int32Value();
6179  SlowPathCode* slow_path = nullptr;
6180  NearLabel done, zero;
6181
6182  // Return 0 if `obj` is null.
6183  // Avoid null check if we know obj is not null.
6184  if (instruction->MustDoNullCheck()) {
6185    __ testl(obj, obj);
6186    __ j(kEqual, &zero);
6187  }
6188
6189  // /* HeapReference<Class> */ out = obj->klass_
6190  GenerateReferenceLoadTwoRegisters(instruction, out_loc, obj_loc, class_offset, maybe_temp_loc);
6191
6192  switch (type_check_kind) {
6193    case TypeCheckKind::kExactCheck: {
6194      if (cls.IsRegister()) {
6195        __ cmpl(out, cls.AsRegister<Register>());
6196      } else {
6197        DCHECK(cls.IsStackSlot()) << cls;
6198        __ cmpl(out, Address(ESP, cls.GetStackIndex()));
6199      }
6200
6201      // Classes must be equal for the instanceof to succeed.
6202      __ j(kNotEqual, &zero);
6203      __ movl(out, Immediate(1));
6204      __ jmp(&done);
6205      break;
6206    }
6207
6208    case TypeCheckKind::kAbstractClassCheck: {
6209      // If the class is abstract, we eagerly fetch the super class of the
6210      // object to avoid doing a comparison we know will fail.
6211      NearLabel loop;
6212      __ Bind(&loop);
6213      // /* HeapReference<Class> */ out = out->super_class_
6214      GenerateReferenceLoadOneRegister(instruction, out_loc, super_offset, maybe_temp_loc);
6215      __ testl(out, out);
6216      // If `out` is null, we use it for the result, and jump to `done`.
6217      __ j(kEqual, &done);
6218      if (cls.IsRegister()) {
6219        __ cmpl(out, cls.AsRegister<Register>());
6220      } else {
6221        DCHECK(cls.IsStackSlot()) << cls;
6222        __ cmpl(out, Address(ESP, cls.GetStackIndex()));
6223      }
6224      __ j(kNotEqual, &loop);
6225      __ movl(out, Immediate(1));
6226      if (zero.IsLinked()) {
6227        __ jmp(&done);
6228      }
6229      break;
6230    }
6231
6232    case TypeCheckKind::kClassHierarchyCheck: {
6233      // Walk over the class hierarchy to find a match.
6234      NearLabel loop, success;
6235      __ Bind(&loop);
6236      if (cls.IsRegister()) {
6237        __ cmpl(out, cls.AsRegister<Register>());
6238      } else {
6239        DCHECK(cls.IsStackSlot()) << cls;
6240        __ cmpl(out, Address(ESP, cls.GetStackIndex()));
6241      }
6242      __ j(kEqual, &success);
6243      // /* HeapReference<Class> */ out = out->super_class_
6244      GenerateReferenceLoadOneRegister(instruction, out_loc, super_offset, maybe_temp_loc);
6245      __ testl(out, out);
6246      __ j(kNotEqual, &loop);
6247      // If `out` is null, we use it for the result, and jump to `done`.
6248      __ jmp(&done);
6249      __ Bind(&success);
6250      __ movl(out, Immediate(1));
6251      if (zero.IsLinked()) {
6252        __ jmp(&done);
6253      }
6254      break;
6255    }
6256
6257    case TypeCheckKind::kArrayObjectCheck: {
6258      // Do an exact check.
6259      NearLabel exact_check;
6260      if (cls.IsRegister()) {
6261        __ cmpl(out, cls.AsRegister<Register>());
6262      } else {
6263        DCHECK(cls.IsStackSlot()) << cls;
6264        __ cmpl(out, Address(ESP, cls.GetStackIndex()));
6265      }
6266      __ j(kEqual, &exact_check);
6267      // Otherwise, we need to check that the object's class is a non-primitive array.
6268      // /* HeapReference<Class> */ out = out->component_type_
6269      GenerateReferenceLoadOneRegister(instruction, out_loc, component_offset, maybe_temp_loc);
6270      __ testl(out, out);
6271      // If `out` is null, we use it for the result, and jump to `done`.
6272      __ j(kEqual, &done);
6273      __ cmpw(Address(out, primitive_offset), Immediate(Primitive::kPrimNot));
6274      __ j(kNotEqual, &zero);
6275      __ Bind(&exact_check);
6276      __ movl(out, Immediate(1));
6277      __ jmp(&done);
6278      break;
6279    }
6280
6281    case TypeCheckKind::kArrayCheck: {
6282      if (cls.IsRegister()) {
6283        __ cmpl(out, cls.AsRegister<Register>());
6284      } else {
6285        DCHECK(cls.IsStackSlot()) << cls;
6286        __ cmpl(out, Address(ESP, cls.GetStackIndex()));
6287      }
6288      DCHECK(locations->OnlyCallsOnSlowPath());
6289      slow_path = new (GetGraph()->GetArena()) TypeCheckSlowPathX86(instruction,
6290                                                                    /* is_fatal */ false);
6291      codegen_->AddSlowPath(slow_path);
6292      __ j(kNotEqual, slow_path->GetEntryLabel());
6293      __ movl(out, Immediate(1));
6294      if (zero.IsLinked()) {
6295        __ jmp(&done);
6296      }
6297      break;
6298    }
6299
6300    case TypeCheckKind::kUnresolvedCheck:
6301    case TypeCheckKind::kInterfaceCheck: {
6302      // Note that we indeed only call on slow path, but we always go
6303      // into the slow path for the unresolved and interface check
6304      // cases.
6305      //
6306      // We cannot directly call the InstanceofNonTrivial runtime
6307      // entry point without resorting to a type checking slow path
6308      // here (i.e. by calling InvokeRuntime directly), as it would
6309      // require to assign fixed registers for the inputs of this
6310      // HInstanceOf instruction (following the runtime calling
6311      // convention), which might be cluttered by the potential first
6312      // read barrier emission at the beginning of this method.
6313      //
6314      // TODO: Introduce a new runtime entry point taking the object
6315      // to test (instead of its class) as argument, and let it deal
6316      // with the read barrier issues. This will let us refactor this
6317      // case of the `switch` code as it was previously (with a direct
6318      // call to the runtime not using a type checking slow path).
6319      // This should also be beneficial for the other cases above.
6320      DCHECK(locations->OnlyCallsOnSlowPath());
6321      slow_path = new (GetGraph()->GetArena()) TypeCheckSlowPathX86(instruction,
6322                                                                    /* is_fatal */ false);
6323      codegen_->AddSlowPath(slow_path);
6324      __ jmp(slow_path->GetEntryLabel());
6325      if (zero.IsLinked()) {
6326        __ jmp(&done);
6327      }
6328      break;
6329    }
6330  }
6331
6332  if (zero.IsLinked()) {
6333    __ Bind(&zero);
6334    __ xorl(out, out);
6335  }
6336
6337  if (done.IsLinked()) {
6338    __ Bind(&done);
6339  }
6340
6341  if (slow_path != nullptr) {
6342    __ Bind(slow_path->GetExitLabel());
6343  }
6344}
6345
6346void LocationsBuilderX86::VisitCheckCast(HCheckCast* instruction) {
6347  LocationSummary::CallKind call_kind = LocationSummary::kNoCall;
6348  bool throws_into_catch = instruction->CanThrowIntoCatchBlock();
6349  TypeCheckKind type_check_kind = instruction->GetTypeCheckKind();
6350  switch (type_check_kind) {
6351    case TypeCheckKind::kExactCheck:
6352    case TypeCheckKind::kAbstractClassCheck:
6353    case TypeCheckKind::kClassHierarchyCheck:
6354    case TypeCheckKind::kArrayObjectCheck:
6355      call_kind = (throws_into_catch || kEmitCompilerReadBarrier) ?
6356          LocationSummary::kCallOnSlowPath :
6357          LocationSummary::kNoCall;  // In fact, call on a fatal (non-returning) slow path.
6358      break;
6359    case TypeCheckKind::kArrayCheck:
6360    case TypeCheckKind::kUnresolvedCheck:
6361    case TypeCheckKind::kInterfaceCheck:
6362      call_kind = LocationSummary::kCallOnSlowPath;
6363      break;
6364  }
6365  LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, call_kind);
6366  locations->SetInAt(0, Location::RequiresRegister());
6367  locations->SetInAt(1, Location::Any());
6368  // Note that TypeCheckSlowPathX86 uses this "temp" register too.
6369  locations->AddTemp(Location::RequiresRegister());
6370  // When read barriers are enabled, we need an additional temporary
6371  // register for some cases.
6372  if (TypeCheckNeedsATemporary(type_check_kind)) {
6373    locations->AddTemp(Location::RequiresRegister());
6374  }
6375}
6376
6377void InstructionCodeGeneratorX86::VisitCheckCast(HCheckCast* instruction) {
6378  TypeCheckKind type_check_kind = instruction->GetTypeCheckKind();
6379  LocationSummary* locations = instruction->GetLocations();
6380  Location obj_loc = locations->InAt(0);
6381  Register obj = obj_loc.AsRegister<Register>();
6382  Location cls = locations->InAt(1);
6383  Location temp_loc = locations->GetTemp(0);
6384  Register temp = temp_loc.AsRegister<Register>();
6385  Location maybe_temp2_loc = TypeCheckNeedsATemporary(type_check_kind) ?
6386      locations->GetTemp(1) :
6387      Location::NoLocation();
6388  uint32_t class_offset = mirror::Object::ClassOffset().Int32Value();
6389  uint32_t super_offset = mirror::Class::SuperClassOffset().Int32Value();
6390  uint32_t component_offset = mirror::Class::ComponentTypeOffset().Int32Value();
6391  uint32_t primitive_offset = mirror::Class::PrimitiveTypeOffset().Int32Value();
6392
6393  bool is_type_check_slow_path_fatal =
6394      (type_check_kind == TypeCheckKind::kExactCheck ||
6395       type_check_kind == TypeCheckKind::kAbstractClassCheck ||
6396       type_check_kind == TypeCheckKind::kClassHierarchyCheck ||
6397       type_check_kind == TypeCheckKind::kArrayObjectCheck) &&
6398      !instruction->CanThrowIntoCatchBlock();
6399  SlowPathCode* type_check_slow_path =
6400      new (GetGraph()->GetArena()) TypeCheckSlowPathX86(instruction,
6401                                                        is_type_check_slow_path_fatal);
6402  codegen_->AddSlowPath(type_check_slow_path);
6403
6404  NearLabel done;
6405  // Avoid null check if we know obj is not null.
6406  if (instruction->MustDoNullCheck()) {
6407    __ testl(obj, obj);
6408    __ j(kEqual, &done);
6409  }
6410
6411  // /* HeapReference<Class> */ temp = obj->klass_
6412  GenerateReferenceLoadTwoRegisters(instruction, temp_loc, obj_loc, class_offset, maybe_temp2_loc);
6413
6414  switch (type_check_kind) {
6415    case TypeCheckKind::kExactCheck:
6416    case TypeCheckKind::kArrayCheck: {
6417      if (cls.IsRegister()) {
6418        __ cmpl(temp, cls.AsRegister<Register>());
6419      } else {
6420        DCHECK(cls.IsStackSlot()) << cls;
6421        __ cmpl(temp, Address(ESP, cls.GetStackIndex()));
6422      }
6423      // Jump to slow path for throwing the exception or doing a
6424      // more involved array check.
6425      __ j(kNotEqual, type_check_slow_path->GetEntryLabel());
6426      break;
6427    }
6428
6429    case TypeCheckKind::kAbstractClassCheck: {
6430      // If the class is abstract, we eagerly fetch the super class of the
6431      // object to avoid doing a comparison we know will fail.
6432      NearLabel loop, compare_classes;
6433      __ Bind(&loop);
6434      // /* HeapReference<Class> */ temp = temp->super_class_
6435      GenerateReferenceLoadOneRegister(instruction, temp_loc, super_offset, maybe_temp2_loc);
6436
6437      // If the class reference currently in `temp` is not null, jump
6438      // to the `compare_classes` label to compare it with the checked
6439      // class.
6440      __ testl(temp, temp);
6441      __ j(kNotEqual, &compare_classes);
6442      // Otherwise, jump to the slow path to throw the exception.
6443      //
6444      // But before, move back the object's class into `temp` before
6445      // going into the slow path, as it has been overwritten in the
6446      // meantime.
6447      // /* HeapReference<Class> */ temp = obj->klass_
6448      GenerateReferenceLoadTwoRegisters(
6449          instruction, temp_loc, obj_loc, class_offset, maybe_temp2_loc);
6450      __ jmp(type_check_slow_path->GetEntryLabel());
6451
6452      __ Bind(&compare_classes);
6453      if (cls.IsRegister()) {
6454        __ cmpl(temp, cls.AsRegister<Register>());
6455      } else {
6456        DCHECK(cls.IsStackSlot()) << cls;
6457        __ cmpl(temp, Address(ESP, cls.GetStackIndex()));
6458      }
6459      __ j(kNotEqual, &loop);
6460      break;
6461    }
6462
6463    case TypeCheckKind::kClassHierarchyCheck: {
6464      // Walk over the class hierarchy to find a match.
6465      NearLabel loop;
6466      __ Bind(&loop);
6467      if (cls.IsRegister()) {
6468        __ cmpl(temp, cls.AsRegister<Register>());
6469      } else {
6470        DCHECK(cls.IsStackSlot()) << cls;
6471        __ cmpl(temp, Address(ESP, cls.GetStackIndex()));
6472      }
6473      __ j(kEqual, &done);
6474
6475      // /* HeapReference<Class> */ temp = temp->super_class_
6476      GenerateReferenceLoadOneRegister(instruction, temp_loc, super_offset, maybe_temp2_loc);
6477
6478      // If the class reference currently in `temp` is not null, jump
6479      // back at the beginning of the loop.
6480      __ testl(temp, temp);
6481      __ j(kNotEqual, &loop);
6482      // Otherwise, jump to the slow path to throw the exception.
6483      //
6484      // But before, move back the object's class into `temp` before
6485      // going into the slow path, as it has been overwritten in the
6486      // meantime.
6487      // /* HeapReference<Class> */ temp = obj->klass_
6488      GenerateReferenceLoadTwoRegisters(
6489          instruction, temp_loc, obj_loc, class_offset, maybe_temp2_loc);
6490      __ jmp(type_check_slow_path->GetEntryLabel());
6491      break;
6492    }
6493
6494    case TypeCheckKind::kArrayObjectCheck: {
6495      // Do an exact check.
6496      NearLabel check_non_primitive_component_type;
6497      if (cls.IsRegister()) {
6498        __ cmpl(temp, cls.AsRegister<Register>());
6499      } else {
6500        DCHECK(cls.IsStackSlot()) << cls;
6501        __ cmpl(temp, Address(ESP, cls.GetStackIndex()));
6502      }
6503      __ j(kEqual, &done);
6504
6505      // Otherwise, we need to check that the object's class is a non-primitive array.
6506      // /* HeapReference<Class> */ temp = temp->component_type_
6507      GenerateReferenceLoadOneRegister(instruction, temp_loc, component_offset, maybe_temp2_loc);
6508
6509      // If the component type is not null (i.e. the object is indeed
6510      // an array), jump to label `check_non_primitive_component_type`
6511      // to further check that this component type is not a primitive
6512      // type.
6513      __ testl(temp, temp);
6514      __ j(kNotEqual, &check_non_primitive_component_type);
6515      // Otherwise, jump to the slow path to throw the exception.
6516      //
6517      // But before, move back the object's class into `temp` before
6518      // going into the slow path, as it has been overwritten in the
6519      // meantime.
6520      // /* HeapReference<Class> */ temp = obj->klass_
6521      GenerateReferenceLoadTwoRegisters(
6522          instruction, temp_loc, obj_loc, class_offset, maybe_temp2_loc);
6523      __ jmp(type_check_slow_path->GetEntryLabel());
6524
6525      __ Bind(&check_non_primitive_component_type);
6526      __ cmpw(Address(temp, primitive_offset), Immediate(Primitive::kPrimNot));
6527      __ j(kEqual, &done);
6528      // Same comment as above regarding `temp` and the slow path.
6529      // /* HeapReference<Class> */ temp = obj->klass_
6530      GenerateReferenceLoadTwoRegisters(
6531          instruction, temp_loc, obj_loc, class_offset, maybe_temp2_loc);
6532      __ jmp(type_check_slow_path->GetEntryLabel());
6533      break;
6534    }
6535
6536    case TypeCheckKind::kUnresolvedCheck:
6537    case TypeCheckKind::kInterfaceCheck:
6538      // We always go into the type check slow path for the unresolved
6539      // and interface check cases.
6540      //
6541      // We cannot directly call the CheckCast runtime entry point
6542      // without resorting to a type checking slow path here (i.e. by
6543      // calling InvokeRuntime directly), as it would require to
6544      // assign fixed registers for the inputs of this HInstanceOf
6545      // instruction (following the runtime calling convention), which
6546      // might be cluttered by the potential first read barrier
6547      // emission at the beginning of this method.
6548      //
6549      // TODO: Introduce a new runtime entry point taking the object
6550      // to test (instead of its class) as argument, and let it deal
6551      // with the read barrier issues. This will let us refactor this
6552      // case of the `switch` code as it was previously (with a direct
6553      // call to the runtime not using a type checking slow path).
6554      // This should also be beneficial for the other cases above.
6555      __ jmp(type_check_slow_path->GetEntryLabel());
6556      break;
6557  }
6558  __ Bind(&done);
6559
6560  __ Bind(type_check_slow_path->GetExitLabel());
6561}
6562
6563void LocationsBuilderX86::VisitMonitorOperation(HMonitorOperation* instruction) {
6564  LocationSummary* locations =
6565      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCall);
6566  InvokeRuntimeCallingConvention calling_convention;
6567  locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0)));
6568}
6569
6570void InstructionCodeGeneratorX86::VisitMonitorOperation(HMonitorOperation* instruction) {
6571  codegen_->InvokeRuntime(instruction->IsEnter() ? QUICK_ENTRY_POINT(pLockObject)
6572                                                 : QUICK_ENTRY_POINT(pUnlockObject),
6573                          instruction,
6574                          instruction->GetDexPc(),
6575                          nullptr);
6576  if (instruction->IsEnter()) {
6577    CheckEntrypointTypes<kQuickLockObject, void, mirror::Object*>();
6578  } else {
6579    CheckEntrypointTypes<kQuickUnlockObject, void, mirror::Object*>();
6580  }
6581}
6582
6583void LocationsBuilderX86::VisitAnd(HAnd* instruction) { HandleBitwiseOperation(instruction); }
6584void LocationsBuilderX86::VisitOr(HOr* instruction) { HandleBitwiseOperation(instruction); }
6585void LocationsBuilderX86::VisitXor(HXor* instruction) { HandleBitwiseOperation(instruction); }
6586
6587void LocationsBuilderX86::HandleBitwiseOperation(HBinaryOperation* instruction) {
6588  LocationSummary* locations =
6589      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
6590  DCHECK(instruction->GetResultType() == Primitive::kPrimInt
6591         || instruction->GetResultType() == Primitive::kPrimLong);
6592  locations->SetInAt(0, Location::RequiresRegister());
6593  locations->SetInAt(1, Location::Any());
6594  locations->SetOut(Location::SameAsFirstInput());
6595}
6596
6597void InstructionCodeGeneratorX86::VisitAnd(HAnd* instruction) {
6598  HandleBitwiseOperation(instruction);
6599}
6600
6601void InstructionCodeGeneratorX86::VisitOr(HOr* instruction) {
6602  HandleBitwiseOperation(instruction);
6603}
6604
6605void InstructionCodeGeneratorX86::VisitXor(HXor* instruction) {
6606  HandleBitwiseOperation(instruction);
6607}
6608
6609void InstructionCodeGeneratorX86::HandleBitwiseOperation(HBinaryOperation* instruction) {
6610  LocationSummary* locations = instruction->GetLocations();
6611  Location first = locations->InAt(0);
6612  Location second = locations->InAt(1);
6613  DCHECK(first.Equals(locations->Out()));
6614
6615  if (instruction->GetResultType() == Primitive::kPrimInt) {
6616    if (second.IsRegister()) {
6617      if (instruction->IsAnd()) {
6618        __ andl(first.AsRegister<Register>(), second.AsRegister<Register>());
6619      } else if (instruction->IsOr()) {
6620        __ orl(first.AsRegister<Register>(), second.AsRegister<Register>());
6621      } else {
6622        DCHECK(instruction->IsXor());
6623        __ xorl(first.AsRegister<Register>(), second.AsRegister<Register>());
6624      }
6625    } else if (second.IsConstant()) {
6626      if (instruction->IsAnd()) {
6627        __ andl(first.AsRegister<Register>(),
6628                Immediate(second.GetConstant()->AsIntConstant()->GetValue()));
6629      } else if (instruction->IsOr()) {
6630        __ orl(first.AsRegister<Register>(),
6631               Immediate(second.GetConstant()->AsIntConstant()->GetValue()));
6632      } else {
6633        DCHECK(instruction->IsXor());
6634        __ xorl(first.AsRegister<Register>(),
6635                Immediate(second.GetConstant()->AsIntConstant()->GetValue()));
6636      }
6637    } else {
6638      if (instruction->IsAnd()) {
6639        __ andl(first.AsRegister<Register>(), Address(ESP, second.GetStackIndex()));
6640      } else if (instruction->IsOr()) {
6641        __ orl(first.AsRegister<Register>(), Address(ESP, second.GetStackIndex()));
6642      } else {
6643        DCHECK(instruction->IsXor());
6644        __ xorl(first.AsRegister<Register>(), Address(ESP, second.GetStackIndex()));
6645      }
6646    }
6647  } else {
6648    DCHECK_EQ(instruction->GetResultType(), Primitive::kPrimLong);
6649    if (second.IsRegisterPair()) {
6650      if (instruction->IsAnd()) {
6651        __ andl(first.AsRegisterPairLow<Register>(), second.AsRegisterPairLow<Register>());
6652        __ andl(first.AsRegisterPairHigh<Register>(), second.AsRegisterPairHigh<Register>());
6653      } else if (instruction->IsOr()) {
6654        __ orl(first.AsRegisterPairLow<Register>(), second.AsRegisterPairLow<Register>());
6655        __ orl(first.AsRegisterPairHigh<Register>(), second.AsRegisterPairHigh<Register>());
6656      } else {
6657        DCHECK(instruction->IsXor());
6658        __ xorl(first.AsRegisterPairLow<Register>(), second.AsRegisterPairLow<Register>());
6659        __ xorl(first.AsRegisterPairHigh<Register>(), second.AsRegisterPairHigh<Register>());
6660      }
6661    } else if (second.IsDoubleStackSlot()) {
6662      if (instruction->IsAnd()) {
6663        __ andl(first.AsRegisterPairLow<Register>(), Address(ESP, second.GetStackIndex()));
6664        __ andl(first.AsRegisterPairHigh<Register>(),
6665                Address(ESP, second.GetHighStackIndex(kX86WordSize)));
6666      } else if (instruction->IsOr()) {
6667        __ orl(first.AsRegisterPairLow<Register>(), Address(ESP, second.GetStackIndex()));
6668        __ orl(first.AsRegisterPairHigh<Register>(),
6669                Address(ESP, second.GetHighStackIndex(kX86WordSize)));
6670      } else {
6671        DCHECK(instruction->IsXor());
6672        __ xorl(first.AsRegisterPairLow<Register>(), Address(ESP, second.GetStackIndex()));
6673        __ xorl(first.AsRegisterPairHigh<Register>(),
6674                Address(ESP, second.GetHighStackIndex(kX86WordSize)));
6675      }
6676    } else {
6677      DCHECK(second.IsConstant()) << second;
6678      int64_t value = second.GetConstant()->AsLongConstant()->GetValue();
6679      int32_t low_value = Low32Bits(value);
6680      int32_t high_value = High32Bits(value);
6681      Immediate low(low_value);
6682      Immediate high(high_value);
6683      Register first_low = first.AsRegisterPairLow<Register>();
6684      Register first_high = first.AsRegisterPairHigh<Register>();
6685      if (instruction->IsAnd()) {
6686        if (low_value == 0) {
6687          __ xorl(first_low, first_low);
6688        } else if (low_value != -1) {
6689          __ andl(first_low, low);
6690        }
6691        if (high_value == 0) {
6692          __ xorl(first_high, first_high);
6693        } else if (high_value != -1) {
6694          __ andl(first_high, high);
6695        }
6696      } else if (instruction->IsOr()) {
6697        if (low_value != 0) {
6698          __ orl(first_low, low);
6699        }
6700        if (high_value != 0) {
6701          __ orl(first_high, high);
6702        }
6703      } else {
6704        DCHECK(instruction->IsXor());
6705        if (low_value != 0) {
6706          __ xorl(first_low, low);
6707        }
6708        if (high_value != 0) {
6709          __ xorl(first_high, high);
6710        }
6711      }
6712    }
6713  }
6714}
6715
6716void InstructionCodeGeneratorX86::GenerateReferenceLoadOneRegister(HInstruction* instruction,
6717                                                                   Location out,
6718                                                                   uint32_t offset,
6719                                                                   Location maybe_temp) {
6720  Register out_reg = out.AsRegister<Register>();
6721  if (kEmitCompilerReadBarrier) {
6722    DCHECK(maybe_temp.IsRegister()) << maybe_temp;
6723    if (kUseBakerReadBarrier) {
6724      // Load with fast path based Baker's read barrier.
6725      // /* HeapReference<Object> */ out = *(out + offset)
6726      codegen_->GenerateFieldLoadWithBakerReadBarrier(
6727          instruction, out, out_reg, offset, maybe_temp, /* needs_null_check */ false);
6728    } else {
6729      // Load with slow path based read barrier.
6730      // Save the value of `out` into `maybe_temp` before overwriting it
6731      // in the following move operation, as we will need it for the
6732      // read barrier below.
6733      __ movl(maybe_temp.AsRegister<Register>(), out_reg);
6734      // /* HeapReference<Object> */ out = *(out + offset)
6735      __ movl(out_reg, Address(out_reg, offset));
6736      codegen_->GenerateReadBarrierSlow(instruction, out, out, maybe_temp, offset);
6737    }
6738  } else {
6739    // Plain load with no read barrier.
6740    // /* HeapReference<Object> */ out = *(out + offset)
6741    __ movl(out_reg, Address(out_reg, offset));
6742    __ MaybeUnpoisonHeapReference(out_reg);
6743  }
6744}
6745
6746void InstructionCodeGeneratorX86::GenerateReferenceLoadTwoRegisters(HInstruction* instruction,
6747                                                                    Location out,
6748                                                                    Location obj,
6749                                                                    uint32_t offset,
6750                                                                    Location maybe_temp) {
6751  Register out_reg = out.AsRegister<Register>();
6752  Register obj_reg = obj.AsRegister<Register>();
6753  if (kEmitCompilerReadBarrier) {
6754    if (kUseBakerReadBarrier) {
6755      DCHECK(maybe_temp.IsRegister()) << maybe_temp;
6756      // Load with fast path based Baker's read barrier.
6757      // /* HeapReference<Object> */ out = *(obj + offset)
6758      codegen_->GenerateFieldLoadWithBakerReadBarrier(
6759          instruction, out, obj_reg, offset, maybe_temp, /* needs_null_check */ false);
6760    } else {
6761      // Load with slow path based read barrier.
6762      // /* HeapReference<Object> */ out = *(obj + offset)
6763      __ movl(out_reg, Address(obj_reg, offset));
6764      codegen_->GenerateReadBarrierSlow(instruction, out, out, obj, offset);
6765    }
6766  } else {
6767    // Plain load with no read barrier.
6768    // /* HeapReference<Object> */ out = *(obj + offset)
6769    __ movl(out_reg, Address(obj_reg, offset));
6770    __ MaybeUnpoisonHeapReference(out_reg);
6771  }
6772}
6773
6774void InstructionCodeGeneratorX86::GenerateGcRootFieldLoad(HInstruction* instruction,
6775                                                          Location root,
6776                                                          const Address& address,
6777                                                          Label* fixup_label) {
6778  Register root_reg = root.AsRegister<Register>();
6779  if (kEmitCompilerReadBarrier) {
6780    if (kUseBakerReadBarrier) {
6781      // Fast path implementation of art::ReadBarrier::BarrierForRoot when
6782      // Baker's read barrier are used:
6783      //
6784      //   root = *address;
6785      //   if (Thread::Current()->GetIsGcMarking()) {
6786      //     root = ReadBarrier::Mark(root)
6787      //   }
6788
6789      // /* GcRoot<mirror::Object> */ root = *address
6790      __ movl(root_reg, address);
6791      if (fixup_label != nullptr) {
6792        __ Bind(fixup_label);
6793      }
6794      static_assert(
6795          sizeof(mirror::CompressedReference<mirror::Object>) == sizeof(GcRoot<mirror::Object>),
6796          "art::mirror::CompressedReference<mirror::Object> and art::GcRoot<mirror::Object> "
6797          "have different sizes.");
6798      static_assert(sizeof(mirror::CompressedReference<mirror::Object>) == sizeof(int32_t),
6799                    "art::mirror::CompressedReference<mirror::Object> and int32_t "
6800                    "have different sizes.");
6801
6802      // Slow path used to mark the GC root `root`.
6803      SlowPathCode* slow_path =
6804          new (GetGraph()->GetArena()) ReadBarrierMarkSlowPathX86(instruction, root, root);
6805      codegen_->AddSlowPath(slow_path);
6806
6807      __ fs()->cmpl(Address::Absolute(Thread::IsGcMarkingOffset<kX86WordSize>().Int32Value()),
6808                    Immediate(0));
6809      __ j(kNotEqual, slow_path->GetEntryLabel());
6810      __ Bind(slow_path->GetExitLabel());
6811    } else {
6812      // GC root loaded through a slow path for read barriers other
6813      // than Baker's.
6814      // /* GcRoot<mirror::Object>* */ root = address
6815      __ leal(root_reg, address);
6816      if (fixup_label != nullptr) {
6817        __ Bind(fixup_label);
6818      }
6819      // /* mirror::Object* */ root = root->Read()
6820      codegen_->GenerateReadBarrierForRootSlow(instruction, root, root);
6821    }
6822  } else {
6823    // Plain GC root load with no read barrier.
6824    // /* GcRoot<mirror::Object> */ root = *address
6825    __ movl(root_reg, address);
6826    if (fixup_label != nullptr) {
6827      __ Bind(fixup_label);
6828    }
6829    // Note that GC roots are not affected by heap poisoning, thus we
6830    // do not have to unpoison `root_reg` here.
6831  }
6832}
6833
6834void CodeGeneratorX86::GenerateFieldLoadWithBakerReadBarrier(HInstruction* instruction,
6835                                                             Location ref,
6836                                                             Register obj,
6837                                                             uint32_t offset,
6838                                                             Location temp,
6839                                                             bool needs_null_check) {
6840  DCHECK(kEmitCompilerReadBarrier);
6841  DCHECK(kUseBakerReadBarrier);
6842
6843  // /* HeapReference<Object> */ ref = *(obj + offset)
6844  Address src(obj, offset);
6845  GenerateReferenceLoadWithBakerReadBarrier(instruction, ref, obj, src, temp, needs_null_check);
6846}
6847
6848void CodeGeneratorX86::GenerateArrayLoadWithBakerReadBarrier(HInstruction* instruction,
6849                                                             Location ref,
6850                                                             Register obj,
6851                                                             uint32_t data_offset,
6852                                                             Location index,
6853                                                             Location temp,
6854                                                             bool needs_null_check) {
6855  DCHECK(kEmitCompilerReadBarrier);
6856  DCHECK(kUseBakerReadBarrier);
6857
6858  // /* HeapReference<Object> */ ref =
6859  //     *(obj + data_offset + index * sizeof(HeapReference<Object>))
6860  Address src = index.IsConstant() ?
6861      Address(obj, (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_4) + data_offset) :
6862      Address(obj, index.AsRegister<Register>(), TIMES_4, data_offset);
6863  GenerateReferenceLoadWithBakerReadBarrier(instruction, ref, obj, src, temp, needs_null_check);
6864}
6865
6866void CodeGeneratorX86::GenerateReferenceLoadWithBakerReadBarrier(HInstruction* instruction,
6867                                                                 Location ref,
6868                                                                 Register obj,
6869                                                                 const Address& src,
6870                                                                 Location temp,
6871                                                                 bool needs_null_check) {
6872  DCHECK(kEmitCompilerReadBarrier);
6873  DCHECK(kUseBakerReadBarrier);
6874
6875  // In slow path based read barriers, the read barrier call is
6876  // inserted after the original load. However, in fast path based
6877  // Baker's read barriers, we need to perform the load of
6878  // mirror::Object::monitor_ *before* the original reference load.
6879  // This load-load ordering is required by the read barrier.
6880  // The fast path/slow path (for Baker's algorithm) should look like:
6881  //
6882  //   uint32_t rb_state = Lockword(obj->monitor_).ReadBarrierState();
6883  //   lfence;  // Load fence or artificial data dependency to prevent load-load reordering
6884  //   HeapReference<Object> ref = *src;  // Original reference load.
6885  //   bool is_gray = (rb_state == ReadBarrier::gray_ptr_);
6886  //   if (is_gray) {
6887  //     ref = ReadBarrier::Mark(ref);  // Performed by runtime entrypoint slow path.
6888  //   }
6889  //
6890  // Note: the original implementation in ReadBarrier::Barrier is
6891  // slightly more complex as:
6892  // - it implements the load-load fence using a data dependency on
6893  //   the high-bits of rb_state, which are expected to be all zeroes
6894  //   (we use CodeGeneratorX86::GenerateMemoryBarrier instead here,
6895  //   which is a no-op thanks to the x86 memory model);
6896  // - it performs additional checks that we do not do here for
6897  //   performance reasons.
6898
6899  Register ref_reg = ref.AsRegister<Register>();
6900  Register temp_reg = temp.AsRegister<Register>();
6901  uint32_t monitor_offset = mirror::Object::MonitorOffset().Int32Value();
6902
6903  // /* int32_t */ monitor = obj->monitor_
6904  __ movl(temp_reg, Address(obj, monitor_offset));
6905  if (needs_null_check) {
6906    MaybeRecordImplicitNullCheck(instruction);
6907  }
6908  // /* LockWord */ lock_word = LockWord(monitor)
6909  static_assert(sizeof(LockWord) == sizeof(int32_t),
6910                "art::LockWord and int32_t have different sizes.");
6911  // /* uint32_t */ rb_state = lock_word.ReadBarrierState()
6912  __ shrl(temp_reg, Immediate(LockWord::kReadBarrierStateShift));
6913  __ andl(temp_reg, Immediate(LockWord::kReadBarrierStateMask));
6914  static_assert(
6915      LockWord::kReadBarrierStateMask == ReadBarrier::rb_ptr_mask_,
6916      "art::LockWord::kReadBarrierStateMask is not equal to art::ReadBarrier::rb_ptr_mask_.");
6917
6918  // Load fence to prevent load-load reordering.
6919  // Note that this is a no-op, thanks to the x86 memory model.
6920  GenerateMemoryBarrier(MemBarrierKind::kLoadAny);
6921
6922  // The actual reference load.
6923  // /* HeapReference<Object> */ ref = *src
6924  __ movl(ref_reg, src);
6925
6926  // Object* ref = ref_addr->AsMirrorPtr()
6927  __ MaybeUnpoisonHeapReference(ref_reg);
6928
6929  // Slow path used to mark the object `ref` when it is gray.
6930  SlowPathCode* slow_path =
6931      new (GetGraph()->GetArena()) ReadBarrierMarkSlowPathX86(instruction, ref, ref);
6932  AddSlowPath(slow_path);
6933
6934  // if (rb_state == ReadBarrier::gray_ptr_)
6935  //   ref = ReadBarrier::Mark(ref);
6936  __ cmpl(temp_reg, Immediate(ReadBarrier::gray_ptr_));
6937  __ j(kEqual, slow_path->GetEntryLabel());
6938  __ Bind(slow_path->GetExitLabel());
6939}
6940
6941void CodeGeneratorX86::GenerateReadBarrierSlow(HInstruction* instruction,
6942                                               Location out,
6943                                               Location ref,
6944                                               Location obj,
6945                                               uint32_t offset,
6946                                               Location index) {
6947  DCHECK(kEmitCompilerReadBarrier);
6948
6949  // Insert a slow path based read barrier *after* the reference load.
6950  //
6951  // If heap poisoning is enabled, the unpoisoning of the loaded
6952  // reference will be carried out by the runtime within the slow
6953  // path.
6954  //
6955  // Note that `ref` currently does not get unpoisoned (when heap
6956  // poisoning is enabled), which is alright as the `ref` argument is
6957  // not used by the artReadBarrierSlow entry point.
6958  //
6959  // TODO: Unpoison `ref` when it is used by artReadBarrierSlow.
6960  SlowPathCode* slow_path = new (GetGraph()->GetArena())
6961      ReadBarrierForHeapReferenceSlowPathX86(instruction, out, ref, obj, offset, index);
6962  AddSlowPath(slow_path);
6963
6964  __ jmp(slow_path->GetEntryLabel());
6965  __ Bind(slow_path->GetExitLabel());
6966}
6967
6968void CodeGeneratorX86::MaybeGenerateReadBarrierSlow(HInstruction* instruction,
6969                                                    Location out,
6970                                                    Location ref,
6971                                                    Location obj,
6972                                                    uint32_t offset,
6973                                                    Location index) {
6974  if (kEmitCompilerReadBarrier) {
6975    // Baker's read barriers shall be handled by the fast path
6976    // (CodeGeneratorX86::GenerateReferenceLoadWithBakerReadBarrier).
6977    DCHECK(!kUseBakerReadBarrier);
6978    // If heap poisoning is enabled, unpoisoning will be taken care of
6979    // by the runtime within the slow path.
6980    GenerateReadBarrierSlow(instruction, out, ref, obj, offset, index);
6981  } else if (kPoisonHeapReferences) {
6982    __ UnpoisonHeapReference(out.AsRegister<Register>());
6983  }
6984}
6985
6986void CodeGeneratorX86::GenerateReadBarrierForRootSlow(HInstruction* instruction,
6987                                                      Location out,
6988                                                      Location root) {
6989  DCHECK(kEmitCompilerReadBarrier);
6990
6991  // Insert a slow path based read barrier *after* the GC root load.
6992  //
6993  // Note that GC roots are not affected by heap poisoning, so we do
6994  // not need to do anything special for this here.
6995  SlowPathCode* slow_path =
6996      new (GetGraph()->GetArena()) ReadBarrierForRootSlowPathX86(instruction, out, root);
6997  AddSlowPath(slow_path);
6998
6999  __ jmp(slow_path->GetEntryLabel());
7000  __ Bind(slow_path->GetExitLabel());
7001}
7002
7003void LocationsBuilderX86::VisitBoundType(HBoundType* instruction ATTRIBUTE_UNUSED) {
7004  // Nothing to do, this should be removed during prepare for register allocator.
7005  LOG(FATAL) << "Unreachable";
7006}
7007
7008void InstructionCodeGeneratorX86::VisitBoundType(HBoundType* instruction ATTRIBUTE_UNUSED) {
7009  // Nothing to do, this should be removed during prepare for register allocator.
7010  LOG(FATAL) << "Unreachable";
7011}
7012
7013// Simple implementation of packed switch - generate cascaded compare/jumps.
7014void LocationsBuilderX86::VisitPackedSwitch(HPackedSwitch* switch_instr) {
7015  LocationSummary* locations =
7016      new (GetGraph()->GetArena()) LocationSummary(switch_instr, LocationSummary::kNoCall);
7017  locations->SetInAt(0, Location::RequiresRegister());
7018}
7019
7020void InstructionCodeGeneratorX86::GenPackedSwitchWithCompares(Register value_reg,
7021                                                              int32_t lower_bound,
7022                                                              uint32_t num_entries,
7023                                                              HBasicBlock* switch_block,
7024                                                              HBasicBlock* default_block) {
7025  // Figure out the correct compare values and jump conditions.
7026  // Handle the first compare/branch as a special case because it might
7027  // jump to the default case.
7028  DCHECK_GT(num_entries, 2u);
7029  Condition first_condition;
7030  uint32_t index;
7031  const ArenaVector<HBasicBlock*>& successors = switch_block->GetSuccessors();
7032  if (lower_bound != 0) {
7033    first_condition = kLess;
7034    __ cmpl(value_reg, Immediate(lower_bound));
7035    __ j(first_condition, codegen_->GetLabelOf(default_block));
7036    __ j(kEqual, codegen_->GetLabelOf(successors[0]));
7037
7038    index = 1;
7039  } else {
7040    // Handle all the compare/jumps below.
7041    first_condition = kBelow;
7042    index = 0;
7043  }
7044
7045  // Handle the rest of the compare/jumps.
7046  for (; index + 1 < num_entries; index += 2) {
7047    int32_t compare_to_value = lower_bound + index + 1;
7048    __ cmpl(value_reg, Immediate(compare_to_value));
7049    // Jump to successors[index] if value < case_value[index].
7050    __ j(first_condition, codegen_->GetLabelOf(successors[index]));
7051    // Jump to successors[index + 1] if value == case_value[index + 1].
7052    __ j(kEqual, codegen_->GetLabelOf(successors[index + 1]));
7053  }
7054
7055  if (index != num_entries) {
7056    // There are an odd number of entries. Handle the last one.
7057    DCHECK_EQ(index + 1, num_entries);
7058    __ cmpl(value_reg, Immediate(lower_bound + index));
7059    __ j(kEqual, codegen_->GetLabelOf(successors[index]));
7060  }
7061
7062  // And the default for any other value.
7063  if (!codegen_->GoesToNextBlock(switch_block, default_block)) {
7064    __ jmp(codegen_->GetLabelOf(default_block));
7065  }
7066}
7067
7068void InstructionCodeGeneratorX86::VisitPackedSwitch(HPackedSwitch* switch_instr) {
7069  int32_t lower_bound = switch_instr->GetStartValue();
7070  uint32_t num_entries = switch_instr->GetNumEntries();
7071  LocationSummary* locations = switch_instr->GetLocations();
7072  Register value_reg = locations->InAt(0).AsRegister<Register>();
7073
7074  GenPackedSwitchWithCompares(value_reg,
7075                              lower_bound,
7076                              num_entries,
7077                              switch_instr->GetBlock(),
7078                              switch_instr->GetDefaultBlock());
7079}
7080
7081void LocationsBuilderX86::VisitX86PackedSwitch(HX86PackedSwitch* switch_instr) {
7082  LocationSummary* locations =
7083      new (GetGraph()->GetArena()) LocationSummary(switch_instr, LocationSummary::kNoCall);
7084  locations->SetInAt(0, Location::RequiresRegister());
7085
7086  // Constant area pointer.
7087  locations->SetInAt(1, Location::RequiresRegister());
7088
7089  // And the temporary we need.
7090  locations->AddTemp(Location::RequiresRegister());
7091}
7092
7093void InstructionCodeGeneratorX86::VisitX86PackedSwitch(HX86PackedSwitch* switch_instr) {
7094  int32_t lower_bound = switch_instr->GetStartValue();
7095  uint32_t num_entries = switch_instr->GetNumEntries();
7096  LocationSummary* locations = switch_instr->GetLocations();
7097  Register value_reg = locations->InAt(0).AsRegister<Register>();
7098  HBasicBlock* default_block = switch_instr->GetDefaultBlock();
7099
7100  if (num_entries <= kPackedSwitchJumpTableThreshold) {
7101    GenPackedSwitchWithCompares(value_reg,
7102                                lower_bound,
7103                                num_entries,
7104                                switch_instr->GetBlock(),
7105                                default_block);
7106    return;
7107  }
7108
7109  // Optimizing has a jump area.
7110  Register temp_reg = locations->GetTemp(0).AsRegister<Register>();
7111  Register constant_area = locations->InAt(1).AsRegister<Register>();
7112
7113  // Remove the bias, if needed.
7114  if (lower_bound != 0) {
7115    __ leal(temp_reg, Address(value_reg, -lower_bound));
7116    value_reg = temp_reg;
7117  }
7118
7119  // Is the value in range?
7120  DCHECK_GE(num_entries, 1u);
7121  __ cmpl(value_reg, Immediate(num_entries - 1));
7122  __ j(kAbove, codegen_->GetLabelOf(default_block));
7123
7124  // We are in the range of the table.
7125  // Load (target-constant_area) from the jump table, indexing by the value.
7126  __ movl(temp_reg, codegen_->LiteralCaseTable(switch_instr, constant_area, value_reg));
7127
7128  // Compute the actual target address by adding in constant_area.
7129  __ addl(temp_reg, constant_area);
7130
7131  // And jump.
7132  __ jmp(temp_reg);
7133}
7134
7135void LocationsBuilderX86::VisitX86ComputeBaseMethodAddress(
7136    HX86ComputeBaseMethodAddress* insn) {
7137  LocationSummary* locations =
7138      new (GetGraph()->GetArena()) LocationSummary(insn, LocationSummary::kNoCall);
7139  locations->SetOut(Location::RequiresRegister());
7140}
7141
7142void InstructionCodeGeneratorX86::VisitX86ComputeBaseMethodAddress(
7143    HX86ComputeBaseMethodAddress* insn) {
7144  LocationSummary* locations = insn->GetLocations();
7145  Register reg = locations->Out().AsRegister<Register>();
7146
7147  // Generate call to next instruction.
7148  Label next_instruction;
7149  __ call(&next_instruction);
7150  __ Bind(&next_instruction);
7151
7152  // Remember this offset for later use with constant area.
7153  codegen_->SetMethodAddressOffset(GetAssembler()->CodeSize());
7154
7155  // Grab the return address off the stack.
7156  __ popl(reg);
7157}
7158
7159void LocationsBuilderX86::VisitX86LoadFromConstantTable(
7160    HX86LoadFromConstantTable* insn) {
7161  LocationSummary* locations =
7162      new (GetGraph()->GetArena()) LocationSummary(insn, LocationSummary::kNoCall);
7163
7164  locations->SetInAt(0, Location::RequiresRegister());
7165  locations->SetInAt(1, Location::ConstantLocation(insn->GetConstant()));
7166
7167  // If we don't need to be materialized, we only need the inputs to be set.
7168  if (insn->IsEmittedAtUseSite()) {
7169    return;
7170  }
7171
7172  switch (insn->GetType()) {
7173    case Primitive::kPrimFloat:
7174    case Primitive::kPrimDouble:
7175      locations->SetOut(Location::RequiresFpuRegister());
7176      break;
7177
7178    case Primitive::kPrimInt:
7179      locations->SetOut(Location::RequiresRegister());
7180      break;
7181
7182    default:
7183      LOG(FATAL) << "Unsupported x86 constant area type " << insn->GetType();
7184  }
7185}
7186
7187void InstructionCodeGeneratorX86::VisitX86LoadFromConstantTable(HX86LoadFromConstantTable* insn) {
7188  if (insn->IsEmittedAtUseSite()) {
7189    return;
7190  }
7191
7192  LocationSummary* locations = insn->GetLocations();
7193  Location out = locations->Out();
7194  Register const_area = locations->InAt(0).AsRegister<Register>();
7195  HConstant *value = insn->GetConstant();
7196
7197  switch (insn->GetType()) {
7198    case Primitive::kPrimFloat:
7199      __ movss(out.AsFpuRegister<XmmRegister>(),
7200               codegen_->LiteralFloatAddress(value->AsFloatConstant()->GetValue(), const_area));
7201      break;
7202
7203    case Primitive::kPrimDouble:
7204      __ movsd(out.AsFpuRegister<XmmRegister>(),
7205               codegen_->LiteralDoubleAddress(value->AsDoubleConstant()->GetValue(), const_area));
7206      break;
7207
7208    case Primitive::kPrimInt:
7209      __ movl(out.AsRegister<Register>(),
7210              codegen_->LiteralInt32Address(value->AsIntConstant()->GetValue(), const_area));
7211      break;
7212
7213    default:
7214      LOG(FATAL) << "Unsupported x86 constant area type " << insn->GetType();
7215  }
7216}
7217
7218/**
7219 * Class to handle late fixup of offsets into constant area.
7220 */
7221class RIPFixup : public AssemblerFixup, public ArenaObject<kArenaAllocCodeGenerator> {
7222 public:
7223  RIPFixup(CodeGeneratorX86& codegen, size_t offset)
7224      : codegen_(&codegen), offset_into_constant_area_(offset) {}
7225
7226 protected:
7227  void SetOffset(size_t offset) { offset_into_constant_area_ = offset; }
7228
7229  CodeGeneratorX86* codegen_;
7230
7231 private:
7232  void Process(const MemoryRegion& region, int pos) OVERRIDE {
7233    // Patch the correct offset for the instruction.  The place to patch is the
7234    // last 4 bytes of the instruction.
7235    // The value to patch is the distance from the offset in the constant area
7236    // from the address computed by the HX86ComputeBaseMethodAddress instruction.
7237    int32_t constant_offset = codegen_->ConstantAreaStart() + offset_into_constant_area_;
7238    int32_t relative_position = constant_offset - codegen_->GetMethodAddressOffset();;
7239
7240    // Patch in the right value.
7241    region.StoreUnaligned<int32_t>(pos - 4, relative_position);
7242  }
7243
7244  // Location in constant area that the fixup refers to.
7245  int32_t offset_into_constant_area_;
7246};
7247
7248/**
7249 * Class to handle late fixup of offsets to a jump table that will be created in the
7250 * constant area.
7251 */
7252class JumpTableRIPFixup : public RIPFixup {
7253 public:
7254  JumpTableRIPFixup(CodeGeneratorX86& codegen, HX86PackedSwitch* switch_instr)
7255      : RIPFixup(codegen, static_cast<size_t>(-1)), switch_instr_(switch_instr) {}
7256
7257  void CreateJumpTable() {
7258    X86Assembler* assembler = codegen_->GetAssembler();
7259
7260    // Ensure that the reference to the jump table has the correct offset.
7261    const int32_t offset_in_constant_table = assembler->ConstantAreaSize();
7262    SetOffset(offset_in_constant_table);
7263
7264    // The label values in the jump table are computed relative to the
7265    // instruction addressing the constant area.
7266    const int32_t relative_offset = codegen_->GetMethodAddressOffset();
7267
7268    // Populate the jump table with the correct values for the jump table.
7269    int32_t num_entries = switch_instr_->GetNumEntries();
7270    HBasicBlock* block = switch_instr_->GetBlock();
7271    const ArenaVector<HBasicBlock*>& successors = block->GetSuccessors();
7272    // The value that we want is the target offset - the position of the table.
7273    for (int32_t i = 0; i < num_entries; i++) {
7274      HBasicBlock* b = successors[i];
7275      Label* l = codegen_->GetLabelOf(b);
7276      DCHECK(l->IsBound());
7277      int32_t offset_to_block = l->Position() - relative_offset;
7278      assembler->AppendInt32(offset_to_block);
7279    }
7280  }
7281
7282 private:
7283  const HX86PackedSwitch* switch_instr_;
7284};
7285
7286void CodeGeneratorX86::Finalize(CodeAllocator* allocator) {
7287  // Generate the constant area if needed.
7288  X86Assembler* assembler = GetAssembler();
7289  if (!assembler->IsConstantAreaEmpty() || !fixups_to_jump_tables_.empty()) {
7290    // Align to 4 byte boundary to reduce cache misses, as the data is 4 and 8
7291    // byte values.
7292    assembler->Align(4, 0);
7293    constant_area_start_ = assembler->CodeSize();
7294
7295    // Populate any jump tables.
7296    for (auto jump_table : fixups_to_jump_tables_) {
7297      jump_table->CreateJumpTable();
7298    }
7299
7300    // And now add the constant area to the generated code.
7301    assembler->AddConstantArea();
7302  }
7303
7304  // And finish up.
7305  CodeGenerator::Finalize(allocator);
7306}
7307
7308Address CodeGeneratorX86::LiteralDoubleAddress(double v, Register reg) {
7309  AssemblerFixup* fixup = new (GetGraph()->GetArena()) RIPFixup(*this, __ AddDouble(v));
7310  return Address(reg, kDummy32BitOffset, fixup);
7311}
7312
7313Address CodeGeneratorX86::LiteralFloatAddress(float v, Register reg) {
7314  AssemblerFixup* fixup = new (GetGraph()->GetArena()) RIPFixup(*this, __ AddFloat(v));
7315  return Address(reg, kDummy32BitOffset, fixup);
7316}
7317
7318Address CodeGeneratorX86::LiteralInt32Address(int32_t v, Register reg) {
7319  AssemblerFixup* fixup = new (GetGraph()->GetArena()) RIPFixup(*this, __ AddInt32(v));
7320  return Address(reg, kDummy32BitOffset, fixup);
7321}
7322
7323Address CodeGeneratorX86::LiteralInt64Address(int64_t v, Register reg) {
7324  AssemblerFixup* fixup = new (GetGraph()->GetArena()) RIPFixup(*this, __ AddInt64(v));
7325  return Address(reg, kDummy32BitOffset, fixup);
7326}
7327
7328void CodeGeneratorX86::Load32BitValue(Register dest, int32_t value) {
7329  if (value == 0) {
7330    __ xorl(dest, dest);
7331  } else {
7332    __ movl(dest, Immediate(value));
7333  }
7334}
7335
7336void CodeGeneratorX86::Compare32BitValue(Register dest, int32_t value) {
7337  if (value == 0) {
7338    __ testl(dest, dest);
7339  } else {
7340    __ cmpl(dest, Immediate(value));
7341  }
7342}
7343
7344Address CodeGeneratorX86::LiteralCaseTable(HX86PackedSwitch* switch_instr,
7345                                           Register reg,
7346                                           Register value) {
7347  // Create a fixup to be used to create and address the jump table.
7348  JumpTableRIPFixup* table_fixup =
7349      new (GetGraph()->GetArena()) JumpTableRIPFixup(*this, switch_instr);
7350
7351  // We have to populate the jump tables.
7352  fixups_to_jump_tables_.push_back(table_fixup);
7353
7354  // We want a scaled address, as we are extracting the correct offset from the table.
7355  return Address(reg, value, TIMES_4, kDummy32BitOffset, table_fixup);
7356}
7357
7358// TODO: target as memory.
7359void CodeGeneratorX86::MoveFromReturnRegister(Location target, Primitive::Type type) {
7360  if (!target.IsValid()) {
7361    DCHECK_EQ(type, Primitive::kPrimVoid);
7362    return;
7363  }
7364
7365  DCHECK_NE(type, Primitive::kPrimVoid);
7366
7367  Location return_loc = InvokeDexCallingConventionVisitorX86().GetReturnLocation(type);
7368  if (target.Equals(return_loc)) {
7369    return;
7370  }
7371
7372  // TODO: Consider pairs in the parallel move resolver, then this could be nicely merged
7373  //       with the else branch.
7374  if (type == Primitive::kPrimLong) {
7375    HParallelMove parallel_move(GetGraph()->GetArena());
7376    parallel_move.AddMove(return_loc.ToLow(), target.ToLow(), Primitive::kPrimInt, nullptr);
7377    parallel_move.AddMove(return_loc.ToHigh(), target.ToHigh(), Primitive::kPrimInt, nullptr);
7378    GetMoveResolver()->EmitNativeCode(&parallel_move);
7379  } else {
7380    // Let the parallel move resolver take care of all of this.
7381    HParallelMove parallel_move(GetGraph()->GetArena());
7382    parallel_move.AddMove(return_loc, target, type, nullptr);
7383    GetMoveResolver()->EmitNativeCode(&parallel_move);
7384  }
7385}
7386
7387#undef __
7388
7389}  // namespace x86
7390}  // namespace art
7391