blob: f1eb3726f0911051d8dbdaed8875369dd7bbf57b [file] [log] [blame]
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +00001/*
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"
Nicolas Geoffray1a43dd72014-07-17 15:15:34 +010018#include "gc/accounting/card_table.h"
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000019#include "utils/assembler.h"
Nicolas Geoffrayf12feb82014-07-17 18:32:41 +010020#include "utils/stack_checks.h"
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000021#include "utils/x86/assembler_x86.h"
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +010022#include "utils/x86/managed_register_x86.h"
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000023
Ian Rogersb0fa5dc2014-04-28 16:47:08 -070024#include "entrypoints/quick/quick_entrypoints.h"
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +000025#include "mirror/array.h"
26#include "mirror/art_method.h"
Ian Rogersb0fa5dc2014-04-28 16:47:08 -070027#include "thread.h"
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +000028
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000029namespace art {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +010030
31x86::X86ManagedRegister Location::AsX86() const {
32 return reg().AsX86();
33}
34
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000035namespace x86 {
36
Nicolas Geoffrayf12feb82014-07-17 18:32:41 +010037static constexpr bool kExplicitStackOverflowCheck = false;
38
39static constexpr int kNumberOfPushedRegistersAtEntry = 1;
40static constexpr int kCurrentMethodStackOffset = 0;
41
Nicolas Geoffraye5038322014-07-04 09:41:32 +010042#define __ reinterpret_cast<X86Assembler*>(codegen->GetAssembler())->
43
44class NullCheckSlowPathX86 : public SlowPathCode {
45 public:
46 explicit NullCheckSlowPathX86(uint32_t dex_pc) : dex_pc_(dex_pc) {}
47
48 virtual void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
49 __ Bind(GetEntryLabel());
50 __ fs()->call(Address::Absolute(QUICK_ENTRYPOINT_OFFSET(kX86WordSize, pThrowNullPointer)));
51 codegen->RecordPcInfo(dex_pc_);
52 }
53
54 private:
55 const uint32_t dex_pc_;
56 DISALLOW_COPY_AND_ASSIGN(NullCheckSlowPathX86);
57};
58
Nicolas Geoffrayf12feb82014-07-17 18:32:41 +010059class StackOverflowCheckSlowPathX86 : public SlowPathCode {
60 public:
61 StackOverflowCheckSlowPathX86() {}
62
63 virtual void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
64 __ Bind(GetEntryLabel());
65 __ addl(ESP,
66 Immediate(codegen->GetFrameSize() - kNumberOfPushedRegistersAtEntry * kX86WordSize));
67 __ fs()->jmp(Address::Absolute(QUICK_ENTRYPOINT_OFFSET(kX86WordSize, pThrowStackOverflow)));
68 }
69
70 private:
71 DISALLOW_COPY_AND_ASSIGN(StackOverflowCheckSlowPathX86);
72};
73
Nicolas Geoffraye5038322014-07-04 09:41:32 +010074#undef __
75#define __ reinterpret_cast<X86Assembler*>(GetAssembler())->
76
Dave Allison20dfc792014-06-16 20:44:29 -070077inline Condition X86Condition(IfCondition cond) {
78 switch (cond) {
79 case kCondEQ: return kEqual;
80 case kCondNE: return kNotEqual;
81 case kCondLT: return kLess;
82 case kCondLE: return kLessEqual;
83 case kCondGT: return kGreater;
84 case kCondGE: return kGreaterEqual;
85 default:
86 LOG(FATAL) << "Unknown if condition";
87 }
88 return kEqual;
89}
90
Nicolas Geoffraya7062e02014-05-22 12:50:17 +010091void CodeGeneratorX86::DumpCoreRegister(std::ostream& stream, int reg) const {
92 stream << X86ManagedRegister::FromCpuRegister(Register(reg));
93}
94
95void CodeGeneratorX86::DumpFloatingPointRegister(std::ostream& stream, int reg) const {
96 stream << X86ManagedRegister::FromXmmRegister(XmmRegister(reg));
97}
98
Nicolas Geoffraya7aca372014-04-28 17:47:12 +010099CodeGeneratorX86::CodeGeneratorX86(HGraph* graph)
100 : CodeGenerator(graph, kNumberOfRegIds),
101 location_builder_(graph, this),
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100102 instruction_visitor_(graph, this),
103 move_resolver_(graph->GetArena(), this) {}
104
Nicolas Geoffrayab032bc2014-07-15 12:55:21 +0100105size_t CodeGeneratorX86::FrameEntrySpillSize() const {
106 return kNumberOfPushedRegistersAtEntry * kX86WordSize;
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100107}
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100108
109static bool* GetBlockedRegisterPairs(bool* blocked_registers) {
110 return blocked_registers + kNumberOfAllocIds;
111}
112
113ManagedRegister CodeGeneratorX86::AllocateFreeRegister(Primitive::Type type,
114 bool* blocked_registers) const {
115 switch (type) {
116 case Primitive::kPrimLong: {
Nicolas Geoffray412f10c2014-06-19 10:00:34 +0100117 bool* blocked_register_pairs = GetBlockedRegisterPairs(blocked_registers);
118 size_t reg = AllocateFreeRegisterInternal(blocked_register_pairs, kNumberOfRegisterPairs);
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100119 X86ManagedRegister pair =
120 X86ManagedRegister::FromRegisterPair(static_cast<RegisterPair>(reg));
121 blocked_registers[pair.AsRegisterPairLow()] = true;
122 blocked_registers[pair.AsRegisterPairHigh()] = true;
Nicolas Geoffray412f10c2014-06-19 10:00:34 +0100123 // Block all other register pairs that share a register with `pair`.
124 for (int i = 0; i < kNumberOfRegisterPairs; i++) {
125 X86ManagedRegister current =
126 X86ManagedRegister::FromRegisterPair(static_cast<RegisterPair>(i));
127 if (current.AsRegisterPairLow() == pair.AsRegisterPairLow()
128 || current.AsRegisterPairLow() == pair.AsRegisterPairHigh()
129 || current.AsRegisterPairHigh() == pair.AsRegisterPairLow()
130 || current.AsRegisterPairHigh() == pair.AsRegisterPairHigh()) {
131 blocked_register_pairs[i] = true;
132 }
133 }
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100134 return pair;
135 }
136
137 case Primitive::kPrimByte:
138 case Primitive::kPrimBoolean:
139 case Primitive::kPrimChar:
140 case Primitive::kPrimShort:
141 case Primitive::kPrimInt:
142 case Primitive::kPrimNot: {
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100143 Register reg = static_cast<Register>(
144 AllocateFreeRegisterInternal(blocked_registers, kNumberOfCpuRegisters));
145 // Block all register pairs that contain `reg`.
146 bool* blocked_register_pairs = GetBlockedRegisterPairs(blocked_registers);
147 for (int i = 0; i < kNumberOfRegisterPairs; i++) {
148 X86ManagedRegister current =
149 X86ManagedRegister::FromRegisterPair(static_cast<RegisterPair>(i));
150 if (current.AsRegisterPairLow() == reg || current.AsRegisterPairHigh() == reg) {
151 blocked_register_pairs[i] = true;
152 }
153 }
154 return X86ManagedRegister::FromCpuRegister(reg);
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100155 }
156
157 case Primitive::kPrimFloat:
158 case Primitive::kPrimDouble:
159 LOG(FATAL) << "Unimplemented register type " << type;
160
161 case Primitive::kPrimVoid:
162 LOG(FATAL) << "Unreachable type " << type;
163 }
164
165 return ManagedRegister::NoRegister();
166}
167
168void CodeGeneratorX86::SetupBlockedRegisters(bool* blocked_registers) const {
169 bool* blocked_register_pairs = GetBlockedRegisterPairs(blocked_registers);
170
171 // Don't allocate the dalvik style register pair passing.
172 blocked_register_pairs[ECX_EDX] = true;
173
174 // Stack register is always reserved.
175 blocked_registers[ESP] = true;
176
177 // TODO: We currently don't use Quick's callee saved registers.
178 blocked_registers[EBP] = true;
179 blocked_registers[ESI] = true;
180 blocked_registers[EDI] = true;
181 blocked_register_pairs[EAX_EDI] = true;
182 blocked_register_pairs[EDX_EDI] = true;
183 blocked_register_pairs[ECX_EDI] = true;
184 blocked_register_pairs[EBX_EDI] = true;
185}
186
187size_t CodeGeneratorX86::GetNumberOfRegisters() const {
188 return kNumberOfRegIds;
189}
190
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100191static Location X86CpuLocation(Register reg) {
192 return Location::RegisterLocation(X86ManagedRegister::FromCpuRegister(reg));
193}
194
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100195InstructionCodeGeneratorX86::InstructionCodeGeneratorX86(HGraph* graph, CodeGeneratorX86* codegen)
196 : HGraphVisitor(graph),
197 assembler_(codegen->GetAssembler()),
198 codegen_(codegen) {}
199
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000200void CodeGeneratorX86::GenerateFrameEntry() {
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000201 // Create a fake register to mimic Quick.
202 static const int kFakeReturnRegister = 8;
203 core_spill_mask_ |= (1 << kFakeReturnRegister);
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000204
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100205 // The return PC has already been pushed on the stack.
Nicolas Geoffray707c8092014-04-04 10:50:14 +0100206 __ subl(ESP, Immediate(GetFrameSize() - kNumberOfPushedRegistersAtEntry * kX86WordSize));
Nicolas Geoffrayf12feb82014-07-17 18:32:41 +0100207
208 bool skip_overflow_check = IsLeafMethod() && !IsLargeFrame(GetFrameSize(), InstructionSet::kX86);
209 if (!skip_overflow_check) {
210 if (kExplicitStackOverflowCheck) {
211 SlowPathCode* slow_path = new (GetGraph()->GetArena()) StackOverflowCheckSlowPathX86();
212 AddSlowPath(slow_path);
213
214 __ fs()->cmpl(ESP, Address::Absolute(Thread::StackEndOffset<kX86WordSize>()));
215 __ j(kLess, slow_path->GetEntryLabel());
216 } else {
217 __ testl(EAX, Address(ESP, -static_cast<int32_t>(GetStackOverflowReservedBytes(kX86))));
218 }
219 }
220
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100221 __ movl(Address(ESP, kCurrentMethodStackOffset), EAX);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000222}
223
224void CodeGeneratorX86::GenerateFrameExit() {
Nicolas Geoffray707c8092014-04-04 10:50:14 +0100225 __ addl(ESP, Immediate(GetFrameSize() - kNumberOfPushedRegistersAtEntry * kX86WordSize));
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000226}
227
228void CodeGeneratorX86::Bind(Label* label) {
229 __ Bind(label);
230}
231
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000232void InstructionCodeGeneratorX86::LoadCurrentMethod(Register reg) {
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100233 __ movl(reg, Address(ESP, kCurrentMethodStackOffset));
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000234}
235
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100236Location CodeGeneratorX86::GetStackLocation(HLoadLocal* load) const {
237 switch (load->GetType()) {
238 case Primitive::kPrimLong:
239 return Location::DoubleStackSlot(GetStackSlot(load->GetLocal()));
240 break;
241
242 case Primitive::kPrimInt:
243 case Primitive::kPrimNot:
244 return Location::StackSlot(GetStackSlot(load->GetLocal()));
245
246 case Primitive::kPrimFloat:
247 case Primitive::kPrimDouble:
248 LOG(FATAL) << "Unimplemented type " << load->GetType();
249
250 case Primitive::kPrimBoolean:
251 case Primitive::kPrimByte:
252 case Primitive::kPrimChar:
253 case Primitive::kPrimShort:
254 case Primitive::kPrimVoid:
255 LOG(FATAL) << "Unexpected type " << load->GetType();
256 }
257
258 LOG(FATAL) << "Unreachable";
259 return Location();
260}
261
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100262static constexpr Register kRuntimeParameterCoreRegisters[] = { EAX, ECX, EDX };
263static constexpr size_t kRuntimeParameterCoreRegistersLength =
264 arraysize(kRuntimeParameterCoreRegisters);
265
266class InvokeRuntimeCallingConvention : public CallingConvention<Register> {
267 public:
268 InvokeRuntimeCallingConvention()
269 : CallingConvention(kRuntimeParameterCoreRegisters,
270 kRuntimeParameterCoreRegistersLength) {}
271
272 private:
273 DISALLOW_COPY_AND_ASSIGN(InvokeRuntimeCallingConvention);
274};
275
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100276Location InvokeDexCallingConventionVisitor::GetNextLocation(Primitive::Type type) {
277 switch (type) {
278 case Primitive::kPrimBoolean:
279 case Primitive::kPrimByte:
280 case Primitive::kPrimChar:
281 case Primitive::kPrimShort:
282 case Primitive::kPrimInt:
283 case Primitive::kPrimNot: {
284 uint32_t index = gp_index_++;
285 if (index < calling_convention.GetNumberOfRegisters()) {
286 return X86CpuLocation(calling_convention.GetRegisterAt(index));
287 } else {
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100288 return Location::StackSlot(calling_convention.GetStackOffsetOf(index));
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100289 }
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100290 }
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100291
292 case Primitive::kPrimLong: {
293 uint32_t index = gp_index_;
294 gp_index_ += 2;
295 if (index + 1 < calling_convention.GetNumberOfRegisters()) {
296 return Location::RegisterLocation(X86ManagedRegister::FromRegisterPair(
297 calling_convention.GetRegisterPairAt(index)));
298 } else if (index + 1 == calling_convention.GetNumberOfRegisters()) {
299 return Location::QuickParameter(index);
300 } else {
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100301 return Location::DoubleStackSlot(calling_convention.GetStackOffsetOf(index));
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100302 }
303 }
304
305 case Primitive::kPrimDouble:
306 case Primitive::kPrimFloat:
307 LOG(FATAL) << "Unimplemented parameter type " << type;
308 break;
309
310 case Primitive::kPrimVoid:
311 LOG(FATAL) << "Unexpected parameter type " << type;
312 break;
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100313 }
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100314 return Location();
315}
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100316
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100317void CodeGeneratorX86::Move32(Location destination, Location source) {
318 if (source.Equals(destination)) {
319 return;
320 }
321 if (destination.IsRegister()) {
322 if (source.IsRegister()) {
323 __ movl(destination.AsX86().AsCpuRegister(), source.AsX86().AsCpuRegister());
324 } else {
325 DCHECK(source.IsStackSlot());
326 __ movl(destination.AsX86().AsCpuRegister(), Address(ESP, source.GetStackIndex()));
327 }
328 } else {
329 if (source.IsRegister()) {
330 __ movl(Address(ESP, destination.GetStackIndex()), source.AsX86().AsCpuRegister());
331 } else {
332 DCHECK(source.IsStackSlot());
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100333 __ pushl(Address(ESP, source.GetStackIndex()));
334 __ popl(Address(ESP, destination.GetStackIndex()));
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100335 }
336 }
337}
338
339void CodeGeneratorX86::Move64(Location destination, Location source) {
340 if (source.Equals(destination)) {
341 return;
342 }
343 if (destination.IsRegister()) {
344 if (source.IsRegister()) {
345 __ movl(destination.AsX86().AsRegisterPairLow(), source.AsX86().AsRegisterPairLow());
346 __ movl(destination.AsX86().AsRegisterPairHigh(), source.AsX86().AsRegisterPairHigh());
347 } else if (source.IsQuickParameter()) {
348 uint32_t argument_index = source.GetQuickParameterIndex();
349 InvokeDexCallingConvention calling_convention;
350 __ movl(destination.AsX86().AsRegisterPairLow(),
351 calling_convention.GetRegisterAt(argument_index));
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100352 __ movl(destination.AsX86().AsRegisterPairHigh(), Address(ESP,
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100353 calling_convention.GetStackOffsetOf(argument_index + 1) + GetFrameSize()));
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100354 } else {
355 DCHECK(source.IsDoubleStackSlot());
356 __ movl(destination.AsX86().AsRegisterPairLow(), Address(ESP, source.GetStackIndex()));
357 __ movl(destination.AsX86().AsRegisterPairHigh(),
358 Address(ESP, source.GetHighStackIndex(kX86WordSize)));
359 }
360 } else if (destination.IsQuickParameter()) {
361 InvokeDexCallingConvention calling_convention;
362 uint32_t argument_index = destination.GetQuickParameterIndex();
363 if (source.IsRegister()) {
364 __ movl(calling_convention.GetRegisterAt(argument_index), source.AsX86().AsRegisterPairLow());
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100365 __ movl(Address(ESP, calling_convention.GetStackOffsetOf(argument_index + 1)),
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100366 source.AsX86().AsRegisterPairHigh());
367 } else {
368 DCHECK(source.IsDoubleStackSlot());
369 __ movl(calling_convention.GetRegisterAt(argument_index),
370 Address(ESP, source.GetStackIndex()));
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100371 __ pushl(Address(ESP, source.GetHighStackIndex(kX86WordSize)));
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100372 __ popl(Address(ESP, calling_convention.GetStackOffsetOf(argument_index + 1)));
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100373 }
374 } else {
375 if (source.IsRegister()) {
376 __ movl(Address(ESP, destination.GetStackIndex()), source.AsX86().AsRegisterPairLow());
377 __ movl(Address(ESP, destination.GetHighStackIndex(kX86WordSize)),
378 source.AsX86().AsRegisterPairHigh());
379 } else if (source.IsQuickParameter()) {
380 InvokeDexCallingConvention calling_convention;
381 uint32_t argument_index = source.GetQuickParameterIndex();
382 __ movl(Address(ESP, destination.GetStackIndex()),
383 calling_convention.GetRegisterAt(argument_index));
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100384 __ pushl(Address(ESP,
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100385 calling_convention.GetStackOffsetOf(argument_index + 1) + GetFrameSize()));
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100386 __ popl(Address(ESP, destination.GetHighStackIndex(kX86WordSize)));
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100387 } else {
388 DCHECK(source.IsDoubleStackSlot());
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100389 __ pushl(Address(ESP, source.GetStackIndex()));
390 __ popl(Address(ESP, destination.GetStackIndex()));
391 __ pushl(Address(ESP, source.GetHighStackIndex(kX86WordSize)));
392 __ popl(Address(ESP, destination.GetHighStackIndex(kX86WordSize)));
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100393 }
394 }
395}
396
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100397void CodeGeneratorX86::Move(HInstruction* instruction, Location location, HInstruction* move_for) {
398 if (instruction->AsIntConstant() != nullptr) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100399 Immediate imm(instruction->AsIntConstant()->GetValue());
400 if (location.IsRegister()) {
401 __ movl(location.AsX86().AsCpuRegister(), imm);
402 } else {
403 __ movl(Address(ESP, location.GetStackIndex()), imm);
404 }
405 } else if (instruction->AsLongConstant() != nullptr) {
406 int64_t value = instruction->AsLongConstant()->GetValue();
407 if (location.IsRegister()) {
408 __ movl(location.AsX86().AsRegisterPairLow(), Immediate(Low32Bits(value)));
409 __ movl(location.AsX86().AsRegisterPairHigh(), Immediate(High32Bits(value)));
410 } else {
411 __ movl(Address(ESP, location.GetStackIndex()), Immediate(Low32Bits(value)));
412 __ movl(Address(ESP, location.GetHighStackIndex(kX86WordSize)), Immediate(High32Bits(value)));
413 }
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100414 } else if (instruction->AsLoadLocal() != nullptr) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100415 switch (instruction->GetType()) {
416 case Primitive::kPrimBoolean:
417 case Primitive::kPrimByte:
418 case Primitive::kPrimChar:
419 case Primitive::kPrimShort:
420 case Primitive::kPrimInt:
421 case Primitive::kPrimNot:
422 Move32(location, Location::StackSlot(GetStackSlot(instruction->AsLoadLocal()->GetLocal())));
423 break;
424
425 case Primitive::kPrimLong:
426 Move64(location, Location::DoubleStackSlot(
427 GetStackSlot(instruction->AsLoadLocal()->GetLocal())));
428 break;
429
430 default:
431 LOG(FATAL) << "Unimplemented local type " << instruction->GetType();
432 }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000433 } else {
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100434 DCHECK((instruction->GetNext() == move_for) || instruction->GetNext()->IsTemporary());
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100435 switch (instruction->GetType()) {
436 case Primitive::kPrimBoolean:
437 case Primitive::kPrimByte:
438 case Primitive::kPrimChar:
439 case Primitive::kPrimShort:
440 case Primitive::kPrimInt:
441 case Primitive::kPrimNot:
442 Move32(location, instruction->GetLocations()->Out());
443 break;
444
445 case Primitive::kPrimLong:
446 Move64(location, instruction->GetLocations()->Out());
447 break;
448
449 default:
450 LOG(FATAL) << "Unimplemented type " << instruction->GetType();
451 }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000452 }
453}
454
455void LocationsBuilderX86::VisitGoto(HGoto* got) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000456 got->SetLocations(nullptr);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000457}
458
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000459void InstructionCodeGeneratorX86::VisitGoto(HGoto* got) {
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000460 HBasicBlock* successor = got->GetSuccessor();
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000461 if (GetGraph()->GetExitBlock() == successor) {
462 codegen_->GenerateFrameExit();
463 } else if (!codegen_->GoesToNextBlock(got->GetBlock(), successor)) {
464 __ jmp(codegen_->GetLabelOf(successor));
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000465 }
466}
467
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000468void LocationsBuilderX86::VisitExit(HExit* exit) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000469 exit->SetLocations(nullptr);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000470}
471
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000472void InstructionCodeGeneratorX86::VisitExit(HExit* exit) {
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000473 if (kIsDebugBuild) {
474 __ Comment("Unreachable");
475 __ int3();
476 }
477}
478
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000479void LocationsBuilderX86::VisitIf(HIf* if_instr) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000480 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(if_instr);
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100481 HInstruction* cond = if_instr->InputAt(0);
482 DCHECK(cond->IsCondition());
483 HCondition* condition = cond->AsCondition();
484 if (condition->NeedsMaterialization()) {
485 locations->SetInAt(0, Location::Any());
486 }
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000487 if_instr->SetLocations(locations);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000488}
489
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000490void InstructionCodeGeneratorX86::VisitIf(HIf* if_instr) {
Dave Allison20dfc792014-06-16 20:44:29 -0700491 HInstruction* cond = if_instr->InputAt(0);
492 DCHECK(cond->IsCondition());
493 HCondition* condition = cond->AsCondition();
494 if (condition->NeedsMaterialization()) {
495 // Materialized condition, compare against 0
496 Location lhs = if_instr->GetLocations()->InAt(0);
497 if (lhs.IsRegister()) {
498 __ cmpl(lhs.AsX86().AsCpuRegister(), Immediate(0));
499 } else {
500 __ cmpl(Address(ESP, lhs.GetStackIndex()), Immediate(0));
501 }
502 __ j(kEqual, codegen_->GetLabelOf(if_instr->IfTrueSuccessor()));
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100503 } else {
Dave Allison20dfc792014-06-16 20:44:29 -0700504 Location lhs = condition->GetLocations()->InAt(0);
505 Location rhs = condition->GetLocations()->InAt(1);
506 // LHS is guaranteed to be in a register (see LocationsBuilderX86::VisitCondition).
507 if (rhs.IsRegister()) {
508 __ cmpl(lhs.AsX86().AsCpuRegister(), rhs.AsX86().AsCpuRegister());
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100509 } else if (rhs.IsConstant()) {
510 HIntConstant* instruction = rhs.GetConstant()->AsIntConstant();
511 Immediate imm(instruction->AsIntConstant()->GetValue());
512 __ cmpl(lhs.AsX86().AsCpuRegister(), imm);
Dave Allison20dfc792014-06-16 20:44:29 -0700513 } else {
514 __ cmpl(lhs.AsX86().AsCpuRegister(), Address(ESP, rhs.GetStackIndex()));
515 }
516 __ j(X86Condition(condition->GetCondition()),
517 codegen_->GetLabelOf(if_instr->IfTrueSuccessor()));
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100518 }
Dave Allison20dfc792014-06-16 20:44:29 -0700519 if (!codegen_->GoesToNextBlock(if_instr->GetBlock(), if_instr->IfFalseSuccessor())) {
520 __ jmp(codegen_->GetLabelOf(if_instr->IfFalseSuccessor()));
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000521 }
522}
523
524void LocationsBuilderX86::VisitLocal(HLocal* local) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000525 local->SetLocations(nullptr);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000526}
527
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000528void InstructionCodeGeneratorX86::VisitLocal(HLocal* local) {
529 DCHECK_EQ(local->GetBlock(), GetGraph()->GetEntryBlock());
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000530}
531
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000532void LocationsBuilderX86::VisitLoadLocal(HLoadLocal* local) {
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100533 local->SetLocations(nullptr);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000534}
535
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000536void InstructionCodeGeneratorX86::VisitLoadLocal(HLoadLocal* load) {
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100537 // Nothing to do, this is driven by the code generator.
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000538}
539
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100540void LocationsBuilderX86::VisitStoreLocal(HStoreLocal* store) {
541 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(store);
542 switch (store->InputAt(1)->GetType()) {
543 case Primitive::kPrimBoolean:
544 case Primitive::kPrimByte:
545 case Primitive::kPrimChar:
546 case Primitive::kPrimShort:
547 case Primitive::kPrimInt:
548 case Primitive::kPrimNot:
549 locations->SetInAt(1, Location::StackSlot(codegen_->GetStackSlot(store->GetLocal())));
550 break;
551
552 case Primitive::kPrimLong:
553 locations->SetInAt(1, Location::DoubleStackSlot(codegen_->GetStackSlot(store->GetLocal())));
554 break;
555
556 default:
557 LOG(FATAL) << "Unimplemented local type " << store->InputAt(1)->GetType();
558 }
559 store->SetLocations(locations);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000560}
561
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000562void InstructionCodeGeneratorX86::VisitStoreLocal(HStoreLocal* store) {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000563}
564
Dave Allison20dfc792014-06-16 20:44:29 -0700565void LocationsBuilderX86::VisitCondition(HCondition* comp) {
566 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(comp);
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100567 locations->SetInAt(0, Location::RequiresRegister());
568 locations->SetInAt(1, Location::Any());
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100569 if (comp->NeedsMaterialization()) {
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100570 locations->SetOut(Location::RequiresRegister());
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100571 }
Dave Allison20dfc792014-06-16 20:44:29 -0700572 comp->SetLocations(locations);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000573}
574
Dave Allison20dfc792014-06-16 20:44:29 -0700575void InstructionCodeGeneratorX86::VisitCondition(HCondition* comp) {
576 if (comp->NeedsMaterialization()) {
577 LocationSummary* locations = comp->GetLocations();
578 if (locations->InAt(1).IsRegister()) {
579 __ cmpl(locations->InAt(0).AsX86().AsCpuRegister(),
580 locations->InAt(1).AsX86().AsCpuRegister());
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100581 } else if (locations->InAt(1).IsConstant()) {
582 HConstant* instruction = locations->InAt(1).GetConstant();
583 Immediate imm(instruction->AsIntConstant()->GetValue());
584 __ cmpl(locations->InAt(0).AsX86().AsCpuRegister(), imm);
Dave Allison20dfc792014-06-16 20:44:29 -0700585 } else {
586 __ cmpl(locations->InAt(0).AsX86().AsCpuRegister(),
587 Address(ESP, locations->InAt(1).GetStackIndex()));
588 }
589 __ setb(X86Condition(comp->GetCondition()), locations->Out().AsX86().AsCpuRegister());
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100590 }
Dave Allison20dfc792014-06-16 20:44:29 -0700591}
592
593void LocationsBuilderX86::VisitEqual(HEqual* comp) {
594 VisitCondition(comp);
595}
596
597void InstructionCodeGeneratorX86::VisitEqual(HEqual* comp) {
598 VisitCondition(comp);
599}
600
601void LocationsBuilderX86::VisitNotEqual(HNotEqual* comp) {
602 VisitCondition(comp);
603}
604
605void InstructionCodeGeneratorX86::VisitNotEqual(HNotEqual* comp) {
606 VisitCondition(comp);
607}
608
609void LocationsBuilderX86::VisitLessThan(HLessThan* comp) {
610 VisitCondition(comp);
611}
612
613void InstructionCodeGeneratorX86::VisitLessThan(HLessThan* comp) {
614 VisitCondition(comp);
615}
616
617void LocationsBuilderX86::VisitLessThanOrEqual(HLessThanOrEqual* comp) {
618 VisitCondition(comp);
619}
620
621void InstructionCodeGeneratorX86::VisitLessThanOrEqual(HLessThanOrEqual* comp) {
622 VisitCondition(comp);
623}
624
625void LocationsBuilderX86::VisitGreaterThan(HGreaterThan* comp) {
626 VisitCondition(comp);
627}
628
629void InstructionCodeGeneratorX86::VisitGreaterThan(HGreaterThan* comp) {
630 VisitCondition(comp);
631}
632
633void LocationsBuilderX86::VisitGreaterThanOrEqual(HGreaterThanOrEqual* comp) {
634 VisitCondition(comp);
635}
636
637void InstructionCodeGeneratorX86::VisitGreaterThanOrEqual(HGreaterThanOrEqual* comp) {
638 VisitCondition(comp);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000639}
640
641void LocationsBuilderX86::VisitIntConstant(HIntConstant* constant) {
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100642 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(constant);
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100643 locations->SetOut(Location::ConstantLocation(constant));
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100644 constant->SetLocations(locations);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000645}
646
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000647void InstructionCodeGeneratorX86::VisitIntConstant(HIntConstant* constant) {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000648}
649
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100650void LocationsBuilderX86::VisitLongConstant(HLongConstant* constant) {
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100651 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(constant);
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100652 locations->SetOut(Location::ConstantLocation(constant));
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100653 constant->SetLocations(locations);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100654}
655
656void InstructionCodeGeneratorX86::VisitLongConstant(HLongConstant* constant) {
657 // Will be generated at use site.
658}
659
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000660void LocationsBuilderX86::VisitReturnVoid(HReturnVoid* ret) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000661 ret->SetLocations(nullptr);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000662}
663
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000664void InstructionCodeGeneratorX86::VisitReturnVoid(HReturnVoid* ret) {
665 codegen_->GenerateFrameExit();
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000666 __ ret();
667}
668
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000669void LocationsBuilderX86::VisitReturn(HReturn* ret) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000670 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(ret);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100671 switch (ret->InputAt(0)->GetType()) {
672 case Primitive::kPrimBoolean:
673 case Primitive::kPrimByte:
674 case Primitive::kPrimChar:
675 case Primitive::kPrimShort:
676 case Primitive::kPrimInt:
677 case Primitive::kPrimNot:
678 locations->SetInAt(0, X86CpuLocation(EAX));
679 break;
680
681 case Primitive::kPrimLong:
682 locations->SetInAt(
683 0, Location::RegisterLocation(X86ManagedRegister::FromRegisterPair(EAX_EDX)));
684 break;
685
686 default:
687 LOG(FATAL) << "Unimplemented return type " << ret->InputAt(0)->GetType();
688 }
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000689 ret->SetLocations(locations);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000690}
691
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000692void InstructionCodeGeneratorX86::VisitReturn(HReturn* ret) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100693 if (kIsDebugBuild) {
694 switch (ret->InputAt(0)->GetType()) {
695 case Primitive::kPrimBoolean:
696 case Primitive::kPrimByte:
697 case Primitive::kPrimChar:
698 case Primitive::kPrimShort:
699 case Primitive::kPrimInt:
700 case Primitive::kPrimNot:
701 DCHECK_EQ(ret->GetLocations()->InAt(0).AsX86().AsCpuRegister(), EAX);
702 break;
703
704 case Primitive::kPrimLong:
705 DCHECK_EQ(ret->GetLocations()->InAt(0).AsX86().AsRegisterPair(), EAX_EDX);
706 break;
707
708 default:
709 LOG(FATAL) << "Unimplemented return type " << ret->InputAt(0)->GetType();
710 }
711 }
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000712 codegen_->GenerateFrameExit();
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000713 __ ret();
714}
715
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000716void LocationsBuilderX86::VisitInvokeStatic(HInvokeStatic* invoke) {
Nicolas Geoffrayf12feb82014-07-17 18:32:41 +0100717 codegen_->MarkNotLeaf();
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000718 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(invoke);
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100719 locations->AddTemp(X86CpuLocation(EAX));
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100720
721 InvokeDexCallingConventionVisitor calling_convention_visitor;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100722 for (size_t i = 0; i < invoke->InputCount(); i++) {
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100723 HInstruction* input = invoke->InputAt(i);
724 locations->SetInAt(i, calling_convention_visitor.GetNextLocation(input->GetType()));
725 }
726
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100727 switch (invoke->GetType()) {
728 case Primitive::kPrimBoolean:
729 case Primitive::kPrimByte:
730 case Primitive::kPrimChar:
731 case Primitive::kPrimShort:
732 case Primitive::kPrimInt:
733 case Primitive::kPrimNot:
734 locations->SetOut(X86CpuLocation(EAX));
735 break;
736
737 case Primitive::kPrimLong:
738 locations->SetOut(Location::RegisterLocation(X86ManagedRegister::FromRegisterPair(EAX_EDX)));
739 break;
740
741 case Primitive::kPrimVoid:
742 break;
743
744 case Primitive::kPrimDouble:
745 case Primitive::kPrimFloat:
746 LOG(FATAL) << "Unimplemented return type " << invoke->GetType();
747 break;
748 }
749
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000750 invoke->SetLocations(locations);
751}
752
753void InstructionCodeGeneratorX86::VisitInvokeStatic(HInvokeStatic* invoke) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100754 Register temp = invoke->GetLocations()->GetTemp(0).AsX86().AsCpuRegister();
Nicolas Geoffrayf61b5372014-06-25 14:35:34 +0100755 uint32_t heap_reference_size = sizeof(mirror::HeapReference<mirror::Object>);
756 size_t index_in_cache = mirror::Array::DataOffset(heap_reference_size).Int32Value() +
Nicolas Geoffray707c8092014-04-04 10:50:14 +0100757 invoke->GetIndexInDexCache() * kX86WordSize;
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000758
759 // TODO: Implement all kinds of calls:
760 // 1) boot -> boot
761 // 2) app -> boot
762 // 3) app -> app
763 //
764 // Currently we implement the app -> app logic, which looks up in the resolve cache.
765
766 // temp = method;
767 LoadCurrentMethod(temp);
768 // temp = temp->dex_cache_resolved_methods_;
769 __ movl(temp, Address(temp, mirror::ArtMethod::DexCacheResolvedMethodsOffset().Int32Value()));
770 // temp = temp[index_in_cache]
771 __ movl(temp, Address(temp, index_in_cache));
772 // (temp + offset_of_quick_compiled_code)()
773 __ call(Address(temp, mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset().Int32Value()));
774
Nicolas Geoffrayf12feb82014-07-17 18:32:41 +0100775 DCHECK(!codegen_->IsLeafMethod());
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000776 codegen_->RecordPcInfo(invoke->GetDexPc());
777}
778
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000779void LocationsBuilderX86::VisitAdd(HAdd* add) {
780 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(add);
781 switch (add->GetResultType()) {
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100782 case Primitive::kPrimInt:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100783 case Primitive::kPrimLong: {
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100784 locations->SetInAt(0, Location::RequiresRegister());
785 locations->SetInAt(1, Location::Any());
786 locations->SetOut(Location::SameAsFirstInput());
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100787 break;
788 }
789
790 case Primitive::kPrimBoolean:
791 case Primitive::kPrimByte:
792 case Primitive::kPrimChar:
793 case Primitive::kPrimShort:
794 LOG(FATAL) << "Unexpected add type " << add->GetResultType();
795 break;
796
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000797 default:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100798 LOG(FATAL) << "Unimplemented add type " << add->GetResultType();
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000799 }
800 add->SetLocations(locations);
801}
802
803void InstructionCodeGeneratorX86::VisitAdd(HAdd* add) {
804 LocationSummary* locations = add->GetLocations();
805 switch (add->GetResultType()) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100806 case Primitive::kPrimInt: {
807 DCHECK_EQ(locations->InAt(0).AsX86().AsCpuRegister(),
808 locations->Out().AsX86().AsCpuRegister());
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100809 if (locations->InAt(1).IsRegister()) {
810 __ addl(locations->InAt(0).AsX86().AsCpuRegister(),
811 locations->InAt(1).AsX86().AsCpuRegister());
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100812 } else if (locations->InAt(1).IsConstant()) {
813 HConstant* instruction = locations->InAt(1).GetConstant();
814 Immediate imm(instruction->AsIntConstant()->GetValue());
815 __ addl(locations->InAt(0).AsX86().AsCpuRegister(), imm);
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100816 } else {
817 __ addl(locations->InAt(0).AsX86().AsCpuRegister(),
818 Address(ESP, locations->InAt(1).GetStackIndex()));
819 }
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000820 break;
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100821 }
822
823 case Primitive::kPrimLong: {
824 DCHECK_EQ(locations->InAt(0).AsX86().AsRegisterPair(),
825 locations->Out().AsX86().AsRegisterPair());
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100826 if (locations->InAt(1).IsRegister()) {
827 __ addl(locations->InAt(0).AsX86().AsRegisterPairLow(),
828 locations->InAt(1).AsX86().AsRegisterPairLow());
829 __ adcl(locations->InAt(0).AsX86().AsRegisterPairHigh(),
830 locations->InAt(1).AsX86().AsRegisterPairHigh());
831 } else {
832 __ addl(locations->InAt(0).AsX86().AsRegisterPairLow(),
833 Address(ESP, locations->InAt(1).GetStackIndex()));
834 __ adcl(locations->InAt(0).AsX86().AsRegisterPairHigh(),
835 Address(ESP, locations->InAt(1).GetHighStackIndex(kX86WordSize)));
836 }
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100837 break;
838 }
839
840 case Primitive::kPrimBoolean:
841 case Primitive::kPrimByte:
842 case Primitive::kPrimChar:
843 case Primitive::kPrimShort:
844 LOG(FATAL) << "Unexpected add type " << add->GetResultType();
845 break;
846
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000847 default:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100848 LOG(FATAL) << "Unimplemented add type " << add->GetResultType();
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000849 }
850}
851
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100852void LocationsBuilderX86::VisitSub(HSub* sub) {
853 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(sub);
854 switch (sub->GetResultType()) {
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100855 case Primitive::kPrimInt:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100856 case Primitive::kPrimLong: {
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100857 locations->SetInAt(0, Location::RequiresRegister());
858 locations->SetInAt(1, Location::Any());
859 locations->SetOut(Location::SameAsFirstInput());
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100860 break;
861 }
862
863 case Primitive::kPrimBoolean:
864 case Primitive::kPrimByte:
865 case Primitive::kPrimChar:
866 case Primitive::kPrimShort:
867 LOG(FATAL) << "Unexpected sub type " << sub->GetResultType();
868 break;
869
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100870 default:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100871 LOG(FATAL) << "Unimplemented sub type " << sub->GetResultType();
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100872 }
873 sub->SetLocations(locations);
874}
875
876void InstructionCodeGeneratorX86::VisitSub(HSub* sub) {
877 LocationSummary* locations = sub->GetLocations();
878 switch (sub->GetResultType()) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100879 case Primitive::kPrimInt: {
880 DCHECK_EQ(locations->InAt(0).AsX86().AsCpuRegister(),
881 locations->Out().AsX86().AsCpuRegister());
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100882 if (locations->InAt(1).IsRegister()) {
883 __ subl(locations->InAt(0).AsX86().AsCpuRegister(),
884 locations->InAt(1).AsX86().AsCpuRegister());
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100885 } else if (locations->InAt(1).IsConstant()) {
886 HConstant* instruction = locations->InAt(1).GetConstant();
887 Immediate imm(instruction->AsIntConstant()->GetValue());
888 __ subl(locations->InAt(0).AsX86().AsCpuRegister(), imm);
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100889 } else {
890 __ subl(locations->InAt(0).AsX86().AsCpuRegister(),
891 Address(ESP, locations->InAt(1).GetStackIndex()));
892 }
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100893 break;
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100894 }
895
896 case Primitive::kPrimLong: {
897 DCHECK_EQ(locations->InAt(0).AsX86().AsRegisterPair(),
898 locations->Out().AsX86().AsRegisterPair());
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100899 if (locations->InAt(1).IsRegister()) {
900 __ subl(locations->InAt(0).AsX86().AsRegisterPairLow(),
901 locations->InAt(1).AsX86().AsRegisterPairLow());
902 __ sbbl(locations->InAt(0).AsX86().AsRegisterPairHigh(),
903 locations->InAt(1).AsX86().AsRegisterPairHigh());
904 } else {
905 __ subl(locations->InAt(0).AsX86().AsRegisterPairLow(),
906 Address(ESP, locations->InAt(1).GetStackIndex()));
907 __ sbbl(locations->InAt(0).AsX86().AsRegisterPairHigh(),
908 Address(ESP, locations->InAt(1).GetHighStackIndex(kX86WordSize)));
909 }
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100910 break;
911 }
912
913 case Primitive::kPrimBoolean:
914 case Primitive::kPrimByte:
915 case Primitive::kPrimChar:
916 case Primitive::kPrimShort:
917 LOG(FATAL) << "Unexpected sub type " << sub->GetResultType();
918 break;
919
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100920 default:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100921 LOG(FATAL) << "Unimplemented sub type " << sub->GetResultType();
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100922 }
923}
924
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100925void LocationsBuilderX86::VisitNewInstance(HNewInstance* instruction) {
Nicolas Geoffrayf12feb82014-07-17 18:32:41 +0100926 codegen_->MarkNotLeaf();
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100927 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100928 locations->SetOut(X86CpuLocation(EAX));
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100929 InvokeRuntimeCallingConvention calling_convention;
930 locations->AddTemp(X86CpuLocation(calling_convention.GetRegisterAt(0)));
931 locations->AddTemp(X86CpuLocation(calling_convention.GetRegisterAt(1)));
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100932 instruction->SetLocations(locations);
933}
934
935void InstructionCodeGeneratorX86::VisitNewInstance(HNewInstance* instruction) {
936 InvokeRuntimeCallingConvention calling_convention;
937 LoadCurrentMethod(calling_convention.GetRegisterAt(1));
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100938 __ movl(calling_convention.GetRegisterAt(0), Immediate(instruction->GetTypeIndex()));
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100939
Nicolas Geoffray707c8092014-04-04 10:50:14 +0100940 __ fs()->call(
941 Address::Absolute(QUICK_ENTRYPOINT_OFFSET(kX86WordSize, pAllocObjectWithAccessCheck)));
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100942
943 codegen_->RecordPcInfo(instruction->GetDexPc());
Nicolas Geoffrayf12feb82014-07-17 18:32:41 +0100944 DCHECK(!codegen_->IsLeafMethod());
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100945}
946
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100947void LocationsBuilderX86::VisitParameterValue(HParameterValue* instruction) {
948 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100949 Location location = parameter_visitor_.GetNextLocation(instruction->GetType());
950 if (location.IsStackSlot()) {
951 location = Location::StackSlot(location.GetStackIndex() + codegen_->GetFrameSize());
952 } else if (location.IsDoubleStackSlot()) {
953 location = Location::DoubleStackSlot(location.GetStackIndex() + codegen_->GetFrameSize());
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100954 }
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100955 locations->SetOut(location);
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100956 instruction->SetLocations(locations);
957}
958
959void InstructionCodeGeneratorX86::VisitParameterValue(HParameterValue* instruction) {
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100960}
961
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100962void LocationsBuilderX86::VisitNot(HNot* instruction) {
963 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100964 locations->SetInAt(0, Location::RequiresRegister());
965 locations->SetOut(Location::SameAsFirstInput());
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100966 instruction->SetLocations(locations);
967}
968
969void InstructionCodeGeneratorX86::VisitNot(HNot* instruction) {
970 LocationSummary* locations = instruction->GetLocations();
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100971 Location out = locations->Out();
972 DCHECK_EQ(locations->InAt(0).AsX86().AsCpuRegister(), out.AsX86().AsCpuRegister());
973 __ xorl(out.AsX86().AsCpuRegister(), Immediate(1));
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100974}
975
Nicolas Geoffray412f10c2014-06-19 10:00:34 +0100976void LocationsBuilderX86::VisitCompare(HCompare* compare) {
977 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(compare);
978 locations->SetInAt(0, Location::RequiresRegister());
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100979 locations->SetInAt(1, Location::Any());
Nicolas Geoffray412f10c2014-06-19 10:00:34 +0100980 locations->SetOut(Location::RequiresRegister());
981 compare->SetLocations(locations);
982}
983
984void InstructionCodeGeneratorX86::VisitCompare(HCompare* compare) {
985 Label greater, done;
986 LocationSummary* locations = compare->GetLocations();
987 switch (compare->InputAt(0)->GetType()) {
988 case Primitive::kPrimLong: {
989 Label less, greater, done;
990 Register output = locations->Out().AsX86().AsCpuRegister();
991 X86ManagedRegister left = locations->InAt(0).AsX86();
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100992 Location right = locations->InAt(1);
993 if (right.IsRegister()) {
994 __ cmpl(left.AsRegisterPairHigh(), right.AsX86().AsRegisterPairHigh());
995 } else {
996 DCHECK(right.IsDoubleStackSlot());
997 __ cmpl(left.AsRegisterPairHigh(), Address(ESP, right.GetHighStackIndex(kX86WordSize)));
998 }
Nicolas Geoffray412f10c2014-06-19 10:00:34 +0100999 __ j(kLess, &less); // Signed compare.
1000 __ j(kGreater, &greater); // Signed compare.
Nicolas Geoffraye5038322014-07-04 09:41:32 +01001001 if (right.IsRegister()) {
1002 __ cmpl(left.AsRegisterPairLow(), right.AsX86().AsRegisterPairLow());
1003 } else {
1004 DCHECK(right.IsDoubleStackSlot());
1005 __ cmpl(left.AsRegisterPairLow(), Address(ESP, right.GetStackIndex()));
1006 }
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01001007 __ movl(output, Immediate(0));
1008 __ j(kEqual, &done);
1009 __ j(kBelow, &less); // Unsigned compare.
1010
1011 __ Bind(&greater);
1012 __ movl(output, Immediate(1));
1013 __ jmp(&done);
1014
1015 __ Bind(&less);
1016 __ movl(output, Immediate(-1));
1017
1018 __ Bind(&done);
1019 break;
1020 }
1021 default:
1022 LOG(FATAL) << "Unimplemented compare type " << compare->InputAt(0)->GetType();
1023 }
1024}
1025
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001026void LocationsBuilderX86::VisitPhi(HPhi* instruction) {
Nicolas Geoffray31d76b42014-06-09 15:02:22 +01001027 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
1028 for (size_t i = 0, e = instruction->InputCount(); i < e; ++i) {
1029 locations->SetInAt(i, Location::Any());
1030 }
1031 locations->SetOut(Location::Any());
1032 instruction->SetLocations(locations);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001033}
1034
1035void InstructionCodeGeneratorX86::VisitPhi(HPhi* instruction) {
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001036 LOG(FATAL) << "Unreachable";
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001037}
1038
Nicolas Geoffraye5038322014-07-04 09:41:32 +01001039void LocationsBuilderX86::VisitInstanceFieldSet(HInstanceFieldSet* instruction) {
1040 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
1041 locations->SetInAt(0, Location::RequiresRegister());
1042 Primitive::Type field_type = instruction->InputAt(1)->GetType();
1043 if (field_type == Primitive::kPrimBoolean || field_type == Primitive::kPrimByte) {
1044 // Ensure the value is in a byte register.
1045 locations->SetInAt(1, X86CpuLocation(EAX));
1046 } else {
1047 locations->SetInAt(1, Location::RequiresRegister());
1048 }
Nicolas Geoffray1a43dd72014-07-17 15:15:34 +01001049 // Temporary registers for the write barrier.
1050 if (instruction->InputAt(1)->GetType() == Primitive::kPrimNot) {
1051 locations->AddTemp(Location::RequiresRegister());
1052 // Ensure the card is in a byte register.
1053 locations->AddTemp(X86CpuLocation(ECX));
1054 }
Nicolas Geoffraye5038322014-07-04 09:41:32 +01001055 instruction->SetLocations(locations);
1056}
1057
1058void InstructionCodeGeneratorX86::VisitInstanceFieldSet(HInstanceFieldSet* instruction) {
1059 LocationSummary* locations = instruction->GetLocations();
1060 Register obj = locations->InAt(0).AsX86().AsCpuRegister();
1061 uint32_t offset = instruction->GetFieldOffset().Uint32Value();
1062 Primitive::Type field_type = instruction->InputAt(1)->GetType();
1063
1064 switch (field_type) {
1065 case Primitive::kPrimBoolean:
1066 case Primitive::kPrimByte: {
1067 ByteRegister value = locations->InAt(1).AsX86().AsByteRegister();
1068 __ movb(Address(obj, offset), value);
1069 break;
1070 }
1071
1072 case Primitive::kPrimShort:
1073 case Primitive::kPrimChar: {
1074 Register value = locations->InAt(1).AsX86().AsCpuRegister();
1075 __ movw(Address(obj, offset), value);
1076 break;
1077 }
1078
Nicolas Geoffray1a43dd72014-07-17 15:15:34 +01001079 case Primitive::kPrimInt: {
1080 Register value = locations->InAt(1).AsX86().AsCpuRegister();
1081 __ movl(Address(obj, offset), value);
1082 break;
1083 }
1084
Nicolas Geoffraye5038322014-07-04 09:41:32 +01001085 case Primitive::kPrimNot: {
1086 Register value = locations->InAt(1).AsX86().AsCpuRegister();
1087 __ movl(Address(obj, offset), value);
Nicolas Geoffray1a43dd72014-07-17 15:15:34 +01001088 Label is_null;
1089 Register temp = locations->GetTemp(0).AsX86().AsCpuRegister();
1090 Register card = locations->GetTemp(1).AsX86().AsCpuRegister();
1091 __ testl(value, value);
1092 __ j(kEqual, &is_null);
1093 __ fs()->movl(card, Address::Absolute(Thread::CardTableOffset<kX86WordSize>().Int32Value()));
1094 __ movl(temp, obj);
1095 __ shrl(temp, Immediate(gc::accounting::CardTable::kCardShift));
1096 __ movb(Address(temp, card, TIMES_1, 0), locations->GetTemp(1).AsX86().AsByteRegister());
1097 __ Bind(&is_null);
Nicolas Geoffraye5038322014-07-04 09:41:32 +01001098 break;
1099 }
1100
1101 case Primitive::kPrimLong: {
1102 X86ManagedRegister value = locations->InAt(1).AsX86();
1103 __ movl(Address(obj, offset), value.AsRegisterPairLow());
1104 __ movl(Address(obj, kX86WordSize + offset), value.AsRegisterPairHigh());
1105 break;
1106 }
1107
1108 case Primitive::kPrimFloat:
1109 case Primitive::kPrimDouble:
1110 LOG(FATAL) << "Unimplemented register type " << field_type;
1111
1112 case Primitive::kPrimVoid:
1113 LOG(FATAL) << "Unreachable type " << field_type;
1114 }
1115}
1116
1117void LocationsBuilderX86::VisitInstanceFieldGet(HInstanceFieldGet* instruction) {
1118 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
1119 locations->SetInAt(0, Location::RequiresRegister());
1120 locations->SetOut(Location::RequiresRegister());
1121 instruction->SetLocations(locations);
1122}
1123
1124void InstructionCodeGeneratorX86::VisitInstanceFieldGet(HInstanceFieldGet* instruction) {
1125 LocationSummary* locations = instruction->GetLocations();
1126 Register obj = locations->InAt(0).AsX86().AsCpuRegister();
1127 uint32_t offset = instruction->GetFieldOffset().Uint32Value();
1128
1129 switch (instruction->GetType()) {
1130 case Primitive::kPrimBoolean: {
1131 Register out = locations->Out().AsX86().AsCpuRegister();
1132 __ movzxb(out, Address(obj, offset));
1133 break;
1134 }
1135
1136 case Primitive::kPrimByte: {
1137 Register out = locations->Out().AsX86().AsCpuRegister();
1138 __ movsxb(out, Address(obj, offset));
1139 break;
1140 }
1141
1142 case Primitive::kPrimShort: {
1143 Register out = locations->Out().AsX86().AsCpuRegister();
1144 __ movsxw(out, Address(obj, offset));
1145 break;
1146 }
1147
1148 case Primitive::kPrimChar: {
1149 Register out = locations->Out().AsX86().AsCpuRegister();
1150 __ movzxw(out, Address(obj, offset));
1151 break;
1152 }
1153
1154 case Primitive::kPrimInt:
1155 case Primitive::kPrimNot: {
1156 Register out = locations->Out().AsX86().AsCpuRegister();
1157 __ movl(out, Address(obj, offset));
1158 break;
1159 }
1160
1161 case Primitive::kPrimLong: {
1162 // TODO: support volatile.
1163 X86ManagedRegister out = locations->Out().AsX86();
1164 __ movl(out.AsRegisterPairLow(), Address(obj, offset));
1165 __ movl(out.AsRegisterPairHigh(), Address(obj, kX86WordSize + offset));
1166 break;
1167 }
1168
1169 case Primitive::kPrimFloat:
1170 case Primitive::kPrimDouble:
1171 LOG(FATAL) << "Unimplemented register type " << instruction->GetType();
1172
1173 case Primitive::kPrimVoid:
1174 LOG(FATAL) << "Unreachable type " << instruction->GetType();
1175 }
1176}
1177
1178void LocationsBuilderX86::VisitNullCheck(HNullCheck* instruction) {
1179 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
1180 locations->SetInAt(0, Location::Any());
1181 // TODO: Have a normalization phase that makes this instruction never used.
1182 locations->SetOut(Location::SameAsFirstInput());
1183 instruction->SetLocations(locations);
1184}
1185
1186void InstructionCodeGeneratorX86::VisitNullCheck(HNullCheck* instruction) {
1187 SlowPathCode* slow_path =
1188 new (GetGraph()->GetArena()) NullCheckSlowPathX86(instruction->GetDexPc());
1189 codegen_->AddSlowPath(slow_path);
1190
1191 LocationSummary* locations = instruction->GetLocations();
1192 Location obj = locations->InAt(0);
1193 DCHECK(obj.Equals(locations->Out()));
1194
1195 if (obj.IsRegister()) {
1196 __ cmpl(obj.AsX86().AsCpuRegister(), Immediate(0));
1197 } else {
1198 DCHECK(locations->InAt(0).IsStackSlot());
1199 __ cmpl(Address(ESP, obj.GetStackIndex()), Immediate(0));
1200 }
1201 __ j(kEqual, slow_path->GetEntryLabel());
1202}
1203
1204void LocationsBuilderX86::VisitTemporary(HTemporary* temp) {
1205 temp->SetLocations(nullptr);
1206}
1207
1208void InstructionCodeGeneratorX86::VisitTemporary(HTemporary* temp) {
1209 // Nothing to do, this is driven by the code generator.
1210}
1211
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01001212void LocationsBuilderX86::VisitParallelMove(HParallelMove* instruction) {
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001213 LOG(FATAL) << "Unreachable";
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01001214}
1215
1216void InstructionCodeGeneratorX86::VisitParallelMove(HParallelMove* instruction) {
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001217 codegen_->GetMoveResolver()->EmitNativeCode(instruction);
1218}
1219
1220X86Assembler* ParallelMoveResolverX86::GetAssembler() const {
1221 return codegen_->GetAssembler();
1222}
1223
1224void ParallelMoveResolverX86::MoveMemoryToMemory(int dst, int src) {
1225 ScratchRegisterScope ensure_scratch(
Nicolas Geoffraye27f31a2014-06-12 17:53:14 +01001226 this, kNoRegister, EAX, codegen_->GetNumberOfCoreRegisters());
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001227 int stack_offset = ensure_scratch.IsSpilled() ? kX86WordSize : 0;
1228 __ movl(static_cast<Register>(ensure_scratch.GetRegister()), Address(ESP, src + stack_offset));
1229 __ movl(Address(ESP, dst + stack_offset), static_cast<Register>(ensure_scratch.GetRegister()));
1230}
1231
1232void ParallelMoveResolverX86::EmitMove(size_t index) {
1233 MoveOperands* move = moves_.Get(index);
1234 Location source = move->GetSource();
1235 Location destination = move->GetDestination();
1236
1237 if (source.IsRegister()) {
1238 if (destination.IsRegister()) {
1239 __ movl(destination.AsX86().AsCpuRegister(), source.AsX86().AsCpuRegister());
1240 } else {
1241 DCHECK(destination.IsStackSlot());
1242 __ movl(Address(ESP, destination.GetStackIndex()), source.AsX86().AsCpuRegister());
1243 }
1244 } else if (source.IsStackSlot()) {
1245 if (destination.IsRegister()) {
1246 __ movl(destination.AsX86().AsCpuRegister(), Address(ESP, source.GetStackIndex()));
1247 } else {
1248 DCHECK(destination.IsStackSlot());
1249 MoveMemoryToMemory(destination.GetStackIndex(),
1250 source.GetStackIndex());
1251 }
Nicolas Geoffray96f89a22014-07-11 10:57:49 +01001252 } else if (source.IsConstant()) {
1253 HIntConstant* instruction = source.GetConstant()->AsIntConstant();
1254 Immediate imm(instruction->AsIntConstant()->GetValue());
1255 if (destination.IsRegister()) {
1256 __ movl(destination.AsX86().AsCpuRegister(), imm);
1257 } else {
1258 __ movl(Address(ESP, destination.GetStackIndex()), imm);
1259 }
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001260 } else {
1261 LOG(FATAL) << "Unimplemented";
1262 }
1263}
1264
1265void ParallelMoveResolverX86::Exchange(Register reg, int mem) {
Nicolas Geoffraye27f31a2014-06-12 17:53:14 +01001266 Register suggested_scratch = reg == EAX ? EBX : EAX;
1267 ScratchRegisterScope ensure_scratch(
1268 this, reg, suggested_scratch, codegen_->GetNumberOfCoreRegisters());
1269
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001270 int stack_offset = ensure_scratch.IsSpilled() ? kX86WordSize : 0;
1271 __ movl(static_cast<Register>(ensure_scratch.GetRegister()), Address(ESP, mem + stack_offset));
1272 __ movl(Address(ESP, mem + stack_offset), reg);
1273 __ movl(reg, static_cast<Register>(ensure_scratch.GetRegister()));
1274}
1275
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001276void ParallelMoveResolverX86::Exchange(int mem1, int mem2) {
1277 ScratchRegisterScope ensure_scratch1(
Nicolas Geoffraye27f31a2014-06-12 17:53:14 +01001278 this, kNoRegister, EAX, codegen_->GetNumberOfCoreRegisters());
1279
1280 Register suggested_scratch = ensure_scratch1.GetRegister() == EAX ? EBX : EAX;
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001281 ScratchRegisterScope ensure_scratch2(
Nicolas Geoffraye27f31a2014-06-12 17:53:14 +01001282 this, ensure_scratch1.GetRegister(), suggested_scratch, codegen_->GetNumberOfCoreRegisters());
1283
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001284 int stack_offset = ensure_scratch1.IsSpilled() ? kX86WordSize : 0;
1285 stack_offset += ensure_scratch2.IsSpilled() ? kX86WordSize : 0;
1286 __ movl(static_cast<Register>(ensure_scratch1.GetRegister()), Address(ESP, mem1 + stack_offset));
1287 __ movl(static_cast<Register>(ensure_scratch2.GetRegister()), Address(ESP, mem2 + stack_offset));
1288 __ movl(Address(ESP, mem2 + stack_offset), static_cast<Register>(ensure_scratch1.GetRegister()));
1289 __ movl(Address(ESP, mem1 + stack_offset), static_cast<Register>(ensure_scratch2.GetRegister()));
1290}
1291
1292void ParallelMoveResolverX86::EmitSwap(size_t index) {
1293 MoveOperands* move = moves_.Get(index);
1294 Location source = move->GetSource();
1295 Location destination = move->GetDestination();
1296
1297 if (source.IsRegister() && destination.IsRegister()) {
1298 __ xchgl(destination.AsX86().AsCpuRegister(), source.AsX86().AsCpuRegister());
1299 } else if (source.IsRegister() && destination.IsStackSlot()) {
1300 Exchange(source.AsX86().AsCpuRegister(), destination.GetStackIndex());
1301 } else if (source.IsStackSlot() && destination.IsRegister()) {
1302 Exchange(destination.AsX86().AsCpuRegister(), source.GetStackIndex());
1303 } else if (source.IsStackSlot() && destination.IsStackSlot()) {
1304 Exchange(destination.GetStackIndex(), source.GetStackIndex());
1305 } else {
1306 LOG(FATAL) << "Unimplemented";
1307 }
1308}
1309
1310void ParallelMoveResolverX86::SpillScratch(int reg) {
1311 __ pushl(static_cast<Register>(reg));
1312}
1313
1314void ParallelMoveResolverX86::RestoreScratch(int reg) {
1315 __ popl(static_cast<Register>(reg));
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01001316}
1317
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +00001318} // namespace x86
1319} // namespace art