blob: 251a2adf614a14c8cfcc3468ad0cb541ff3cd26b [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 Geoffray397f2e42014-07-23 12:57:19 +0100205 bool skip_overflow_check = IsLeafMethod() && !IsLargeFrame(GetFrameSize(), InstructionSet::kX86);
206 if (!skip_overflow_check && !kExplicitStackOverflowCheck) {
207 __ testl(EAX, Address(ESP, -static_cast<int32_t>(GetStackOverflowReservedBytes(kX86))));
208 RecordPcInfo(0);
209 }
210
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100211 // The return PC has already been pushed on the stack.
Nicolas Geoffray707c8092014-04-04 10:50:14 +0100212 __ subl(ESP, Immediate(GetFrameSize() - kNumberOfPushedRegistersAtEntry * kX86WordSize));
Nicolas Geoffrayf12feb82014-07-17 18:32:41 +0100213
Nicolas Geoffray397f2e42014-07-23 12:57:19 +0100214 if (!skip_overflow_check && kExplicitStackOverflowCheck) {
215 SlowPathCode* slow_path = new (GetGraph()->GetArena()) StackOverflowCheckSlowPathX86();
216 AddSlowPath(slow_path);
Nicolas Geoffrayf12feb82014-07-17 18:32:41 +0100217
Nicolas Geoffray397f2e42014-07-23 12:57:19 +0100218 __ fs()->cmpl(ESP, Address::Absolute(Thread::StackEndOffset<kX86WordSize>()));
219 __ j(kLess, slow_path->GetEntryLabel());
Nicolas Geoffrayf12feb82014-07-17 18:32:41 +0100220 }
221
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100222 __ movl(Address(ESP, kCurrentMethodStackOffset), EAX);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000223}
224
225void CodeGeneratorX86::GenerateFrameExit() {
Nicolas Geoffray707c8092014-04-04 10:50:14 +0100226 __ addl(ESP, Immediate(GetFrameSize() - kNumberOfPushedRegistersAtEntry * kX86WordSize));
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000227}
228
229void CodeGeneratorX86::Bind(Label* label) {
230 __ Bind(label);
231}
232
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000233void InstructionCodeGeneratorX86::LoadCurrentMethod(Register reg) {
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100234 __ movl(reg, Address(ESP, kCurrentMethodStackOffset));
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000235}
236
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100237Location CodeGeneratorX86::GetStackLocation(HLoadLocal* load) const {
238 switch (load->GetType()) {
239 case Primitive::kPrimLong:
240 return Location::DoubleStackSlot(GetStackSlot(load->GetLocal()));
241 break;
242
243 case Primitive::kPrimInt:
244 case Primitive::kPrimNot:
245 return Location::StackSlot(GetStackSlot(load->GetLocal()));
246
247 case Primitive::kPrimFloat:
248 case Primitive::kPrimDouble:
249 LOG(FATAL) << "Unimplemented type " << load->GetType();
250
251 case Primitive::kPrimBoolean:
252 case Primitive::kPrimByte:
253 case Primitive::kPrimChar:
254 case Primitive::kPrimShort:
255 case Primitive::kPrimVoid:
256 LOG(FATAL) << "Unexpected type " << load->GetType();
257 }
258
259 LOG(FATAL) << "Unreachable";
260 return Location();
261}
262
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100263static constexpr Register kRuntimeParameterCoreRegisters[] = { EAX, ECX, EDX };
264static constexpr size_t kRuntimeParameterCoreRegistersLength =
265 arraysize(kRuntimeParameterCoreRegisters);
266
267class InvokeRuntimeCallingConvention : public CallingConvention<Register> {
268 public:
269 InvokeRuntimeCallingConvention()
270 : CallingConvention(kRuntimeParameterCoreRegisters,
271 kRuntimeParameterCoreRegistersLength) {}
272
273 private:
274 DISALLOW_COPY_AND_ASSIGN(InvokeRuntimeCallingConvention);
275};
276
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100277Location InvokeDexCallingConventionVisitor::GetNextLocation(Primitive::Type type) {
278 switch (type) {
279 case Primitive::kPrimBoolean:
280 case Primitive::kPrimByte:
281 case Primitive::kPrimChar:
282 case Primitive::kPrimShort:
283 case Primitive::kPrimInt:
284 case Primitive::kPrimNot: {
285 uint32_t index = gp_index_++;
286 if (index < calling_convention.GetNumberOfRegisters()) {
287 return X86CpuLocation(calling_convention.GetRegisterAt(index));
288 } else {
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100289 return Location::StackSlot(calling_convention.GetStackOffsetOf(index));
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100290 }
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100291 }
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100292
293 case Primitive::kPrimLong: {
294 uint32_t index = gp_index_;
295 gp_index_ += 2;
296 if (index + 1 < calling_convention.GetNumberOfRegisters()) {
297 return Location::RegisterLocation(X86ManagedRegister::FromRegisterPair(
298 calling_convention.GetRegisterPairAt(index)));
299 } else if (index + 1 == calling_convention.GetNumberOfRegisters()) {
300 return Location::QuickParameter(index);
301 } else {
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100302 return Location::DoubleStackSlot(calling_convention.GetStackOffsetOf(index));
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100303 }
304 }
305
306 case Primitive::kPrimDouble:
307 case Primitive::kPrimFloat:
308 LOG(FATAL) << "Unimplemented parameter type " << type;
309 break;
310
311 case Primitive::kPrimVoid:
312 LOG(FATAL) << "Unexpected parameter type " << type;
313 break;
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100314 }
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100315 return Location();
316}
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100317
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100318void CodeGeneratorX86::Move32(Location destination, Location source) {
319 if (source.Equals(destination)) {
320 return;
321 }
322 if (destination.IsRegister()) {
323 if (source.IsRegister()) {
324 __ movl(destination.AsX86().AsCpuRegister(), source.AsX86().AsCpuRegister());
325 } else {
326 DCHECK(source.IsStackSlot());
327 __ movl(destination.AsX86().AsCpuRegister(), Address(ESP, source.GetStackIndex()));
328 }
329 } else {
330 if (source.IsRegister()) {
331 __ movl(Address(ESP, destination.GetStackIndex()), source.AsX86().AsCpuRegister());
332 } else {
333 DCHECK(source.IsStackSlot());
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100334 __ pushl(Address(ESP, source.GetStackIndex()));
335 __ popl(Address(ESP, destination.GetStackIndex()));
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100336 }
337 }
338}
339
340void CodeGeneratorX86::Move64(Location destination, Location source) {
341 if (source.Equals(destination)) {
342 return;
343 }
344 if (destination.IsRegister()) {
345 if (source.IsRegister()) {
346 __ movl(destination.AsX86().AsRegisterPairLow(), source.AsX86().AsRegisterPairLow());
347 __ movl(destination.AsX86().AsRegisterPairHigh(), source.AsX86().AsRegisterPairHigh());
348 } else if (source.IsQuickParameter()) {
349 uint32_t argument_index = source.GetQuickParameterIndex();
350 InvokeDexCallingConvention calling_convention;
351 __ movl(destination.AsX86().AsRegisterPairLow(),
352 calling_convention.GetRegisterAt(argument_index));
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100353 __ movl(destination.AsX86().AsRegisterPairHigh(), Address(ESP,
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100354 calling_convention.GetStackOffsetOf(argument_index + 1) + GetFrameSize()));
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100355 } else {
356 DCHECK(source.IsDoubleStackSlot());
357 __ movl(destination.AsX86().AsRegisterPairLow(), Address(ESP, source.GetStackIndex()));
358 __ movl(destination.AsX86().AsRegisterPairHigh(),
359 Address(ESP, source.GetHighStackIndex(kX86WordSize)));
360 }
361 } else if (destination.IsQuickParameter()) {
362 InvokeDexCallingConvention calling_convention;
363 uint32_t argument_index = destination.GetQuickParameterIndex();
364 if (source.IsRegister()) {
365 __ movl(calling_convention.GetRegisterAt(argument_index), source.AsX86().AsRegisterPairLow());
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100366 __ movl(Address(ESP, calling_convention.GetStackOffsetOf(argument_index + 1)),
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100367 source.AsX86().AsRegisterPairHigh());
368 } else {
369 DCHECK(source.IsDoubleStackSlot());
370 __ movl(calling_convention.GetRegisterAt(argument_index),
371 Address(ESP, source.GetStackIndex()));
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100372 __ pushl(Address(ESP, source.GetHighStackIndex(kX86WordSize)));
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100373 __ popl(Address(ESP, calling_convention.GetStackOffsetOf(argument_index + 1)));
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100374 }
375 } else {
376 if (source.IsRegister()) {
377 __ movl(Address(ESP, destination.GetStackIndex()), source.AsX86().AsRegisterPairLow());
378 __ movl(Address(ESP, destination.GetHighStackIndex(kX86WordSize)),
379 source.AsX86().AsRegisterPairHigh());
380 } else if (source.IsQuickParameter()) {
381 InvokeDexCallingConvention calling_convention;
382 uint32_t argument_index = source.GetQuickParameterIndex();
383 __ movl(Address(ESP, destination.GetStackIndex()),
384 calling_convention.GetRegisterAt(argument_index));
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100385 __ pushl(Address(ESP,
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100386 calling_convention.GetStackOffsetOf(argument_index + 1) + GetFrameSize()));
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100387 __ popl(Address(ESP, destination.GetHighStackIndex(kX86WordSize)));
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100388 } else {
389 DCHECK(source.IsDoubleStackSlot());
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100390 __ pushl(Address(ESP, source.GetStackIndex()));
391 __ popl(Address(ESP, destination.GetStackIndex()));
392 __ pushl(Address(ESP, source.GetHighStackIndex(kX86WordSize)));
393 __ popl(Address(ESP, destination.GetHighStackIndex(kX86WordSize)));
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100394 }
395 }
396}
397
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100398void CodeGeneratorX86::Move(HInstruction* instruction, Location location, HInstruction* move_for) {
399 if (instruction->AsIntConstant() != nullptr) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100400 Immediate imm(instruction->AsIntConstant()->GetValue());
401 if (location.IsRegister()) {
402 __ movl(location.AsX86().AsCpuRegister(), imm);
403 } else {
404 __ movl(Address(ESP, location.GetStackIndex()), imm);
405 }
406 } else if (instruction->AsLongConstant() != nullptr) {
407 int64_t value = instruction->AsLongConstant()->GetValue();
408 if (location.IsRegister()) {
409 __ movl(location.AsX86().AsRegisterPairLow(), Immediate(Low32Bits(value)));
410 __ movl(location.AsX86().AsRegisterPairHigh(), Immediate(High32Bits(value)));
411 } else {
412 __ movl(Address(ESP, location.GetStackIndex()), Immediate(Low32Bits(value)));
413 __ movl(Address(ESP, location.GetHighStackIndex(kX86WordSize)), Immediate(High32Bits(value)));
414 }
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100415 } else if (instruction->AsLoadLocal() != nullptr) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100416 switch (instruction->GetType()) {
417 case Primitive::kPrimBoolean:
418 case Primitive::kPrimByte:
419 case Primitive::kPrimChar:
420 case Primitive::kPrimShort:
421 case Primitive::kPrimInt:
422 case Primitive::kPrimNot:
423 Move32(location, Location::StackSlot(GetStackSlot(instruction->AsLoadLocal()->GetLocal())));
424 break;
425
426 case Primitive::kPrimLong:
427 Move64(location, Location::DoubleStackSlot(
428 GetStackSlot(instruction->AsLoadLocal()->GetLocal())));
429 break;
430
431 default:
432 LOG(FATAL) << "Unimplemented local type " << instruction->GetType();
433 }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000434 } else {
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100435 DCHECK((instruction->GetNext() == move_for) || instruction->GetNext()->IsTemporary());
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100436 switch (instruction->GetType()) {
437 case Primitive::kPrimBoolean:
438 case Primitive::kPrimByte:
439 case Primitive::kPrimChar:
440 case Primitive::kPrimShort:
441 case Primitive::kPrimInt:
442 case Primitive::kPrimNot:
443 Move32(location, instruction->GetLocations()->Out());
444 break;
445
446 case Primitive::kPrimLong:
447 Move64(location, instruction->GetLocations()->Out());
448 break;
449
450 default:
451 LOG(FATAL) << "Unimplemented type " << instruction->GetType();
452 }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000453 }
454}
455
456void LocationsBuilderX86::VisitGoto(HGoto* got) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000457 got->SetLocations(nullptr);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000458}
459
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000460void InstructionCodeGeneratorX86::VisitGoto(HGoto* got) {
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000461 HBasicBlock* successor = got->GetSuccessor();
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000462 if (GetGraph()->GetExitBlock() == successor) {
463 codegen_->GenerateFrameExit();
464 } else if (!codegen_->GoesToNextBlock(got->GetBlock(), successor)) {
465 __ jmp(codegen_->GetLabelOf(successor));
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000466 }
467}
468
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000469void LocationsBuilderX86::VisitExit(HExit* exit) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000470 exit->SetLocations(nullptr);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000471}
472
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000473void InstructionCodeGeneratorX86::VisitExit(HExit* exit) {
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000474 if (kIsDebugBuild) {
475 __ Comment("Unreachable");
476 __ int3();
477 }
478}
479
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000480void LocationsBuilderX86::VisitIf(HIf* if_instr) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000481 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(if_instr);
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100482 HInstruction* cond = if_instr->InputAt(0);
483 DCHECK(cond->IsCondition());
484 HCondition* condition = cond->AsCondition();
485 if (condition->NeedsMaterialization()) {
486 locations->SetInAt(0, Location::Any());
487 }
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000488 if_instr->SetLocations(locations);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000489}
490
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000491void InstructionCodeGeneratorX86::VisitIf(HIf* if_instr) {
Dave Allison20dfc792014-06-16 20:44:29 -0700492 HInstruction* cond = if_instr->InputAt(0);
493 DCHECK(cond->IsCondition());
494 HCondition* condition = cond->AsCondition();
495 if (condition->NeedsMaterialization()) {
496 // Materialized condition, compare against 0
497 Location lhs = if_instr->GetLocations()->InAt(0);
498 if (lhs.IsRegister()) {
499 __ cmpl(lhs.AsX86().AsCpuRegister(), Immediate(0));
500 } else {
501 __ cmpl(Address(ESP, lhs.GetStackIndex()), Immediate(0));
502 }
503 __ j(kEqual, codegen_->GetLabelOf(if_instr->IfTrueSuccessor()));
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100504 } else {
Dave Allison20dfc792014-06-16 20:44:29 -0700505 Location lhs = condition->GetLocations()->InAt(0);
506 Location rhs = condition->GetLocations()->InAt(1);
507 // LHS is guaranteed to be in a register (see LocationsBuilderX86::VisitCondition).
508 if (rhs.IsRegister()) {
509 __ cmpl(lhs.AsX86().AsCpuRegister(), rhs.AsX86().AsCpuRegister());
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100510 } else if (rhs.IsConstant()) {
511 HIntConstant* instruction = rhs.GetConstant()->AsIntConstant();
512 Immediate imm(instruction->AsIntConstant()->GetValue());
513 __ cmpl(lhs.AsX86().AsCpuRegister(), imm);
Dave Allison20dfc792014-06-16 20:44:29 -0700514 } else {
515 __ cmpl(lhs.AsX86().AsCpuRegister(), Address(ESP, rhs.GetStackIndex()));
516 }
517 __ j(X86Condition(condition->GetCondition()),
518 codegen_->GetLabelOf(if_instr->IfTrueSuccessor()));
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100519 }
Dave Allison20dfc792014-06-16 20:44:29 -0700520 if (!codegen_->GoesToNextBlock(if_instr->GetBlock(), if_instr->IfFalseSuccessor())) {
521 __ jmp(codegen_->GetLabelOf(if_instr->IfFalseSuccessor()));
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000522 }
523}
524
525void LocationsBuilderX86::VisitLocal(HLocal* local) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000526 local->SetLocations(nullptr);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000527}
528
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000529void InstructionCodeGeneratorX86::VisitLocal(HLocal* local) {
530 DCHECK_EQ(local->GetBlock(), GetGraph()->GetEntryBlock());
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000531}
532
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000533void LocationsBuilderX86::VisitLoadLocal(HLoadLocal* local) {
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100534 local->SetLocations(nullptr);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000535}
536
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000537void InstructionCodeGeneratorX86::VisitLoadLocal(HLoadLocal* load) {
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100538 // Nothing to do, this is driven by the code generator.
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000539}
540
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100541void LocationsBuilderX86::VisitStoreLocal(HStoreLocal* store) {
542 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(store);
543 switch (store->InputAt(1)->GetType()) {
544 case Primitive::kPrimBoolean:
545 case Primitive::kPrimByte:
546 case Primitive::kPrimChar:
547 case Primitive::kPrimShort:
548 case Primitive::kPrimInt:
549 case Primitive::kPrimNot:
550 locations->SetInAt(1, Location::StackSlot(codegen_->GetStackSlot(store->GetLocal())));
551 break;
552
553 case Primitive::kPrimLong:
554 locations->SetInAt(1, Location::DoubleStackSlot(codegen_->GetStackSlot(store->GetLocal())));
555 break;
556
557 default:
558 LOG(FATAL) << "Unimplemented local type " << store->InputAt(1)->GetType();
559 }
560 store->SetLocations(locations);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000561}
562
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000563void InstructionCodeGeneratorX86::VisitStoreLocal(HStoreLocal* store) {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000564}
565
Dave Allison20dfc792014-06-16 20:44:29 -0700566void LocationsBuilderX86::VisitCondition(HCondition* comp) {
567 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(comp);
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100568 locations->SetInAt(0, Location::RequiresRegister());
569 locations->SetInAt(1, Location::Any());
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100570 if (comp->NeedsMaterialization()) {
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100571 locations->SetOut(Location::RequiresRegister());
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100572 }
Dave Allison20dfc792014-06-16 20:44:29 -0700573 comp->SetLocations(locations);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000574}
575
Dave Allison20dfc792014-06-16 20:44:29 -0700576void InstructionCodeGeneratorX86::VisitCondition(HCondition* comp) {
577 if (comp->NeedsMaterialization()) {
578 LocationSummary* locations = comp->GetLocations();
579 if (locations->InAt(1).IsRegister()) {
580 __ cmpl(locations->InAt(0).AsX86().AsCpuRegister(),
581 locations->InAt(1).AsX86().AsCpuRegister());
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100582 } else if (locations->InAt(1).IsConstant()) {
583 HConstant* instruction = locations->InAt(1).GetConstant();
584 Immediate imm(instruction->AsIntConstant()->GetValue());
585 __ cmpl(locations->InAt(0).AsX86().AsCpuRegister(), imm);
Dave Allison20dfc792014-06-16 20:44:29 -0700586 } else {
587 __ cmpl(locations->InAt(0).AsX86().AsCpuRegister(),
588 Address(ESP, locations->InAt(1).GetStackIndex()));
589 }
590 __ setb(X86Condition(comp->GetCondition()), locations->Out().AsX86().AsCpuRegister());
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100591 }
Dave Allison20dfc792014-06-16 20:44:29 -0700592}
593
594void LocationsBuilderX86::VisitEqual(HEqual* comp) {
595 VisitCondition(comp);
596}
597
598void InstructionCodeGeneratorX86::VisitEqual(HEqual* comp) {
599 VisitCondition(comp);
600}
601
602void LocationsBuilderX86::VisitNotEqual(HNotEqual* comp) {
603 VisitCondition(comp);
604}
605
606void InstructionCodeGeneratorX86::VisitNotEqual(HNotEqual* comp) {
607 VisitCondition(comp);
608}
609
610void LocationsBuilderX86::VisitLessThan(HLessThan* comp) {
611 VisitCondition(comp);
612}
613
614void InstructionCodeGeneratorX86::VisitLessThan(HLessThan* comp) {
615 VisitCondition(comp);
616}
617
618void LocationsBuilderX86::VisitLessThanOrEqual(HLessThanOrEqual* comp) {
619 VisitCondition(comp);
620}
621
622void InstructionCodeGeneratorX86::VisitLessThanOrEqual(HLessThanOrEqual* comp) {
623 VisitCondition(comp);
624}
625
626void LocationsBuilderX86::VisitGreaterThan(HGreaterThan* comp) {
627 VisitCondition(comp);
628}
629
630void InstructionCodeGeneratorX86::VisitGreaterThan(HGreaterThan* comp) {
631 VisitCondition(comp);
632}
633
634void LocationsBuilderX86::VisitGreaterThanOrEqual(HGreaterThanOrEqual* comp) {
635 VisitCondition(comp);
636}
637
638void InstructionCodeGeneratorX86::VisitGreaterThanOrEqual(HGreaterThanOrEqual* comp) {
639 VisitCondition(comp);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000640}
641
642void LocationsBuilderX86::VisitIntConstant(HIntConstant* constant) {
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100643 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(constant);
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100644 locations->SetOut(Location::ConstantLocation(constant));
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100645 constant->SetLocations(locations);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000646}
647
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000648void InstructionCodeGeneratorX86::VisitIntConstant(HIntConstant* constant) {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000649}
650
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100651void LocationsBuilderX86::VisitLongConstant(HLongConstant* constant) {
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100652 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(constant);
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100653 locations->SetOut(Location::ConstantLocation(constant));
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100654 constant->SetLocations(locations);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100655}
656
657void InstructionCodeGeneratorX86::VisitLongConstant(HLongConstant* constant) {
658 // Will be generated at use site.
659}
660
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000661void LocationsBuilderX86::VisitReturnVoid(HReturnVoid* ret) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000662 ret->SetLocations(nullptr);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000663}
664
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000665void InstructionCodeGeneratorX86::VisitReturnVoid(HReturnVoid* ret) {
666 codegen_->GenerateFrameExit();
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000667 __ ret();
668}
669
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000670void LocationsBuilderX86::VisitReturn(HReturn* ret) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000671 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(ret);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100672 switch (ret->InputAt(0)->GetType()) {
673 case Primitive::kPrimBoolean:
674 case Primitive::kPrimByte:
675 case Primitive::kPrimChar:
676 case Primitive::kPrimShort:
677 case Primitive::kPrimInt:
678 case Primitive::kPrimNot:
679 locations->SetInAt(0, X86CpuLocation(EAX));
680 break;
681
682 case Primitive::kPrimLong:
683 locations->SetInAt(
684 0, Location::RegisterLocation(X86ManagedRegister::FromRegisterPair(EAX_EDX)));
685 break;
686
687 default:
688 LOG(FATAL) << "Unimplemented return type " << ret->InputAt(0)->GetType();
689 }
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000690 ret->SetLocations(locations);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000691}
692
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000693void InstructionCodeGeneratorX86::VisitReturn(HReturn* ret) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100694 if (kIsDebugBuild) {
695 switch (ret->InputAt(0)->GetType()) {
696 case Primitive::kPrimBoolean:
697 case Primitive::kPrimByte:
698 case Primitive::kPrimChar:
699 case Primitive::kPrimShort:
700 case Primitive::kPrimInt:
701 case Primitive::kPrimNot:
702 DCHECK_EQ(ret->GetLocations()->InAt(0).AsX86().AsCpuRegister(), EAX);
703 break;
704
705 case Primitive::kPrimLong:
706 DCHECK_EQ(ret->GetLocations()->InAt(0).AsX86().AsRegisterPair(), EAX_EDX);
707 break;
708
709 default:
710 LOG(FATAL) << "Unimplemented return type " << ret->InputAt(0)->GetType();
711 }
712 }
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000713 codegen_->GenerateFrameExit();
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000714 __ ret();
715}
716
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000717void LocationsBuilderX86::VisitInvokeStatic(HInvokeStatic* invoke) {
Nicolas Geoffrayf12feb82014-07-17 18:32:41 +0100718 codegen_->MarkNotLeaf();
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000719 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(invoke);
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100720 locations->AddTemp(X86CpuLocation(EAX));
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100721
722 InvokeDexCallingConventionVisitor calling_convention_visitor;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100723 for (size_t i = 0; i < invoke->InputCount(); i++) {
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100724 HInstruction* input = invoke->InputAt(i);
725 locations->SetInAt(i, calling_convention_visitor.GetNextLocation(input->GetType()));
726 }
727
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100728 switch (invoke->GetType()) {
729 case Primitive::kPrimBoolean:
730 case Primitive::kPrimByte:
731 case Primitive::kPrimChar:
732 case Primitive::kPrimShort:
733 case Primitive::kPrimInt:
734 case Primitive::kPrimNot:
735 locations->SetOut(X86CpuLocation(EAX));
736 break;
737
738 case Primitive::kPrimLong:
739 locations->SetOut(Location::RegisterLocation(X86ManagedRegister::FromRegisterPair(EAX_EDX)));
740 break;
741
742 case Primitive::kPrimVoid:
743 break;
744
745 case Primitive::kPrimDouble:
746 case Primitive::kPrimFloat:
747 LOG(FATAL) << "Unimplemented return type " << invoke->GetType();
748 break;
749 }
750
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000751 invoke->SetLocations(locations);
752}
753
754void InstructionCodeGeneratorX86::VisitInvokeStatic(HInvokeStatic* invoke) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100755 Register temp = invoke->GetLocations()->GetTemp(0).AsX86().AsCpuRegister();
Nicolas Geoffrayf61b5372014-06-25 14:35:34 +0100756 uint32_t heap_reference_size = sizeof(mirror::HeapReference<mirror::Object>);
757 size_t index_in_cache = mirror::Array::DataOffset(heap_reference_size).Int32Value() +
Nicolas Geoffray707c8092014-04-04 10:50:14 +0100758 invoke->GetIndexInDexCache() * kX86WordSize;
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000759
760 // TODO: Implement all kinds of calls:
761 // 1) boot -> boot
762 // 2) app -> boot
763 // 3) app -> app
764 //
765 // Currently we implement the app -> app logic, which looks up in the resolve cache.
766
767 // temp = method;
768 LoadCurrentMethod(temp);
769 // temp = temp->dex_cache_resolved_methods_;
770 __ movl(temp, Address(temp, mirror::ArtMethod::DexCacheResolvedMethodsOffset().Int32Value()));
771 // temp = temp[index_in_cache]
772 __ movl(temp, Address(temp, index_in_cache));
773 // (temp + offset_of_quick_compiled_code)()
774 __ call(Address(temp, mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset().Int32Value()));
775
Nicolas Geoffrayf12feb82014-07-17 18:32:41 +0100776 DCHECK(!codegen_->IsLeafMethod());
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000777 codegen_->RecordPcInfo(invoke->GetDexPc());
778}
779
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000780void LocationsBuilderX86::VisitAdd(HAdd* add) {
781 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(add);
782 switch (add->GetResultType()) {
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100783 case Primitive::kPrimInt:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100784 case Primitive::kPrimLong: {
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100785 locations->SetInAt(0, Location::RequiresRegister());
786 locations->SetInAt(1, Location::Any());
787 locations->SetOut(Location::SameAsFirstInput());
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100788 break;
789 }
790
791 case Primitive::kPrimBoolean:
792 case Primitive::kPrimByte:
793 case Primitive::kPrimChar:
794 case Primitive::kPrimShort:
795 LOG(FATAL) << "Unexpected add type " << add->GetResultType();
796 break;
797
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000798 default:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100799 LOG(FATAL) << "Unimplemented add type " << add->GetResultType();
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000800 }
801 add->SetLocations(locations);
802}
803
804void InstructionCodeGeneratorX86::VisitAdd(HAdd* add) {
805 LocationSummary* locations = add->GetLocations();
806 switch (add->GetResultType()) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100807 case Primitive::kPrimInt: {
808 DCHECK_EQ(locations->InAt(0).AsX86().AsCpuRegister(),
809 locations->Out().AsX86().AsCpuRegister());
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100810 if (locations->InAt(1).IsRegister()) {
811 __ addl(locations->InAt(0).AsX86().AsCpuRegister(),
812 locations->InAt(1).AsX86().AsCpuRegister());
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100813 } else if (locations->InAt(1).IsConstant()) {
814 HConstant* instruction = locations->InAt(1).GetConstant();
815 Immediate imm(instruction->AsIntConstant()->GetValue());
816 __ addl(locations->InAt(0).AsX86().AsCpuRegister(), imm);
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100817 } else {
818 __ addl(locations->InAt(0).AsX86().AsCpuRegister(),
819 Address(ESP, locations->InAt(1).GetStackIndex()));
820 }
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000821 break;
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100822 }
823
824 case Primitive::kPrimLong: {
825 DCHECK_EQ(locations->InAt(0).AsX86().AsRegisterPair(),
826 locations->Out().AsX86().AsRegisterPair());
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100827 if (locations->InAt(1).IsRegister()) {
828 __ addl(locations->InAt(0).AsX86().AsRegisterPairLow(),
829 locations->InAt(1).AsX86().AsRegisterPairLow());
830 __ adcl(locations->InAt(0).AsX86().AsRegisterPairHigh(),
831 locations->InAt(1).AsX86().AsRegisterPairHigh());
832 } else {
833 __ addl(locations->InAt(0).AsX86().AsRegisterPairLow(),
834 Address(ESP, locations->InAt(1).GetStackIndex()));
835 __ adcl(locations->InAt(0).AsX86().AsRegisterPairHigh(),
836 Address(ESP, locations->InAt(1).GetHighStackIndex(kX86WordSize)));
837 }
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100838 break;
839 }
840
841 case Primitive::kPrimBoolean:
842 case Primitive::kPrimByte:
843 case Primitive::kPrimChar:
844 case Primitive::kPrimShort:
845 LOG(FATAL) << "Unexpected add type " << add->GetResultType();
846 break;
847
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000848 default:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100849 LOG(FATAL) << "Unimplemented add type " << add->GetResultType();
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000850 }
851}
852
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100853void LocationsBuilderX86::VisitSub(HSub* sub) {
854 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(sub);
855 switch (sub->GetResultType()) {
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100856 case Primitive::kPrimInt:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100857 case Primitive::kPrimLong: {
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100858 locations->SetInAt(0, Location::RequiresRegister());
859 locations->SetInAt(1, Location::Any());
860 locations->SetOut(Location::SameAsFirstInput());
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100861 break;
862 }
863
864 case Primitive::kPrimBoolean:
865 case Primitive::kPrimByte:
866 case Primitive::kPrimChar:
867 case Primitive::kPrimShort:
868 LOG(FATAL) << "Unexpected sub type " << sub->GetResultType();
869 break;
870
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100871 default:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100872 LOG(FATAL) << "Unimplemented sub type " << sub->GetResultType();
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100873 }
874 sub->SetLocations(locations);
875}
876
877void InstructionCodeGeneratorX86::VisitSub(HSub* sub) {
878 LocationSummary* locations = sub->GetLocations();
879 switch (sub->GetResultType()) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100880 case Primitive::kPrimInt: {
881 DCHECK_EQ(locations->InAt(0).AsX86().AsCpuRegister(),
882 locations->Out().AsX86().AsCpuRegister());
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100883 if (locations->InAt(1).IsRegister()) {
884 __ subl(locations->InAt(0).AsX86().AsCpuRegister(),
885 locations->InAt(1).AsX86().AsCpuRegister());
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100886 } else if (locations->InAt(1).IsConstant()) {
887 HConstant* instruction = locations->InAt(1).GetConstant();
888 Immediate imm(instruction->AsIntConstant()->GetValue());
889 __ subl(locations->InAt(0).AsX86().AsCpuRegister(), imm);
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100890 } else {
891 __ subl(locations->InAt(0).AsX86().AsCpuRegister(),
892 Address(ESP, locations->InAt(1).GetStackIndex()));
893 }
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100894 break;
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100895 }
896
897 case Primitive::kPrimLong: {
898 DCHECK_EQ(locations->InAt(0).AsX86().AsRegisterPair(),
899 locations->Out().AsX86().AsRegisterPair());
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100900 if (locations->InAt(1).IsRegister()) {
901 __ subl(locations->InAt(0).AsX86().AsRegisterPairLow(),
902 locations->InAt(1).AsX86().AsRegisterPairLow());
903 __ sbbl(locations->InAt(0).AsX86().AsRegisterPairHigh(),
904 locations->InAt(1).AsX86().AsRegisterPairHigh());
905 } else {
906 __ subl(locations->InAt(0).AsX86().AsRegisterPairLow(),
907 Address(ESP, locations->InAt(1).GetStackIndex()));
908 __ sbbl(locations->InAt(0).AsX86().AsRegisterPairHigh(),
909 Address(ESP, locations->InAt(1).GetHighStackIndex(kX86WordSize)));
910 }
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100911 break;
912 }
913
914 case Primitive::kPrimBoolean:
915 case Primitive::kPrimByte:
916 case Primitive::kPrimChar:
917 case Primitive::kPrimShort:
918 LOG(FATAL) << "Unexpected sub type " << sub->GetResultType();
919 break;
920
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100921 default:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100922 LOG(FATAL) << "Unimplemented sub type " << sub->GetResultType();
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100923 }
924}
925
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100926void LocationsBuilderX86::VisitNewInstance(HNewInstance* instruction) {
Nicolas Geoffrayf12feb82014-07-17 18:32:41 +0100927 codegen_->MarkNotLeaf();
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100928 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100929 locations->SetOut(X86CpuLocation(EAX));
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100930 InvokeRuntimeCallingConvention calling_convention;
931 locations->AddTemp(X86CpuLocation(calling_convention.GetRegisterAt(0)));
932 locations->AddTemp(X86CpuLocation(calling_convention.GetRegisterAt(1)));
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100933 instruction->SetLocations(locations);
934}
935
936void InstructionCodeGeneratorX86::VisitNewInstance(HNewInstance* instruction) {
937 InvokeRuntimeCallingConvention calling_convention;
938 LoadCurrentMethod(calling_convention.GetRegisterAt(1));
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100939 __ movl(calling_convention.GetRegisterAt(0), Immediate(instruction->GetTypeIndex()));
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100940
Nicolas Geoffray707c8092014-04-04 10:50:14 +0100941 __ fs()->call(
942 Address::Absolute(QUICK_ENTRYPOINT_OFFSET(kX86WordSize, pAllocObjectWithAccessCheck)));
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100943
944 codegen_->RecordPcInfo(instruction->GetDexPc());
Nicolas Geoffrayf12feb82014-07-17 18:32:41 +0100945 DCHECK(!codegen_->IsLeafMethod());
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100946}
947
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100948void LocationsBuilderX86::VisitParameterValue(HParameterValue* instruction) {
949 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100950 Location location = parameter_visitor_.GetNextLocation(instruction->GetType());
951 if (location.IsStackSlot()) {
952 location = Location::StackSlot(location.GetStackIndex() + codegen_->GetFrameSize());
953 } else if (location.IsDoubleStackSlot()) {
954 location = Location::DoubleStackSlot(location.GetStackIndex() + codegen_->GetFrameSize());
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100955 }
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100956 locations->SetOut(location);
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100957 instruction->SetLocations(locations);
958}
959
960void InstructionCodeGeneratorX86::VisitParameterValue(HParameterValue* instruction) {
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100961}
962
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100963void LocationsBuilderX86::VisitNot(HNot* instruction) {
964 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100965 locations->SetInAt(0, Location::RequiresRegister());
966 locations->SetOut(Location::SameAsFirstInput());
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100967 instruction->SetLocations(locations);
968}
969
970void InstructionCodeGeneratorX86::VisitNot(HNot* instruction) {
971 LocationSummary* locations = instruction->GetLocations();
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100972 Location out = locations->Out();
973 DCHECK_EQ(locations->InAt(0).AsX86().AsCpuRegister(), out.AsX86().AsCpuRegister());
974 __ xorl(out.AsX86().AsCpuRegister(), Immediate(1));
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100975}
976
Nicolas Geoffray412f10c2014-06-19 10:00:34 +0100977void LocationsBuilderX86::VisitCompare(HCompare* compare) {
978 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(compare);
979 locations->SetInAt(0, Location::RequiresRegister());
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100980 locations->SetInAt(1, Location::Any());
Nicolas Geoffray412f10c2014-06-19 10:00:34 +0100981 locations->SetOut(Location::RequiresRegister());
982 compare->SetLocations(locations);
983}
984
985void InstructionCodeGeneratorX86::VisitCompare(HCompare* compare) {
986 Label greater, done;
987 LocationSummary* locations = compare->GetLocations();
988 switch (compare->InputAt(0)->GetType()) {
989 case Primitive::kPrimLong: {
990 Label less, greater, done;
991 Register output = locations->Out().AsX86().AsCpuRegister();
992 X86ManagedRegister left = locations->InAt(0).AsX86();
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100993 Location right = locations->InAt(1);
994 if (right.IsRegister()) {
995 __ cmpl(left.AsRegisterPairHigh(), right.AsX86().AsRegisterPairHigh());
996 } else {
997 DCHECK(right.IsDoubleStackSlot());
998 __ cmpl(left.AsRegisterPairHigh(), Address(ESP, right.GetHighStackIndex(kX86WordSize)));
999 }
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01001000 __ j(kLess, &less); // Signed compare.
1001 __ j(kGreater, &greater); // Signed compare.
Nicolas Geoffraye5038322014-07-04 09:41:32 +01001002 if (right.IsRegister()) {
1003 __ cmpl(left.AsRegisterPairLow(), right.AsX86().AsRegisterPairLow());
1004 } else {
1005 DCHECK(right.IsDoubleStackSlot());
1006 __ cmpl(left.AsRegisterPairLow(), Address(ESP, right.GetStackIndex()));
1007 }
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01001008 __ movl(output, Immediate(0));
1009 __ j(kEqual, &done);
1010 __ j(kBelow, &less); // Unsigned compare.
1011
1012 __ Bind(&greater);
1013 __ movl(output, Immediate(1));
1014 __ jmp(&done);
1015
1016 __ Bind(&less);
1017 __ movl(output, Immediate(-1));
1018
1019 __ Bind(&done);
1020 break;
1021 }
1022 default:
1023 LOG(FATAL) << "Unimplemented compare type " << compare->InputAt(0)->GetType();
1024 }
1025}
1026
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001027void LocationsBuilderX86::VisitPhi(HPhi* instruction) {
Nicolas Geoffray31d76b42014-06-09 15:02:22 +01001028 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
1029 for (size_t i = 0, e = instruction->InputCount(); i < e; ++i) {
1030 locations->SetInAt(i, Location::Any());
1031 }
1032 locations->SetOut(Location::Any());
1033 instruction->SetLocations(locations);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001034}
1035
1036void InstructionCodeGeneratorX86::VisitPhi(HPhi* instruction) {
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001037 LOG(FATAL) << "Unreachable";
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001038}
1039
Nicolas Geoffraye5038322014-07-04 09:41:32 +01001040void LocationsBuilderX86::VisitInstanceFieldSet(HInstanceFieldSet* instruction) {
1041 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
1042 locations->SetInAt(0, Location::RequiresRegister());
1043 Primitive::Type field_type = instruction->InputAt(1)->GetType();
1044 if (field_type == Primitive::kPrimBoolean || field_type == Primitive::kPrimByte) {
1045 // Ensure the value is in a byte register.
1046 locations->SetInAt(1, X86CpuLocation(EAX));
1047 } else {
1048 locations->SetInAt(1, Location::RequiresRegister());
1049 }
Nicolas Geoffray1a43dd72014-07-17 15:15:34 +01001050 // Temporary registers for the write barrier.
1051 if (instruction->InputAt(1)->GetType() == Primitive::kPrimNot) {
1052 locations->AddTemp(Location::RequiresRegister());
1053 // Ensure the card is in a byte register.
1054 locations->AddTemp(X86CpuLocation(ECX));
1055 }
Nicolas Geoffraye5038322014-07-04 09:41:32 +01001056 instruction->SetLocations(locations);
1057}
1058
1059void InstructionCodeGeneratorX86::VisitInstanceFieldSet(HInstanceFieldSet* instruction) {
1060 LocationSummary* locations = instruction->GetLocations();
1061 Register obj = locations->InAt(0).AsX86().AsCpuRegister();
1062 uint32_t offset = instruction->GetFieldOffset().Uint32Value();
1063 Primitive::Type field_type = instruction->InputAt(1)->GetType();
1064
1065 switch (field_type) {
1066 case Primitive::kPrimBoolean:
1067 case Primitive::kPrimByte: {
1068 ByteRegister value = locations->InAt(1).AsX86().AsByteRegister();
1069 __ movb(Address(obj, offset), value);
1070 break;
1071 }
1072
1073 case Primitive::kPrimShort:
1074 case Primitive::kPrimChar: {
1075 Register value = locations->InAt(1).AsX86().AsCpuRegister();
1076 __ movw(Address(obj, offset), value);
1077 break;
1078 }
1079
Nicolas Geoffray1a43dd72014-07-17 15:15:34 +01001080 case Primitive::kPrimInt: {
1081 Register value = locations->InAt(1).AsX86().AsCpuRegister();
1082 __ movl(Address(obj, offset), value);
1083 break;
1084 }
1085
Nicolas Geoffraye5038322014-07-04 09:41:32 +01001086 case Primitive::kPrimNot: {
1087 Register value = locations->InAt(1).AsX86().AsCpuRegister();
1088 __ movl(Address(obj, offset), value);
Nicolas Geoffray1a43dd72014-07-17 15:15:34 +01001089 Label is_null;
1090 Register temp = locations->GetTemp(0).AsX86().AsCpuRegister();
1091 Register card = locations->GetTemp(1).AsX86().AsCpuRegister();
1092 __ testl(value, value);
1093 __ j(kEqual, &is_null);
1094 __ fs()->movl(card, Address::Absolute(Thread::CardTableOffset<kX86WordSize>().Int32Value()));
1095 __ movl(temp, obj);
1096 __ shrl(temp, Immediate(gc::accounting::CardTable::kCardShift));
1097 __ movb(Address(temp, card, TIMES_1, 0), locations->GetTemp(1).AsX86().AsByteRegister());
1098 __ Bind(&is_null);
Nicolas Geoffraye5038322014-07-04 09:41:32 +01001099 break;
1100 }
1101
1102 case Primitive::kPrimLong: {
1103 X86ManagedRegister value = locations->InAt(1).AsX86();
1104 __ movl(Address(obj, offset), value.AsRegisterPairLow());
1105 __ movl(Address(obj, kX86WordSize + offset), value.AsRegisterPairHigh());
1106 break;
1107 }
1108
1109 case Primitive::kPrimFloat:
1110 case Primitive::kPrimDouble:
1111 LOG(FATAL) << "Unimplemented register type " << field_type;
1112
1113 case Primitive::kPrimVoid:
1114 LOG(FATAL) << "Unreachable type " << field_type;
1115 }
1116}
1117
1118void LocationsBuilderX86::VisitInstanceFieldGet(HInstanceFieldGet* instruction) {
1119 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
1120 locations->SetInAt(0, Location::RequiresRegister());
1121 locations->SetOut(Location::RequiresRegister());
1122 instruction->SetLocations(locations);
1123}
1124
1125void InstructionCodeGeneratorX86::VisitInstanceFieldGet(HInstanceFieldGet* instruction) {
1126 LocationSummary* locations = instruction->GetLocations();
1127 Register obj = locations->InAt(0).AsX86().AsCpuRegister();
1128 uint32_t offset = instruction->GetFieldOffset().Uint32Value();
1129
1130 switch (instruction->GetType()) {
1131 case Primitive::kPrimBoolean: {
1132 Register out = locations->Out().AsX86().AsCpuRegister();
1133 __ movzxb(out, Address(obj, offset));
1134 break;
1135 }
1136
1137 case Primitive::kPrimByte: {
1138 Register out = locations->Out().AsX86().AsCpuRegister();
1139 __ movsxb(out, Address(obj, offset));
1140 break;
1141 }
1142
1143 case Primitive::kPrimShort: {
1144 Register out = locations->Out().AsX86().AsCpuRegister();
1145 __ movsxw(out, Address(obj, offset));
1146 break;
1147 }
1148
1149 case Primitive::kPrimChar: {
1150 Register out = locations->Out().AsX86().AsCpuRegister();
1151 __ movzxw(out, Address(obj, offset));
1152 break;
1153 }
1154
1155 case Primitive::kPrimInt:
1156 case Primitive::kPrimNot: {
1157 Register out = locations->Out().AsX86().AsCpuRegister();
1158 __ movl(out, Address(obj, offset));
1159 break;
1160 }
1161
1162 case Primitive::kPrimLong: {
1163 // TODO: support volatile.
1164 X86ManagedRegister out = locations->Out().AsX86();
1165 __ movl(out.AsRegisterPairLow(), Address(obj, offset));
1166 __ movl(out.AsRegisterPairHigh(), Address(obj, kX86WordSize + offset));
1167 break;
1168 }
1169
1170 case Primitive::kPrimFloat:
1171 case Primitive::kPrimDouble:
1172 LOG(FATAL) << "Unimplemented register type " << instruction->GetType();
1173
1174 case Primitive::kPrimVoid:
1175 LOG(FATAL) << "Unreachable type " << instruction->GetType();
1176 }
1177}
1178
1179void LocationsBuilderX86::VisitNullCheck(HNullCheck* instruction) {
1180 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
1181 locations->SetInAt(0, Location::Any());
1182 // TODO: Have a normalization phase that makes this instruction never used.
1183 locations->SetOut(Location::SameAsFirstInput());
1184 instruction->SetLocations(locations);
1185}
1186
1187void InstructionCodeGeneratorX86::VisitNullCheck(HNullCheck* instruction) {
1188 SlowPathCode* slow_path =
1189 new (GetGraph()->GetArena()) NullCheckSlowPathX86(instruction->GetDexPc());
1190 codegen_->AddSlowPath(slow_path);
1191
1192 LocationSummary* locations = instruction->GetLocations();
1193 Location obj = locations->InAt(0);
1194 DCHECK(obj.Equals(locations->Out()));
1195
1196 if (obj.IsRegister()) {
1197 __ cmpl(obj.AsX86().AsCpuRegister(), Immediate(0));
1198 } else {
1199 DCHECK(locations->InAt(0).IsStackSlot());
1200 __ cmpl(Address(ESP, obj.GetStackIndex()), Immediate(0));
1201 }
1202 __ j(kEqual, slow_path->GetEntryLabel());
1203}
1204
1205void LocationsBuilderX86::VisitTemporary(HTemporary* temp) {
1206 temp->SetLocations(nullptr);
1207}
1208
1209void InstructionCodeGeneratorX86::VisitTemporary(HTemporary* temp) {
1210 // Nothing to do, this is driven by the code generator.
1211}
1212
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01001213void LocationsBuilderX86::VisitParallelMove(HParallelMove* instruction) {
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001214 LOG(FATAL) << "Unreachable";
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01001215}
1216
1217void InstructionCodeGeneratorX86::VisitParallelMove(HParallelMove* instruction) {
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001218 codegen_->GetMoveResolver()->EmitNativeCode(instruction);
1219}
1220
1221X86Assembler* ParallelMoveResolverX86::GetAssembler() const {
1222 return codegen_->GetAssembler();
1223}
1224
1225void ParallelMoveResolverX86::MoveMemoryToMemory(int dst, int src) {
1226 ScratchRegisterScope ensure_scratch(
Nicolas Geoffraye27f31a2014-06-12 17:53:14 +01001227 this, kNoRegister, EAX, codegen_->GetNumberOfCoreRegisters());
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001228 int stack_offset = ensure_scratch.IsSpilled() ? kX86WordSize : 0;
1229 __ movl(static_cast<Register>(ensure_scratch.GetRegister()), Address(ESP, src + stack_offset));
1230 __ movl(Address(ESP, dst + stack_offset), static_cast<Register>(ensure_scratch.GetRegister()));
1231}
1232
1233void ParallelMoveResolverX86::EmitMove(size_t index) {
1234 MoveOperands* move = moves_.Get(index);
1235 Location source = move->GetSource();
1236 Location destination = move->GetDestination();
1237
1238 if (source.IsRegister()) {
1239 if (destination.IsRegister()) {
1240 __ movl(destination.AsX86().AsCpuRegister(), source.AsX86().AsCpuRegister());
1241 } else {
1242 DCHECK(destination.IsStackSlot());
1243 __ movl(Address(ESP, destination.GetStackIndex()), source.AsX86().AsCpuRegister());
1244 }
1245 } else if (source.IsStackSlot()) {
1246 if (destination.IsRegister()) {
1247 __ movl(destination.AsX86().AsCpuRegister(), Address(ESP, source.GetStackIndex()));
1248 } else {
1249 DCHECK(destination.IsStackSlot());
1250 MoveMemoryToMemory(destination.GetStackIndex(),
1251 source.GetStackIndex());
1252 }
Nicolas Geoffray96f89a22014-07-11 10:57:49 +01001253 } else if (source.IsConstant()) {
1254 HIntConstant* instruction = source.GetConstant()->AsIntConstant();
1255 Immediate imm(instruction->AsIntConstant()->GetValue());
1256 if (destination.IsRegister()) {
1257 __ movl(destination.AsX86().AsCpuRegister(), imm);
1258 } else {
1259 __ movl(Address(ESP, destination.GetStackIndex()), imm);
1260 }
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001261 } else {
1262 LOG(FATAL) << "Unimplemented";
1263 }
1264}
1265
1266void ParallelMoveResolverX86::Exchange(Register reg, int mem) {
Nicolas Geoffraye27f31a2014-06-12 17:53:14 +01001267 Register suggested_scratch = reg == EAX ? EBX : EAX;
1268 ScratchRegisterScope ensure_scratch(
1269 this, reg, suggested_scratch, codegen_->GetNumberOfCoreRegisters());
1270
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001271 int stack_offset = ensure_scratch.IsSpilled() ? kX86WordSize : 0;
1272 __ movl(static_cast<Register>(ensure_scratch.GetRegister()), Address(ESP, mem + stack_offset));
1273 __ movl(Address(ESP, mem + stack_offset), reg);
1274 __ movl(reg, static_cast<Register>(ensure_scratch.GetRegister()));
1275}
1276
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001277void ParallelMoveResolverX86::Exchange(int mem1, int mem2) {
1278 ScratchRegisterScope ensure_scratch1(
Nicolas Geoffraye27f31a2014-06-12 17:53:14 +01001279 this, kNoRegister, EAX, codegen_->GetNumberOfCoreRegisters());
1280
1281 Register suggested_scratch = ensure_scratch1.GetRegister() == EAX ? EBX : EAX;
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001282 ScratchRegisterScope ensure_scratch2(
Nicolas Geoffraye27f31a2014-06-12 17:53:14 +01001283 this, ensure_scratch1.GetRegister(), suggested_scratch, codegen_->GetNumberOfCoreRegisters());
1284
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001285 int stack_offset = ensure_scratch1.IsSpilled() ? kX86WordSize : 0;
1286 stack_offset += ensure_scratch2.IsSpilled() ? kX86WordSize : 0;
1287 __ movl(static_cast<Register>(ensure_scratch1.GetRegister()), Address(ESP, mem1 + stack_offset));
1288 __ movl(static_cast<Register>(ensure_scratch2.GetRegister()), Address(ESP, mem2 + stack_offset));
1289 __ movl(Address(ESP, mem2 + stack_offset), static_cast<Register>(ensure_scratch1.GetRegister()));
1290 __ movl(Address(ESP, mem1 + stack_offset), static_cast<Register>(ensure_scratch2.GetRegister()));
1291}
1292
1293void ParallelMoveResolverX86::EmitSwap(size_t index) {
1294 MoveOperands* move = moves_.Get(index);
1295 Location source = move->GetSource();
1296 Location destination = move->GetDestination();
1297
1298 if (source.IsRegister() && destination.IsRegister()) {
1299 __ xchgl(destination.AsX86().AsCpuRegister(), source.AsX86().AsCpuRegister());
1300 } else if (source.IsRegister() && destination.IsStackSlot()) {
1301 Exchange(source.AsX86().AsCpuRegister(), destination.GetStackIndex());
1302 } else if (source.IsStackSlot() && destination.IsRegister()) {
1303 Exchange(destination.AsX86().AsCpuRegister(), source.GetStackIndex());
1304 } else if (source.IsStackSlot() && destination.IsStackSlot()) {
1305 Exchange(destination.GetStackIndex(), source.GetStackIndex());
1306 } else {
1307 LOG(FATAL) << "Unimplemented";
1308 }
1309}
1310
1311void ParallelMoveResolverX86::SpillScratch(int reg) {
1312 __ pushl(static_cast<Register>(reg));
1313}
1314
1315void ParallelMoveResolverX86::RestoreScratch(int reg) {
1316 __ popl(static_cast<Register>(reg));
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01001317}
1318
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +00001319} // namespace x86
1320} // namespace art